UNPKG

vscode-extension-tester

Version:

ExTester is a package that is designed to help you run UI tests for your Visual Studio Code extensions using selenium-webdriver.

224 lines 9.15 kB
"use strict"; /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License", destination); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VSRunner = void 0; const browser_1 = require("../browser"); const fs = __importStar(require("fs-extra")); const mocha_1 = __importDefault(require("mocha")); const glob_1 = require("glob"); const path = __importStar(require("path")); const yaml = __importStar(require("js-yaml")); const sanitize_filename_1 = __importDefault(require("sanitize-filename")); const selenium_webdriver_1 = require("selenium-webdriver"); const os = __importStar(require("os")); const coverage_1 = require("../util/coverage"); /** * Mocha runner wrapper */ class VSRunner { mocha; chromeBin; customSettings; codeVersion; cleanup; tmpLink = path.join(os.tmpdir(), 'extest-code'); releaseType; constructor(bin, codeVersion, customSettings = {}, cleanup = false, releaseType, config) { const conf = this.loadConfig(config); this.mocha = new mocha_1.default(conf); this.chromeBin = bin; this.customSettings = customSettings; this.codeVersion = codeVersion; this.cleanup = cleanup; this.releaseType = releaseType; } /** * Set up mocha suite, add vscode instance handling, run tests * @param testFilesPattern glob pattern of test files to run * @param logLevel The logging level for the Webdriver * @return The exit code of the mocha process */ runTests(testFilesPattern, code, logLevel = selenium_webdriver_1.logging.Level.INFO, resources) { return new Promise((resolve) => { const self = this; const browser = new browser_1.VSBrowser(this.codeVersion, this.releaseType, this.customSettings, logLevel); let coverage; const testFiles = new Set(); for (const pattern of testFilesPattern) { const universalPattern = pattern.replace(/'/g, ''); (0, glob_1.globSync)(universalPattern) .reverse() .forEach((val) => testFiles.add(val)); } testFiles.forEach((file) => this.mocha.addFile(file)); this.mocha.suite.afterEach(async function () { if (this.currentTest && this.currentTest.state !== 'passed') { try { const filename = (0, sanitize_filename_1.default)(this.currentTest.fullTitle()); await browser.takeScreenshot(filename); } catch (err) { console.log('Screenshot capture failed.', err); } } }); this.mocha.suite.beforeAll(async function () { this.timeout(180000); if (code.coverageEnabled) { coverage = new coverage_1.Coverage(); await coverage.loadConfig(); process.env.NODE_V8_COVERAGE = coverage?.targetDir; } const start = Date.now(); const binPath = process.platform === 'darwin' ? await self.createShortcut(code.getCodeFolder(), self.tmpLink) : self.chromeBin; await browser.start(binPath); await browser.openResources(...resources); await browser.waitForWorkbench(); console.log(`Browser ready in ${Date.now() - start} ms`); console.log('Launching tests...'); }); this.mocha.suite.afterAll(async function () { this.timeout(180000); await browser.quit(); if (process.platform === 'darwin') { if (await fs.pathExists(self.tmpLink)) { try { fs.unlinkSync(self.tmpLink); } catch (err) { console.log(err); } } } if (code.coverageEnabled) { await coverage?.write(); } code.uninstallExtension(self.cleanup); }); this.mocha.run((failures) => { process.exitCode = failures ? 1 : 0; if (process.exitCode) { console.log('\x1b[33m%s\x1b[0m', `INFO: Screenshots of failures can be found in: ${browser.getScreenshotsDir()}\n`); } resolve(process.exitCode); }); }); } async createShortcut(src, dest) { try { await fs.ensureSymlink(src, dest, 'dir'); } catch (err) { return this.chromeBin; } const dir = path.parse(src); const segments = this.chromeBin.split(path.sep); const newSegments = dest.split(path.sep); let found = false; for (const segment of segments) { if (!found) { found = segment === dir.base; } else { newSegments.push(segment); } } return path.join(dir.root, ...newSegments); } loadConfig(config) { const defaultFiles = ['.mocharc.js', '.mocharc.json', '.mocharc.yml', '.mocharc.yaml']; let conf = {}; let file = config; if (!config) { file = path.resolve('.'); for (const defFile of defaultFiles) { if (fs.existsSync(path.join(file, defFile))) { file = path.join(file, defFile); break; } } } if (file && fs.existsSync(file) && fs.statSync(file).isFile()) { console.log(`Loading mocha configuration from ${file}`); if (/\.(yml|yaml)$/.test(file)) { try { conf = yaml.load(fs.readFileSync(file, 'utf-8')); } catch (err) { console.log('Invalid mocha configuration file, will be ignored'); } } else if (/\.(js|json)$/.test(file)) { try { conf = require(path.resolve(file)); } catch (err) { console.log('Invalid mocha configuration file, will be ignored'); } } else { console.log('Unsupported mocha configuration file extension, make sure to use .js, .json, .yml or .yaml file'); } } if (process.env.MOCHA_GREP) { conf.grep = process.env.MOCHA_GREP; } if (process.env.MOCHA_INVERT) { conf.invert = process.env.MOCHA_INVERT === 'true'; } return conf; } } exports.VSRunner = VSRunner; //# sourceMappingURL=runner.js.map