Files

137 lines
5.3 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>VSCode Tests</title>
<link href="../../../node_modules/mocha/mocha.css" rel="stylesheet" />
</head>
<body>
<div id="mocha"></div>
<script src="../../../node_modules/mocha/mocha.js"></script>
<script>
// !!! DO NOT CHANGE !!!
// Our unit tests may run in environments without
// display (e.g. from builds) and tests may by
// accident bring up native dialogs or even open
// windows. This we cannot allow as it may crash
// the test run.
// !!! DO NOT CHANGE !!!
window.open = function () { throw new Error('window.open() is not supported in tests!'); };
window.alert = function () { throw new Error('window.alert() is not supported in tests!'); }
window.confirm = function () { throw new Error('window.confirm() is not supported in tests!'); }
// Ignore uncaught cancelled promise errors
window.addEventListener('unhandledrejection', e => {
const name = e && e.reason && e.reason.name;
if (name === 'Canceled') {
e.preventDefault();
e.stopPropagation();
}
});
</script>
<script>
const urlParams = new URLSearchParams(window.location.search);
const argv = JSON.parse(urlParams.get('argv'));
const outdir = argv.build ? 'out-build' : 'out';
const basePath = require('path').join(__dirname, `../../../${outdir}/`);
const baseUrl = require('url').pathToFileURL(basePath);
// Tests run in a renderer that IS node-enabled. So we will encounter imports for node-modules which isn't
// supported by blink/chromium. To work around this, we generate an import map that maps all node modules
// to a blob that exports all properties of the module as named exports and the module itself as default.
// Some CommonJS modules export keys that are reserved words in ES module syntax
// (e.g. zod exports `enum`, `default`, `function`). Generating `export const enum = ...`
// for those would fail to parse, so skip them. Hoisted to outer scope so we don't
// reallocate the Set / regex for every dependency the import map covers.
const RESERVED_EXPORT_NAMES = new Set(['break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'null', 'return', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield', 'let', 'static', 'implements', 'interface', 'package', 'private', 'protected', 'public', 'await']);
const VALID_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
function asRequireBlobUri(name) {
let _mod;
try {
_mod = require(name);
} catch (err) {
// These are somewhat expected because of platform differences (windows vs mac vs linux) or because of node/electron binary differences
// console.error(`[ESM] Failed to require ${name}`);
// console.error(err);
return undefined;
}
// export all properties and the module itself as default
let jsSrc = `const _mod = require('${name}')\n`;
for (const name of Object.keys(_mod)) {
if (RESERVED_EXPORT_NAMES.has(name) || !VALID_IDENTIFIER.test(name)) {
continue;
}
jsSrc += `export const ${name} = _mod['${name}'];\n`;
}
jsSrc += `export default _mod;\n`;
const blob = new Blob([jsSrc], { type: 'application/javascript' });
const url = URL.createObjectURL(blob);
return url;
}
// generate import map
const importMap = {
imports: {
assert: new URL('../test/unit/assert.js', baseUrl).href,
sinon: new URL('../node_modules/sinon/pkg/sinon-esm.js', baseUrl).href,
'sinon-test': new URL('../node_modules/sinon-test/dist/sinon-test-es.js', baseUrl).href,
'electron': asRequireBlobUri('electron'),
}
};
const builtin = require('module').builtinModules.filter(mod => !mod.startsWith('_') && !mod.startsWith('electron/js2c/')).sort();
const dependencies = Object.keys(require('../../../package.json').dependencies).sort();
const optionalDependencies = Object.keys(require('../../../package.json').optionalDependencies).sort();
const dependenciesRemote = Object.keys(require('../../../remote/package.json').dependencies).sort();
for (const name of new Set([].concat(builtin, dependencies, optionalDependencies, dependenciesRemote))) {
const url = asRequireBlobUri(name);
if (!url) {
continue;
}
importMap.imports[name] = url;
}
//2: CSS modules
const style = document.createElement('style');
style.type = 'text/css';
document.head.appendChild(style);
globalThis._VSCODE_CSS_LOAD = function (url) {
style.sheet.insertRule(`@import url(${url});`);
};
const { promisify } = require('util');
globalThis._VSCODE_TEST_INIT = promisify(require('glob'))('**/*.css', { cwd: basePath }).then(cssModules => {
for (const cssModule of cssModules) {
const cssUrl = new URL(cssModule, baseUrl).href;
const jsSrc = `globalThis._VSCODE_CSS_LOAD('${cssUrl}');\n`;
const blob = new Blob([jsSrc], { type: 'application/javascript' });
importMap.imports[cssUrl] = URL.createObjectURL(blob);
}
}).then(() => {
const rawImportMap = JSON.stringify(importMap, undefined, 2);
const importMapScript = document.createElement('script');
importMapScript.type = 'importmap';
importMapScript.textContent = rawImportMap;
document.head.append(importMapScript);
});
</script>
<script src="./renderer.js"></script>
</body>
</html>