@vscode/test-electron
Advanced tools
Comparing version 2.2.3 to 2.3.0
# Changelog | ||
### 2.3.0 | 2022-02-27 | ||
- Automatically use the most recent version matching `engines.vscode` in extensions' package.json | ||
- Allow insiders `version`s to be specified, such as `version: "1.76.0-insider"` | ||
- Reduce the likelihood of 'broken' installations on interrupted downloads | ||
- Remove dependency on outdated `unzipper` module | ||
### 2.2.4 | 2022-02-19 | ||
- Use existing downloads if internet is inaccessible | ||
### 2.2.3 | 2022-01-30 | ||
@@ -120,3 +131,3 @@ | ||
- Add `resolveCliPathFromVSCodeExecutablePath` that would resolve `vscodeExecutablePath` to VS Code CLI path, which can be used | ||
for extension management features such as `--install-extension` and `--uninstall-extension`. [#31](https://github.com/microsoft/vscode-test/issues/31). | ||
for extension management features such as `--install-extension` and `--uninstall-extension`. [#31](https://github.com/microsoft/vscode-test/issues/31). | ||
@@ -144,9 +155,9 @@ ### 1.0.2 | 2019-07-17 | ||
- Updated API: | ||
- One single set of options. | ||
- `extensionPath` => `extensionDevelopmentPath` to align with VS Code launch flags | ||
- `testRunnerPath` => `extensionTestsPath` to align with VS Code launch flags | ||
- `testRunnerEnv` => `extensionTestsEnv` to align with VS Code launch flags | ||
- `additionalLaunchArgs` => `launchArgs` | ||
- `testWorkspace` removed. Pass path to file/folder/workspace as first argument to `launchArgs` instead. | ||
- `locale` removed. Pass `--locale` to `launchArgs` instead. | ||
- One single set of options. | ||
- `extensionPath` => `extensionDevelopmentPath` to align with VS Code launch flags | ||
- `testRunnerPath` => `extensionTestsPath` to align with VS Code launch flags | ||
- `testRunnerEnv` => `extensionTestsEnv` to align with VS Code launch flags | ||
- `additionalLaunchArgs` => `launchArgs` | ||
- `testWorkspace` removed. Pass path to file/folder/workspace as first argument to `launchArgs` instead. | ||
- `locale` removed. Pass `--locale` to `launchArgs` instead. | ||
@@ -164,3 +175,3 @@ ### 0.4.3 | 2019-05-30 | ||
- Fix Linux crash because `testRunnerEnv` is not merged with `process.env` for spawning the | ||
testing process. [#14](https://github.com/Microsoft/vscode-test/issues/14c). | ||
testing process. [#14](https://github.com/Microsoft/vscode-test/issues/14c). | ||
@@ -167,0 +178,0 @@ ### 0.4.0 | 2019-04-18 |
import { ProgressReporter } from './progress'; | ||
interface IFetchStableOptions { | ||
timeout: number; | ||
cachePath: string; | ||
platform: string; | ||
} | ||
interface IFetchInferredOptions extends IFetchStableOptions { | ||
extensionsDevelopmentPath?: string | string[]; | ||
} | ||
export declare const fetchStableVersions: (timeout: number) => Promise<string[]>; | ||
export declare const fetchInsiderVersions: (timeout: number) => Promise<string[]>; | ||
export declare function fetchTargetInferredVersion(options: IFetchInferredOptions): Promise<string>; | ||
/** | ||
@@ -6,3 +17,3 @@ * Adapted from https://github.com/microsoft/TypeScript/issues/29729 | ||
*/ | ||
declare type StringLiteralUnion<T extends U, U = string> = T | (U & {}); | ||
declare type StringLiteralUnion<T extends string> = T | (string & {}); | ||
export declare type DownloadVersion = StringLiteralUnion<'insiders' | 'stable'>; | ||
@@ -14,2 +25,3 @@ export declare type DownloadPlatform = StringLiteralUnion<'darwin' | 'darwin-arm64' | 'win32-archive' | 'win32-x64-archive' | 'linux-x64' | 'linux-arm64' | 'linux-armhf'>; | ||
readonly platform: DownloadPlatform; | ||
readonly extensionDevelopmentPath?: string | string[]; | ||
readonly reporter?: ProgressReporter; | ||
@@ -16,0 +28,0 @@ readonly extractSync?: boolean; |
@@ -7,3 +7,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.downloadAndUnzipVSCode = exports.download = exports.defaultCachePath = void 0; | ||
exports.downloadAndUnzipVSCode = exports.download = exports.defaultCachePath = exports.fetchTargetInferredVersion = exports.fetchInsiderVersions = exports.fetchStableVersions = void 0; | ||
const cp = require("child_process"); | ||
@@ -14,27 +14,105 @@ const fs = require("fs"); | ||
const stream_1 = require("stream"); | ||
const unzipper_1 = require("unzipper"); | ||
const util_1 = require("util"); | ||
const del = require("./del"); | ||
const progress_1 = require("./progress"); | ||
const request = require("./request"); | ||
const semver = require("semver"); | ||
const util_2 = require("./util"); | ||
const extensionRoot = process.cwd(); | ||
const pipelineAsync = util_1.promisify(stream_1.pipeline); | ||
const vscodeStableReleasesAPI = `https://update.code.visualstudio.com/api/releases/stable`; | ||
const vscodeInsiderReleasesAPI = `https://update.code.visualstudio.com/api/releases/insider`; | ||
const vscodeInsiderCommitsAPI = (platform) => `https://update.code.visualstudio.com/api/commits/insider/${platform}`; | ||
const downloadDirNameFormat = /^vscode-(?<platform>[a-z]+)-(?<version>[0-9.]+)$/; | ||
const makeDownloadDirName = (platform, version) => `vscode-${platform}-${version}`; | ||
const DOWNLOAD_ATTEMPTS = 3; | ||
async function fetchLatestStableVersion(timeout) { | ||
const versions = await request.getJSON(vscodeStableReleasesAPI, timeout); | ||
if (!versions || !Array.isArray(versions) || !versions[0]) { | ||
throw Error('Failed to get latest VS Code version'); | ||
exports.fetchStableVersions = util_2.onceWithoutRejections((timeout) => request.getJSON(vscodeStableReleasesAPI, timeout)); | ||
exports.fetchInsiderVersions = util_2.onceWithoutRejections((timeout) => request.getJSON(vscodeInsiderReleasesAPI, timeout)); | ||
/** | ||
* Returns the stable version to run tests against. Attempts to get the latest | ||
* version from the update sverice, but falls back to local installs if | ||
* not available (e.g. if the machine is offline). | ||
*/ | ||
async function fetchTargetStableVersion({ timeout, cachePath, platform }) { | ||
try { | ||
const versions = await exports.fetchStableVersions(timeout); | ||
return versions[0]; | ||
} | ||
return versions[0]; | ||
catch (e) { | ||
return fallbackToLocalEntries(cachePath, platform, e); | ||
} | ||
} | ||
async function fetchTargetInferredVersion(options) { | ||
if (!options.extensionsDevelopmentPath) { | ||
return fetchTargetStableVersion(options); | ||
} | ||
// load all engines versions from all development paths. Then, get the latest | ||
// stable version (or, latest Insiders version) that satisfies all | ||
// `engines.vscode` constraints. | ||
const extPaths = Array.isArray(options.extensionsDevelopmentPath) | ||
? options.extensionsDevelopmentPath | ||
: [options.extensionsDevelopmentPath]; | ||
const maybeExtVersions = await Promise.all(extPaths.map(getEngineVersionFromExtension)); | ||
const extVersions = maybeExtVersions.filter(util_2.isDefined); | ||
const matches = (v) => !extVersions.some((range) => !semver.satisfies(v, range, { includePrerelease: true })); | ||
try { | ||
const stable = await exports.fetchStableVersions(options.timeout); | ||
const found1 = stable.find(matches); | ||
if (found1) { | ||
return found1; | ||
} | ||
const insiders = await exports.fetchInsiderVersions(options.timeout); | ||
const found2 = insiders.find(matches); | ||
if (found2) { | ||
return found2; | ||
} | ||
const v = extVersions.join(', '); | ||
console.warn(`No version of VS Code satisfies all extension engine constraints (${v}). Falling back to stable.`); | ||
return stable[0]; // 🤷 | ||
} | ||
catch (e) { | ||
return fallbackToLocalEntries(options.cachePath, options.platform, e); | ||
} | ||
} | ||
exports.fetchTargetInferredVersion = fetchTargetInferredVersion; | ||
async function getEngineVersionFromExtension(extensionPath) { | ||
var _a; | ||
try { | ||
const packageContents = await fs.promises.readFile(path.join(extensionPath, 'package.json'), 'utf8'); | ||
const packageJson = JSON.parse(packageContents); | ||
return (_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.engines) === null || _a === void 0 ? void 0 : _a.vscode; | ||
} | ||
catch { | ||
return undefined; | ||
} | ||
} | ||
async function fallbackToLocalEntries(cachePath, platform, fromError) { | ||
const entries = await fs.promises.readdir(cachePath).catch(() => []); | ||
const [fallbackTo] = entries | ||
.map((e) => downloadDirNameFormat.exec(e)) | ||
.filter(util_2.isDefined) | ||
.filter((e) => e.groups.platform === platform) | ||
.map((e) => e.groups.version) | ||
.sort((a, b) => Number(b) - Number(a)); | ||
if (fallbackTo) { | ||
console.warn(`Error retrieving VS Code versions, using already-installed version ${fallbackTo}`, fromError); | ||
return fallbackTo; | ||
} | ||
throw fromError; | ||
} | ||
async function isValidVersion(version, platform, timeout) { | ||
if (version === 'insiders') { | ||
if (version === 'insiders' || version === 'stable') { | ||
return true; | ||
} | ||
const stableVersionNumbers = await request.getJSON(vscodeStableReleasesAPI, timeout); | ||
if (stableVersionNumbers.includes(version)) { | ||
return true; | ||
if (util_2.isStableVersionIdentifier(version)) { | ||
const stableVersionNumbers = await exports.fetchStableVersions(timeout); | ||
if (stableVersionNumbers.includes(version)) { | ||
return true; | ||
} | ||
} | ||
if (util_2.isInsiderVersionIdentifier(version)) { | ||
const insiderVersionNumbers = await exports.fetchInsiderVersions(timeout); | ||
if (insiderVersionNumbers.includes(version)) { | ||
return true; | ||
} | ||
} | ||
const insiderCommits = await request.getJSON(vscodeInsiderCommitsAPI(platform), timeout); | ||
@@ -74,9 +152,19 @@ if (insiderCommits.includes(version)) { | ||
const timeoutCtrl = new request.TimeoutController(timeout); | ||
(_b = options.reporter) === null || _b === void 0 ? void 0 : _b.report({ stage: progress_1.ProgressReportStage.Downloading, url, bytesSoFar: 0, totalBytes }); | ||
(_b = options.reporter) === null || _b === void 0 ? void 0 : _b.report({ | ||
stage: progress_1.ProgressReportStage.Downloading, | ||
url, | ||
bytesSoFar: 0, | ||
totalBytes, | ||
}); | ||
let bytesSoFar = 0; | ||
download.on('data', chunk => { | ||
download.on('data', (chunk) => { | ||
var _a; | ||
bytesSoFar += chunk.length; | ||
timeoutCtrl.touch(); | ||
(_a = options.reporter) === null || _a === void 0 ? void 0 : _a.report({ stage: progress_1.ProgressReportStage.Downloading, url, bytesSoFar, totalBytes }); | ||
(_a = options.reporter) === null || _a === void 0 ? void 0 : _a.report({ | ||
stage: progress_1.ProgressReportStage.Downloading, | ||
url, | ||
bytesSoFar, | ||
totalBytes, | ||
}); | ||
}); | ||
@@ -86,3 +174,8 @@ download.on('end', () => { | ||
timeoutCtrl.dispose(); | ||
(_a = options.reporter) === null || _a === void 0 ? void 0 : _a.report({ stage: progress_1.ProgressReportStage.Downloading, url, bytesSoFar: totalBytes, totalBytes }); | ||
(_a = options.reporter) === null || _a === void 0 ? void 0 : _a.report({ | ||
stage: progress_1.ProgressReportStage.Downloading, | ||
url, | ||
bytesSoFar: totalBytes, | ||
totalBytes, | ||
}); | ||
}); | ||
@@ -101,39 +194,36 @@ timeoutCtrl.signal.addEventListener('abort', () => { | ||
if (format === 'zip') { | ||
// note: this used to use Expand-Archive, but this caused a failure | ||
// on longer file paths on windows. Instead use unzipper, which does | ||
// not have this limitation. | ||
// | ||
// However it has problems that prevent it working on OSX: | ||
// - https://github.com/ZJONSSON/node-unzipper/issues/216 (avoidable) | ||
// - https://github.com/ZJONSSON/node-unzipper/issues/115 (not avoidable) | ||
if (process.platform === 'win32' && extractSync) { | ||
try { | ||
await util_1.promisify(stream_1.pipeline)(stream, fs.createWriteStream(stagingFile)); | ||
reporter.report({ stage: progress_1.ProgressReportStage.ExtractingSynchonrously }); | ||
await spawnDecompressorChild('powershell.exe', [ | ||
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-NonInteractive', '-NoLogo', | ||
'-Command', `Microsoft.PowerShell.Archive\\Expand-Archive -Path "${stagingFile}" -DestinationPath "${extractDir}"` | ||
]); | ||
try { | ||
reporter.report({ stage: progress_1.ProgressReportStage.ExtractingSynchonrously }); | ||
// note: this used to use Expand-Archive, but this caused a failure | ||
// on longer file paths on windows. And we used to use the streaming | ||
// "unzipper", but the module was very outdated and a bit buggy. | ||
// Instead, use jszip. It's well-used and actually 8x faster than | ||
// Expand-Archive on my machine. | ||
if (process.platform === 'win32') { | ||
const [buffer, JSZip] = await Promise.all([util_2.streamToBuffer(stream), Promise.resolve().then(() => require('jszip'))]); | ||
const content = await JSZip.loadAsync(buffer); | ||
// extract file with jszip | ||
for (const filename of Object.keys(content.files)) { | ||
const file = content.files[filename]; | ||
const filepath = path.join(extractDir, filename); | ||
if (file.dir) { | ||
continue; | ||
} | ||
// vscode update zips are trusted, but check for zip slip anyway. | ||
if (!util_2.isSubdirectory(extractDir, filepath)) { | ||
throw new Error(`Invalid zip file: ${filename}`); | ||
} | ||
await fs.promises.mkdir(path.dirname(filepath), { recursive: true }); | ||
await pipelineAsync(file.nodeStream(), fs.createWriteStream(filepath)); | ||
} | ||
} | ||
finally { | ||
fs.unlink(stagingFile, () => undefined); | ||
else { | ||
// darwin or *nix sync | ||
await pipelineAsync(stream, fs.createWriteStream(stagingFile)); | ||
await spawnDecompressorChild('unzip', ['-q', stagingFile, '-d', extractDir]); | ||
} | ||
} | ||
else if (process.platform !== 'darwin' && !extractSync) { | ||
await new Promise((resolve, reject) => stream | ||
.on('error', reject) | ||
.pipe(unzipper_1.Extract({ path: extractDir })) | ||
.on('close', resolve) | ||
.on('error', reject)); | ||
finally { | ||
fs.unlink(stagingFile, () => undefined); | ||
} | ||
else { // darwin or *nix sync | ||
try { | ||
await util_1.promisify(stream_1.pipeline)(stream, fs.createWriteStream(stagingFile)); | ||
reporter.report({ stage: progress_1.ProgressReportStage.ExtractingSynchonrously }); | ||
await spawnDecompressorChild('unzip', ['-q', stagingFile, '-d', extractDir]); | ||
} | ||
finally { | ||
fs.unlink(stagingFile, () => undefined); | ||
} | ||
} | ||
} | ||
@@ -158,3 +248,3 @@ else { | ||
child.on('error', reject); | ||
child.on('exit', code => code === 0 ? resolve() : reject(new Error(`Failed to unzip archive, exited with ${code}`))); | ||
child.on('exit', (code) => code === 0 ? resolve() : reject(new Error(`Failed to unzip archive, exited with ${code}`))); | ||
}); | ||
@@ -170,14 +260,12 @@ } | ||
const { platform = util_2.systemDefaultPlatform, cachePath = exports.defaultCachePath, reporter = new progress_1.ConsoleReporter(process.stdout.isTTY), extractSync = false, timeout = 15000, } = options; | ||
if (version) { | ||
if (version === 'stable') { | ||
version = await fetchLatestStableVersion(timeout); | ||
} | ||
else { | ||
/** | ||
* Only validate version against server when no local download that matches version exists | ||
*/ | ||
if (!fs.existsSync(path.resolve(cachePath, `vscode-${platform}-${version}`))) { | ||
if (!(await isValidVersion(version, platform, timeout))) { | ||
throw Error(`Invalid version ${version}`); | ||
} | ||
if (version === 'stable') { | ||
version = await fetchTargetStableVersion({ timeout, cachePath, platform }); | ||
} | ||
else if (version) { | ||
/** | ||
* Only validate version against server when no local download that matches version exists | ||
*/ | ||
if (!fs.existsSync(path.resolve(cachePath, `vscode-${platform}-${version}`))) { | ||
if (!(await isValidVersion(version, platform, timeout))) { | ||
throw Error(`Invalid version ${version}`); | ||
} | ||
@@ -187,11 +275,18 @@ } | ||
else { | ||
version = await fetchLatestStableVersion(timeout); | ||
version = await fetchTargetInferredVersion({ | ||
timeout, | ||
cachePath, | ||
platform, | ||
extensionsDevelopmentPath: options.extensionDevelopmentPath, | ||
}); | ||
} | ||
reporter.report({ stage: progress_1.ProgressReportStage.ResolvedVersion, version }); | ||
const downloadedPath = path.resolve(cachePath, `vscode-${platform}-${version}`); | ||
const downloadedPath = path.resolve(cachePath, makeDownloadDirName(platform, version)); | ||
if (fs.existsSync(downloadedPath)) { | ||
if (version === 'insiders') { | ||
if (util_2.isInsiderVersionIdentifier(version)) { | ||
reporter.report({ stage: progress_1.ProgressReportStage.FetchingInsidersMetadata }); | ||
const { version: currentHash, date: currentDate } = util_2.insidersDownloadDirMetadata(downloadedPath, platform); | ||
const { version: latestHash, timestamp: latestTimestamp } = await util_2.getLatestInsidersMetadata(util_2.systemDefaultPlatform); | ||
const { version: latestHash, timestamp: latestTimestamp } = version === 'insiders' | ||
? await util_2.getLatestInsidersMetadata(util_2.systemDefaultPlatform) | ||
: await util_2.getInsidersVersionMetadata(util_2.systemDefaultPlatform, version); | ||
if (currentHash === latestHash) { | ||
@@ -211,3 +306,3 @@ reporter.report({ stage: progress_1.ProgressReportStage.FoundMatchingInstall, downloadedPath }); | ||
}); | ||
await del.rmdir(downloadedPath); | ||
await fs.promises.rm(downloadedPath, { force: true, recursive: true }); | ||
} | ||
@@ -231,4 +326,17 @@ catch (err) { | ||
try { | ||
const { stream, format } = await downloadVSCodeArchive({ version, platform, cachePath, reporter, timeout }); | ||
await unzipVSCode(reporter, downloadedPath, extractSync, stream, format); | ||
// Use a staging directory and rename after unzipping so partially- | ||
// downloaded/unzipped files aren't "stuck" being used. | ||
const downloadStaging = `${downloadedPath}.tmp`; | ||
await fs.promises.rm(downloadStaging, { recursive: true, force: true }); | ||
const { stream, format } = await downloadVSCodeArchive({ | ||
version, | ||
platform, | ||
cachePath, | ||
reporter, | ||
timeout, | ||
}); | ||
// important! do not put anything async here, since unzipVSCode will need | ||
// to start consuming the stream immediately. | ||
await unzipVSCode(reporter, downloadStaging, extractSync, stream, format); | ||
await fs.promises.rename(downloadStaging, downloadedPath); | ||
reporter.report({ stage: progress_1.ProgressReportStage.NewInstallComplete, downloadedPath }); | ||
@@ -239,3 +347,8 @@ break; | ||
if (i++ < DOWNLOAD_ATTEMPTS) { | ||
reporter.report({ stage: progress_1.ProgressReportStage.Retrying, attempt: i, error: error, totalAttempts: DOWNLOAD_ATTEMPTS }); | ||
reporter.report({ | ||
stage: progress_1.ProgressReportStage.Retrying, | ||
attempt: i, | ||
error: error, | ||
totalAttempts: DOWNLOAD_ATTEMPTS, | ||
}); | ||
} | ||
@@ -242,0 +355,0 @@ else { |
@@ -11,3 +11,11 @@ "use strict"; | ||
const util_1 = require("./util"); | ||
const platforms = ['darwin', 'darwin-arm64', 'win32-archive', 'win32-x64-archive', 'linux-x64', 'linux-arm64', 'linux-armhf']; | ||
const platforms = [ | ||
'darwin', | ||
'darwin-arm64', | ||
'win32-archive', | ||
'win32-x64-archive', | ||
'linux-x64', | ||
'linux-arm64', | ||
'linux-armhf', | ||
]; | ||
vitest_1.describe('sane downloads', () => { | ||
@@ -49,1 +57,63 @@ const testTempDir = path_1.join(os_1.tmpdir(), 'vscode-test-download'); | ||
}); | ||
vitest_1.describe('fetchTargetInferredVersion', () => { | ||
let stable; | ||
let insiders; | ||
let extensionsDevelopmentPath = path_1.join(os_1.tmpdir(), 'vscode-test-tmp-workspace'); | ||
vitest_1.beforeAll(async () => { | ||
[stable, insiders] = await Promise.all([download_1.fetchStableVersions(5000), download_1.fetchInsiderVersions(5000)]); | ||
}); | ||
vitest_1.afterEach(async () => { | ||
await fs_1.promises.rm(extensionsDevelopmentPath, { recursive: true, force: true }); | ||
}); | ||
const writeJSON = async (path, contents) => { | ||
const target = path_1.join(extensionsDevelopmentPath, path); | ||
await fs_1.promises.mkdir(path_1.dirname(target), { recursive: true }); | ||
await fs_1.promises.writeFile(target, JSON.stringify(contents)); | ||
}; | ||
const doFetch = (paths = ['./']) => download_1.fetchTargetInferredVersion({ | ||
cachePath: path_1.join(extensionsDevelopmentPath, '.cache'), | ||
platform: 'win32-archive', | ||
timeout: 5000, | ||
extensionsDevelopmentPath: paths.map((p) => path_1.join(extensionsDevelopmentPath, p)), | ||
}); | ||
vitest_1.test('matches stable if no workspace', async () => { | ||
const version = await doFetch(); | ||
vitest_1.expect(version).to.equal(stable[0]); | ||
}); | ||
vitest_1.test('matches stable by default', async () => { | ||
await writeJSON('package.json', {}); | ||
const version = await doFetch(); | ||
vitest_1.expect(version).to.equal(stable[0]); | ||
}); | ||
vitest_1.test('matches if stable is defined', async () => { | ||
await writeJSON('package.json', { engines: { vscode: '^1.50.0' } }); | ||
const version = await doFetch(); | ||
vitest_1.expect(version).to.equal(stable[0]); | ||
}); | ||
vitest_1.test('matches best', async () => { | ||
await writeJSON('package.json', { engines: { vscode: '<=1.60.5' } }); | ||
const version = await doFetch(); | ||
vitest_1.expect(version).to.equal('1.60.2'); | ||
}); | ||
vitest_1.test('matches multiple workspaces', async () => { | ||
await writeJSON('a/package.json', { engines: { vscode: '<=1.60.5' } }); | ||
await writeJSON('b/package.json', { engines: { vscode: '<=1.55.5' } }); | ||
const version = await doFetch(['a', 'b']); | ||
vitest_1.expect(version).to.equal('1.55.2'); | ||
}); | ||
vitest_1.test('matches insiders to better stable if there is one', async () => { | ||
await writeJSON('package.json', { engines: { vscode: '^1.60.0-insider' } }); | ||
const version = await doFetch(); | ||
vitest_1.expect(version).to.equal(stable[0]); | ||
}); | ||
vitest_1.test('matches current insiders', async () => { | ||
await writeJSON('package.json', { engines: { vscode: `^${insiders[0]}` } }); | ||
const version = await doFetch(); | ||
vitest_1.expect(version).to.equal(insiders[0]); | ||
}); | ||
vitest_1.test('matches insiders to exact', async () => { | ||
await writeJSON('package.json', { engines: { vscode: '1.60.0-insider' } }); | ||
const version = await doFetch(); | ||
vitest_1.expect(version).to.equal('1.60.0-insider'); | ||
}); | ||
}); |
@@ -28,6 +28,6 @@ "use strict"; | ||
'--disable-workspace-trust', | ||
'--extensionTestsPath=' + options.extensionTestsPath | ||
'--extensionTestsPath=' + options.extensionTestsPath, | ||
]; | ||
if (Array.isArray(options.extensionDevelopmentPath)) { | ||
args.push(...options.extensionDevelopmentPath.map(devPath => `--extensionDevelopmentPath=${devPath}`)); | ||
args.push(...options.extensionDevelopmentPath.map((devPath) => `--extensionDevelopmentPath=${devPath}`)); | ||
} | ||
@@ -59,3 +59,3 @@ else { | ||
function hasArg(argName, argList) { | ||
return argList.some(a => a === `--${argName}` || a.startsWith(`--${argName}=`)); | ||
return argList.some((a) => a === `--${argName}` || a.startsWith(`--${argName}=`)); | ||
} | ||
@@ -66,4 +66,4 @@ async function innerRunTests(executable, args, testRunnerEnv) { | ||
const cmd = cp.spawn(executable, args, { env: fullEnv }); | ||
cmd.stdout.on('data', d => process.stdout.write(d)); | ||
cmd.stderr.on('data', d => process.stderr.write(d)); | ||
cmd.stdout.on('data', (d) => process.stdout.write(d)); | ||
cmd.stderr.on('data', (d) => process.stderr.write(d)); | ||
cmd.on('error', function (data) { | ||
@@ -70,0 +70,0 @@ console.log('Test error: ' + data.toString()); |
@@ -6,2 +6,3 @@ /// <reference types="node" /> | ||
export declare let systemDefaultPlatform: DownloadPlatform; | ||
export declare function isInsiderVersionIdentifier(version: string): boolean; | ||
export declare function isStableVersionIdentifier(version: string): boolean; | ||
@@ -26,2 +27,3 @@ export declare function getVSCodeDownloadUrl(version: string, platform?: DownloadPlatform): string; | ||
} | ||
export declare function getInsidersVersionMetadata(platform: string, version: string): Promise<IUpdateMetadata>; | ||
export declare function getLatestInsidersMetadata(platform: string): Promise<IUpdateMetadata>; | ||
@@ -52,1 +54,12 @@ /** | ||
export declare function resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath: string, options?: Pick<TestOptions, 'reuseMachineInstall' | 'platform'>): string[]; | ||
/** Predicates whether arg is undefined or null */ | ||
export declare function isDefined<T>(arg: T | undefined | null): arg is T; | ||
/** Gets a Buffer from a Node.js stream */ | ||
export declare function streamToBuffer(readable: NodeJS.ReadableStream): Promise<Buffer>; | ||
/** Gets whether child is a subdirectory of the parent */ | ||
export declare function isSubdirectory(parent: string, child: string): boolean; | ||
/** | ||
* Wraps a function so that it's called once, and never again, memoizing | ||
* the result unless it rejects. | ||
*/ | ||
export declare function onceWithoutRejections<T, Args extends unknown[]>(fn: (...args: Args) => Promise<T>): (...args: Args) => Promise<T>; |
@@ -7,3 +7,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.resolveCliArgsFromVSCodeExecutablePath = exports.resolveCliPathFromVSCodeExecutablePath = exports.getLatestInsidersMetadata = exports.insidersDownloadDirMetadata = exports.insidersDownloadDirToExecutablePath = exports.downloadDirToExecutablePath = exports.urlToOptions = exports.getVSCodeDownloadUrl = exports.isStableVersionIdentifier = exports.systemDefaultPlatform = void 0; | ||
exports.onceWithoutRejections = exports.isSubdirectory = exports.streamToBuffer = exports.isDefined = exports.resolveCliArgsFromVSCodeExecutablePath = exports.resolveCliPathFromVSCodeExecutablePath = exports.getLatestInsidersMetadata = exports.getInsidersVersionMetadata = exports.insidersDownloadDirMetadata = exports.insidersDownloadDirToExecutablePath = exports.downloadDirToExecutablePath = exports.urlToOptions = exports.getVSCodeDownloadUrl = exports.isStableVersionIdentifier = exports.isInsiderVersionIdentifier = exports.systemDefaultPlatform = void 0; | ||
const path = require("path"); | ||
@@ -23,17 +23,19 @@ const url_1 = require("url"); | ||
case 'win32': | ||
exports.systemDefaultPlatform = process.arch === 'arm64' | ||
? 'win32-arm64-archive' | ||
: process.arch === 'ia32' | ||
? 'win32-archive' | ||
: 'win32-x64-archive'; | ||
exports.systemDefaultPlatform = | ||
process.arch === 'arm64' | ||
? 'win32-arm64-archive' | ||
: process.arch === 'ia32' | ||
? 'win32-archive' | ||
: 'win32-x64-archive'; | ||
break; | ||
default: | ||
exports.systemDefaultPlatform = process.arch === 'arm64' | ||
? 'linux-arm64' | ||
: process.arch === 'arm' | ||
? 'linux-armhf' | ||
: 'linux-x64'; | ||
exports.systemDefaultPlatform = | ||
process.arch === 'arm64' ? 'linux-arm64' : process.arch === 'arm' ? 'linux-armhf' : 'linux-x64'; | ||
} | ||
function isInsiderVersionIdentifier(version) { | ||
return version === 'insider' || version.endsWith('-insider'); // insider or 1.2.3-insider version string | ||
} | ||
exports.isInsiderVersionIdentifier = isInsiderVersionIdentifier; | ||
function isStableVersionIdentifier(version) { | ||
return version === 'stable' || version.includes('.'); // stable or 1.2.3 version string | ||
return version === 'stable' || /^[0-9]+\.[0-9]+\.[0-9]$/.test(version); // stable or 1.2.3 version string | ||
} | ||
@@ -45,6 +47,10 @@ exports.isStableVersionIdentifier = isStableVersionIdentifier; | ||
} | ||
else if (isInsiderVersionIdentifier(version)) { | ||
return `https://update.code.visualstudio.com/${version}/${platform}/insider`; | ||
} | ||
else if (isStableVersionIdentifier(version)) { | ||
return `https://update.code.visualstudio.com/${version}/${platform}/stable`; | ||
} | ||
else { // insiders commit hash | ||
else { | ||
// insiders commit hash | ||
return `https://update.code.visualstudio.com/commit:${version}/${platform}/insider`; | ||
@@ -113,6 +119,11 @@ } | ||
version: productJson.commit, | ||
date: new Date(productJson.date) | ||
date: new Date(productJson.date), | ||
}; | ||
} | ||
exports.insidersDownloadDirMetadata = insidersDownloadDirMetadata; | ||
async function getInsidersVersionMetadata(platform, version) { | ||
const remoteUrl = `https://update.code.visualstudio.com/api/versions/${version}/${platform}/insider`; | ||
return await request.getJSON(remoteUrl, 30000); | ||
} | ||
exports.getInsidersVersionMetadata = getInsidersVersionMetadata; | ||
async function getLatestInsidersMetadata(platform) { | ||
@@ -169,3 +180,5 @@ const remoteUrl = `https://update.code.visualstudio.com/api/update/${platform}/insider/latest`; | ||
var _a; | ||
const args = [resolveCliPathFromVSCodeExecutablePath(vscodeExecutablePath, (_a = options === null || options === void 0 ? void 0 : options.platform) !== null && _a !== void 0 ? _a : exports.systemDefaultPlatform)]; | ||
const args = [ | ||
resolveCliPathFromVSCodeExecutablePath(vscodeExecutablePath, (_a = options === null || options === void 0 ? void 0 : options.platform) !== null && _a !== void 0 ? _a : exports.systemDefaultPlatform), | ||
]; | ||
if (!(options === null || options === void 0 ? void 0 : options.reuseMachineInstall)) { | ||
@@ -177,1 +190,39 @@ args.push(...runTest_1.getProfileArguments(args)); | ||
exports.resolveCliArgsFromVSCodeExecutablePath = resolveCliArgsFromVSCodeExecutablePath; | ||
/** Predicates whether arg is undefined or null */ | ||
function isDefined(arg) { | ||
return arg != null; | ||
} | ||
exports.isDefined = isDefined; | ||
/** Gets a Buffer from a Node.js stream */ | ||
function streamToBuffer(readable) { | ||
return new Promise((resolve, reject) => { | ||
const chunks = []; | ||
readable.on('data', (chunk) => chunks.push(chunk)); | ||
readable.on('error', reject); | ||
readable.on('end', () => resolve(Buffer.concat(chunks))); | ||
}); | ||
} | ||
exports.streamToBuffer = streamToBuffer; | ||
/** Gets whether child is a subdirectory of the parent */ | ||
function isSubdirectory(parent, child) { | ||
const relative = path.relative(parent, child); | ||
return !relative.startsWith('..') && !path.isAbsolute(relative); | ||
} | ||
exports.isSubdirectory = isSubdirectory; | ||
/** | ||
* Wraps a function so that it's called once, and never again, memoizing | ||
* the result unless it rejects. | ||
*/ | ||
function onceWithoutRejections(fn) { | ||
let value; | ||
return (...args) => { | ||
if (!value) { | ||
value = fn(...args).catch((err) => { | ||
value = undefined; | ||
throw err; | ||
}); | ||
} | ||
return value; | ||
}; | ||
} | ||
exports.onceWithoutRejections = onceWithoutRejections; |
{ | ||
"name": "@vscode/test-electron", | ||
"version": "2.2.3", | ||
"version": "2.3.0", | ||
"scripts": { | ||
@@ -8,4 +8,15 @@ "compile": "tsc -p ./", | ||
"prepublish": "tsc -p ./", | ||
"test": "eslint lib --ext ts && vitest && tsc --noEmit" | ||
"fmt": "prettier --write \"lib/**/*.ts\" \"*.md\"", | ||
"test": "eslint lib --ext ts && vitest && tsc --noEmit", | ||
"prepare": "husky install" | ||
}, | ||
"lint-staged": { | ||
"*.ts": [ | ||
"eslint --fix", | ||
"prettier --write" | ||
], | ||
"*.md": [ | ||
"prettier --write" | ||
] | ||
}, | ||
"main": "./out/index.js", | ||
@@ -18,4 +29,4 @@ "engines": { | ||
"https-proxy-agent": "^5.0.0", | ||
"rimraf": "^3.0.2", | ||
"unzipper": "^0.10.11" | ||
"jszip": "^3.10.1", | ||
"semver": "^7.3.8" | ||
}, | ||
@@ -25,3 +36,3 @@ "devDependencies": { | ||
"@types/rimraf": "^3.0.0", | ||
"@types/unzipper": "^0.10.3", | ||
"@types/semver": "^7.3.13", | ||
"@typescript-eslint/eslint-plugin": "^4.13.0", | ||
@@ -31,2 +42,5 @@ "@typescript-eslint/parser": "^4.13.0", | ||
"eslint-plugin-header": "^3.1.0", | ||
"husky": "^8.0.3", | ||
"lint-staged": "^13.1.2", | ||
"prettier": "^2.8.4", | ||
"typescript": "^4.3.5", | ||
@@ -33,0 +47,0 @@ "vitest": "^0.10.2" |
@@ -23,4 +23,4 @@ # vscode-test | ||
try { | ||
const extensionDevelopmentPath = path.resolve(__dirname, '../../../') | ||
const extensionTestsPath = path.resolve(__dirname, './suite') | ||
const extensionDevelopmentPath = path.resolve(__dirname, '../../../'); | ||
const extensionTestsPath = path.resolve(__dirname, './suite'); | ||
@@ -32,7 +32,7 @@ /** | ||
extensionDevelopmentPath, | ||
extensionTestsPath | ||
}) | ||
extensionTestsPath, | ||
}); | ||
const extensionTestsPath2 = path.resolve(__dirname, './suite2') | ||
const testWorkspace = path.resolve(__dirname, '../../../test-fixtures/fixture1') | ||
const extensionTestsPath2 = path.resolve(__dirname, './suite2'); | ||
const testWorkspace = path.resolve(__dirname, '../../../test-fixtures/fixture1'); | ||
@@ -45,4 +45,4 @@ /** | ||
extensionTestsPath: extensionTestsPath2, | ||
launchArgs: [testWorkspace] | ||
}) | ||
launchArgs: [testWorkspace], | ||
}); | ||
@@ -56,4 +56,4 @@ /** | ||
extensionTestsPath, | ||
launchArgs: [testWorkspace] | ||
}) | ||
launchArgs: [testWorkspace], | ||
}); | ||
@@ -67,4 +67,4 @@ /** | ||
extensionTestsPath, | ||
launchArgs: [testWorkspace] | ||
}) | ||
launchArgs: [testWorkspace], | ||
}); | ||
@@ -74,3 +74,3 @@ /** | ||
*/ | ||
await downloadAndUnzipVSCode('1.36.1') | ||
await downloadAndUnzipVSCode('1.36.1'); | ||
@@ -80,3 +80,3 @@ /** | ||
*/ | ||
const vscodeExecutablePath = await downloadAndUnzipVSCode('1.35.0') | ||
const vscodeExecutablePath = await downloadAndUnzipVSCode('1.35.0'); | ||
await runTests({ | ||
@@ -86,4 +86,4 @@ vscodeExecutablePath, | ||
extensionTestsPath, | ||
launchArgs: [testWorkspace] | ||
}) | ||
launchArgs: [testWorkspace], | ||
}); | ||
@@ -96,3 +96,3 @@ /** | ||
encoding: 'utf-8', | ||
stdio: 'inherit' | ||
stdio: 'inherit', | ||
}); | ||
@@ -111,7 +111,7 @@ | ||
// This disables all extensions except the one being tested | ||
'--disable-extensions' | ||
'--disable-extensions', | ||
], | ||
// Custom environment variables for extension test script | ||
extensionTestsEnv: { foo: 'bar' } | ||
}) | ||
extensionTestsEnv: { foo: 'bar' }, | ||
}); | ||
@@ -126,13 +126,12 @@ /** | ||
version: '1.40.0', | ||
platform: 'win32-x64-archive' | ||
platform: 'win32-x64-archive', | ||
}); | ||
} | ||
} catch (err) { | ||
console.error('Failed to run tests') | ||
process.exit(1) | ||
console.error('Failed to run tests'); | ||
process.exit(1); | ||
} | ||
} | ||
go() | ||
go(); | ||
``` | ||
@@ -139,0 +138,0 @@ |
@@ -15,15 +15,15 @@ <!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK --> | ||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). | ||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). | ||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). | ||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). | ||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: | ||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) | ||
* Full paths of source file(s) related to the manifestation of the issue | ||
* The location of the affected source code (tag/branch/commit or direct URL) | ||
* Any special configuration required to reproduce the issue | ||
* Step-by-step instructions to reproduce the issue | ||
* Proof-of-concept or exploit code (if possible) | ||
* Impact of the issue, including how an attacker might exploit the issue | ||
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) | ||
- Full paths of source file(s) related to the manifestation of the issue | ||
- The location of the affected source code (tag/branch/commit or direct URL) | ||
- Any special configuration required to reproduce the issue | ||
- Step-by-step instructions to reproduce the issue | ||
- Proof-of-concept or exploit code (if possible) | ||
- Impact of the issue, including how an attacker might exploit the issue | ||
@@ -30,0 +30,0 @@ This information will help us triage your report more quickly. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79117
1369
12
25
152
+ Addedjszip@^3.10.1
+ Addedsemver@^7.3.8
+ Addedimmediate@3.0.6(transitive)
+ Addedjszip@3.10.1(transitive)
+ Addedlie@3.3.0(transitive)
+ Addedpako@1.0.11(transitive)
+ Addedsemver@7.6.3(transitive)
- Removedrimraf@^3.0.2
- Removedunzipper@^0.10.11
- Removedbalanced-match@1.0.2(transitive)
- Removedbig-integer@1.6.52(transitive)
- Removedbinary@0.3.0(transitive)
- Removedbluebird@3.4.7(transitive)
- Removedbrace-expansion@1.1.11(transitive)
- Removedbuffer-indexof-polyfill@1.0.2(transitive)
- Removedbuffers@0.1.1(transitive)
- Removedchainsaw@0.1.0(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removedduplexer2@0.1.4(transitive)
- Removedfs.realpath@1.0.0(transitive)
- Removedfstream@1.0.12(transitive)
- Removedglob@7.2.3(transitive)
- Removedgraceful-fs@4.2.11(transitive)
- Removedinflight@1.0.6(transitive)
- Removedlistenercount@1.0.1(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedonce@1.4.0(transitive)
- Removedpath-is-absolute@1.0.1(transitive)
- Removedrimraf@2.7.13.0.2(transitive)
- Removedtraverse@0.3.9(transitive)
- Removedunzipper@0.10.14(transitive)
- Removedwrappy@1.0.2(transitive)