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
JavaScript
;
/**
* 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