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.

260 lines 12.4 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 __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExTester = exports.NODEJS_VERSION_MAX = exports.VSCODE_VERSION_MAX = exports.VSCODE_VERSION_MIN = exports.DEFAULT_STORAGE_FOLDER = exports.DEFAULT_SETUP_OPTIONS = exports.ReleaseQuality = void 0; exports.loadCodeVersion = loadCodeVersion; const codeUtil_1 = require("./util/codeUtil"); Object.defineProperty(exports, "ReleaseQuality", { enumerable: true, get: function () { return codeUtil_1.ReleaseQuality; } }); const driverUtil_1 = require("./util/driverUtil"); const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const os = __importStar(require("os")); const url_1 = require("url"); const package_json_1 = __importDefault(require("../package.json")); const glob_1 = require("glob"); __exportStar(require("./browser"), exports); __exportStar(require("./suite/mochaHooks"), exports); __exportStar(require("@redhat-developer/page-objects"), exports); exports.DEFAULT_SETUP_OPTIONS = { vscodeVersion: 'latest', installDependencies: false, }; exports.DEFAULT_STORAGE_FOLDER = process.env.TEST_RESOURCES ? process.env.TEST_RESOURCES : path.join(os.tmpdir(), 'test-resources'); exports.VSCODE_VERSION_MIN = package_json_1.default.supportedVersions['vscode-min']; exports.VSCODE_VERSION_MAX = package_json_1.default.supportedVersions['vscode-max']; /** * The latest version with automated tests */ exports.NODEJS_VERSION_MAX = package_json_1.default.supportedVersions.nodejs; /** * ExTester */ class ExTester { code; chrome; constructor(storageFolder = exports.DEFAULT_STORAGE_FOLDER, releaseType = codeUtil_1.ReleaseQuality.Stable, extensionsDir, coverage) { this.code = new codeUtil_1.CodeUtil(storageFolder, releaseType, extensionsDir, coverage); this.chrome = new driverUtil_1.DriverUtil(storageFolder); if (process.versions.node.slice(0, 2) > exports.NODEJS_VERSION_MAX) { console.log('\x1b[33m%s\x1b[0m', `\nWarning: You are using the untested NodeJS version '${process.versions.node}'. The latest supported version is '${exports.NODEJS_VERSION_MAX}.x.x'.\n\t We recommend to use tested version to have ExTester working properly.\n\n`); } } /** * Download VS Code of given version and release quality stream * @param version version to download, default latest * @param noCache whether to skip using cached version */ async downloadCode(version = 'latest', noCache = false) { return await this.code.downloadVSCode(loadCodeVersion(version), noCache); } /** * Install the extension into the test instance of VS Code * @param vsixFile path to extension .vsix file. If not set, default vsce path will be used * @param useYarn when true run `vsce package` with the `--yarn` flag */ async installVsix({ vsixFile, useYarn, installDependencies, } = {}) { let target = vsixFile; if (vsixFile) { try { // Attempt to handle vsixFile as a URL const uri = new url_1.URL(vsixFile); target = await this.code.downloadExtension(uri.toString()); this.code.installExtension(target); } catch (urlError) { //Convert Windows-style paths to Unix-style for glob const normalizedPattern = vsixFile.replace(/\\/g, '/'); const vsixFiles = (0, glob_1.globSync)(normalizedPattern); if (vsixFiles.length === 0) { throw new Error(`No VSIX files found matching pattern: ${vsixFile}`); } for (const file of vsixFiles) { try { const normalizedPath = path.normalize(file); const target = await this.processVsixFile(normalizedPath); this.code.installExtension(target); } catch (error) { console.error(`Error installing ${file}:`, error); } } } } else { await this.code.packageExtension(useYarn); this.code.installExtension(target); } if (installDependencies) { this.code.installDependencies(); } } /** * Processes a given VSIX file path or URL to validate and return the appropriate value. * * @param filePath The file path or URL of the VSIX file to process. * @returns Resolves to the processed file path or base name if the input is a valid URL. */ async processVsixFile(filePath) { console.log(`Processing VSIX file: ${filePath}`); try { const uri = new url_1.URL(filePath); console.log(`Parsed URI: ${uri}`); if (!(process.platform === 'win32' && /^[a-zA-Z]:/.test(uri.protocol))) { return path.basename(filePath); } } catch { console.log(`File is not a valid URL. Checking existence: ${filePath}`); await fs.stat(filePath).catch(() => { throw new Error(`File ${filePath} does not exist.`); }); } return filePath; } /** * Install an extension from VS Code marketplace into the test instance * @param id id of the extension to install */ async installFromMarketplace(id, preRelease) { return this.code.installExtension(undefined, id, preRelease); } /** * Download the matching chromedriver for a given VS Code version * @param vscodeVersion selected version of VS Code, default latest * @param noCache whether to skip using cached version */ async downloadChromeDriver(vscodeVersion = 'latest', noCache = false) { const chromiumVersion = await this.code.getChromiumVersion(loadCodeVersion(vscodeVersion)); return await this.chrome.downloadChromeDriverForChromiumVersion(chromiumVersion, noCache); } /** * Performs all necessary setup: getting VS Code + ChromeDriver * and packaging/installing extension into the test instance * * @param options Additional options for setting up the tests * @param offline whether to run in offline mode * @param cleanup whether to clean up after tests * @param noCache whether to skip using cached version */ async setupRequirements(options = exports.DEFAULT_SETUP_OPTIONS, offline = false, cleanup = false) { const { useYarn, vscodeVersion, installDependencies, noCache } = options; const vscodeParsedVersion = loadCodeVersion(vscodeVersion); if (!offline) { await this.downloadCode(vscodeParsedVersion, noCache); await this.downloadChromeDriver(vscodeParsedVersion, noCache); } else { console.log('Attempting Setup in offline mode'); const expectedChromeVersion = this.code.checkOfflineRequirements().split('.')[0]; const actualChromeVersion = (await this.chrome.checkDriverVersionOffline(vscodeParsedVersion)).split('.')[0]; if (expectedChromeVersion !== actualChromeVersion) { console.log('\x1b[33m%s\x1b[0m', `WARNING: Local copy of VS Code runs Chromium version ${expectedChromeVersion}, the installed ChromeDriver is version ${actualChromeVersion}.`); console.log(`Attempting with ChromeDriver ${actualChromeVersion} anyway. Tests may experience issues due to version mismatch.`); } } if (!this.code.coverageEnabled || cleanup) { await this.installVsix({ useYarn }); } if (installDependencies && !offline) { this.code.installDependencies(); } } /** * Performs requirements setup and runs extension tests * * @param testFilesPattern glob pattern(s) for test files to run * @param vscodeVersion version of VS Code to test against, defaults to latest * @param setupOptions Additional options for setting up the tests * @param runOptions Additional options for running the tests * * @returns Promise resolving to the mocha process exit code - 0 for no failures, 1 otherwise */ async setupAndRunTests(testFilesPattern, vscodeVersion = 'latest', setupOptions = exports.DEFAULT_SETUP_OPTIONS, runOptions = codeUtil_1.DEFAULT_RUN_OPTIONS) { await this.setupRequirements({ ...setupOptions, vscodeVersion }, runOptions.offline, runOptions.cleanup); return await this.runTests(testFilesPattern, { ...runOptions, vscodeVersion, }); } /** * Runs the selected test files in VS Code using mocha and webdriver * @param testFilesPattern glob pattern(s) for selected test files * @param runOptions Additional options for running the tests * * @returns Promise resolving to the mocha process exit code - 0 for no failures, 1 otherwise */ async runTests(testFilesPattern, runOptions = codeUtil_1.DEFAULT_RUN_OPTIONS) { runOptions.vscodeVersion = loadCodeVersion(runOptions.vscodeVersion); const patterns = typeof testFilesPattern === 'string' ? [testFilesPattern] : testFilesPattern; return await this.code.runTests(patterns, runOptions); } } exports.ExTester = ExTester; function loadCodeVersion(version) { const codeVersion = process.env.CODE_VERSION ? process.env.CODE_VERSION : version; if (codeVersion !== undefined) { if (codeVersion.toLowerCase() === 'max') { return exports.VSCODE_VERSION_MAX; } if (codeVersion.toLowerCase() === 'min') { return exports.VSCODE_VERSION_MIN; } return codeVersion; } return 'latest'; } //# sourceMappingURL=extester.js.map