@vitest/browser 2.0.0-beta.3 → 2.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/context.d.ts +8 -0
- package/dist/client/.vite/manifest.json +24 -0
- package/dist/client/__vitest__/assets/index-DrQA2UkS.css +1 -0
- package/dist/client/__vitest__/assets/index-T2_JR9hd.js +51 -0
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/orchestrator-D24IzA4b.js +180 -0
- package/dist/client/__vitest_browser__/{rpc-Hw6RY18C.js → rpc-DBukiZYG.js} +217 -416
- package/dist/client/__vitest_browser__/{tester-Ly7RLJnN.js → tester-C3Mchfpf.js} +246 -33
- package/dist/client/esm-client-injector.js +12 -28
- package/dist/client/{index.html → orchestrator.html} +8 -7
- package/dist/client/tester.html +4 -3
- package/dist/index.js +243 -258
- package/package.json +9 -7
- package/dist/client/__vitest__/assets/index-C576npev.css +0 -1
- package/dist/client/__vitest__/assets/index-DBVixaI-.js +0 -51
- package/dist/client/__vitest_browser__/main-uRgy0zc4.js +0 -102
package/dist/index.js
CHANGED
|
@@ -3,11 +3,11 @@ import { readFile as readFile$1 } from 'node:fs/promises';
|
|
|
3
3
|
import sirv from 'sirv';
|
|
4
4
|
import { coverageConfigDefaults } from 'vitest/config';
|
|
5
5
|
import { slash } from '@vitest/utils';
|
|
6
|
-
import MagicString from 'magic-string';
|
|
7
|
-
import { esmWalker } from '@vitest/utils/ast';
|
|
8
6
|
import fs, { promises } from 'node:fs';
|
|
9
7
|
import { resolve as resolve$1, dirname } from 'node:path';
|
|
10
8
|
import { isFileServingAllowed } from 'vitest/node';
|
|
9
|
+
import MagicString from 'magic-string';
|
|
10
|
+
import { esmWalker } from '@vitest/utils/ast';
|
|
11
11
|
|
|
12
12
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
13
13
|
function normalizeWindowsPath(input = "") {
|
|
@@ -159,248 +159,6 @@ const basename = function(p, extension) {
|
|
|
159
159
|
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
160
160
|
};
|
|
161
161
|
|
|
162
|
-
/**
|
|
163
|
-
* @param {import('estree').Node} param
|
|
164
|
-
* @returns {string[]}
|
|
165
|
-
*/
|
|
166
|
-
function extract_names(param) {
|
|
167
|
-
return extract_identifiers(param).map((node) => node.name);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* @param {import('estree').Node} param
|
|
172
|
-
* @param {import('estree').Identifier[]} nodes
|
|
173
|
-
* @returns {import('estree').Identifier[]}
|
|
174
|
-
*/
|
|
175
|
-
function extract_identifiers(param, nodes = []) {
|
|
176
|
-
switch (param.type) {
|
|
177
|
-
case 'Identifier':
|
|
178
|
-
nodes.push(param);
|
|
179
|
-
break;
|
|
180
|
-
|
|
181
|
-
case 'MemberExpression':
|
|
182
|
-
let object = param;
|
|
183
|
-
while (object.type === 'MemberExpression') {
|
|
184
|
-
object = /** @type {any} */ (object.object);
|
|
185
|
-
}
|
|
186
|
-
nodes.push(/** @type {any} */ (object));
|
|
187
|
-
break;
|
|
188
|
-
|
|
189
|
-
case 'ObjectPattern':
|
|
190
|
-
for (const prop of param.properties) {
|
|
191
|
-
if (prop.type === 'RestElement') {
|
|
192
|
-
extract_identifiers(prop.argument, nodes);
|
|
193
|
-
} else {
|
|
194
|
-
extract_identifiers(prop.value, nodes);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
break;
|
|
199
|
-
|
|
200
|
-
case 'ArrayPattern':
|
|
201
|
-
for (const element of param.elements) {
|
|
202
|
-
if (element) extract_identifiers(element, nodes);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
break;
|
|
206
|
-
|
|
207
|
-
case 'RestElement':
|
|
208
|
-
extract_identifiers(param.argument, nodes);
|
|
209
|
-
break;
|
|
210
|
-
|
|
211
|
-
case 'AssignmentPattern':
|
|
212
|
-
extract_identifiers(param.left, nodes);
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return nodes;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const viInjectedKey = "__vi_inject__";
|
|
220
|
-
const viExportAllHelper = "__vitest_browser_runner__.exportAll";
|
|
221
|
-
const skipHijack = [
|
|
222
|
-
"/@vite/client",
|
|
223
|
-
"/@vite/env",
|
|
224
|
-
/vite\/dist\/client/
|
|
225
|
-
];
|
|
226
|
-
function injectVitestModule(code, id, parse) {
|
|
227
|
-
if (skipHijack.some((skip) => id.match(skip)))
|
|
228
|
-
return;
|
|
229
|
-
const s = new MagicString(code);
|
|
230
|
-
let ast;
|
|
231
|
-
try {
|
|
232
|
-
ast = parse(code);
|
|
233
|
-
} catch (err) {
|
|
234
|
-
console.error(`Cannot parse ${id}:
|
|
235
|
-
${err.message}`);
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
let uid = 0;
|
|
239
|
-
const idToImportMap = /* @__PURE__ */ new Map();
|
|
240
|
-
const declaredConst = /* @__PURE__ */ new Set();
|
|
241
|
-
const hoistIndex = 0;
|
|
242
|
-
const transformImportDeclaration = (node) => {
|
|
243
|
-
const source = node.source.value;
|
|
244
|
-
if (skipHijack.some((skip) => source.match(skip)))
|
|
245
|
-
return null;
|
|
246
|
-
const importId = `__vi_esm_${uid++}__`;
|
|
247
|
-
const hasSpecifiers = node.specifiers.length > 0;
|
|
248
|
-
const code2 = hasSpecifiers ? `import { ${viInjectedKey} as ${importId} } from '${source}'
|
|
249
|
-
` : `import '${source}'
|
|
250
|
-
`;
|
|
251
|
-
return {
|
|
252
|
-
code: code2,
|
|
253
|
-
id: importId
|
|
254
|
-
};
|
|
255
|
-
};
|
|
256
|
-
function defineImport(node) {
|
|
257
|
-
const declaration = transformImportDeclaration(node);
|
|
258
|
-
if (!declaration)
|
|
259
|
-
return null;
|
|
260
|
-
s.appendLeft(hoistIndex, declaration.code);
|
|
261
|
-
return declaration.id;
|
|
262
|
-
}
|
|
263
|
-
function defineImportAll(source) {
|
|
264
|
-
const importId = `__vi_esm_${uid++}__`;
|
|
265
|
-
s.appendLeft(hoistIndex, `const { ${viInjectedKey}: ${importId} } = await import(${JSON.stringify(source)});
|
|
266
|
-
`);
|
|
267
|
-
return importId;
|
|
268
|
-
}
|
|
269
|
-
function defineExport(position, name, local = name) {
|
|
270
|
-
s.appendLeft(
|
|
271
|
-
position,
|
|
272
|
-
`
|
|
273
|
-
Object.defineProperty(${viInjectedKey}, "${name}", { enumerable: true, configurable: true, get(){ return ${local} }});`
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
for (const node of ast.body) {
|
|
277
|
-
if (node.type === "ImportDeclaration") {
|
|
278
|
-
const importId = defineImport(node);
|
|
279
|
-
if (!importId)
|
|
280
|
-
continue;
|
|
281
|
-
s.remove(node.start, node.end);
|
|
282
|
-
for (const spec of node.specifiers) {
|
|
283
|
-
if (spec.type === "ImportSpecifier") {
|
|
284
|
-
idToImportMap.set(
|
|
285
|
-
spec.local.name,
|
|
286
|
-
`${importId}.${spec.imported.name}`
|
|
287
|
-
);
|
|
288
|
-
} else if (spec.type === "ImportDefaultSpecifier") {
|
|
289
|
-
idToImportMap.set(spec.local.name, `${importId}.default`);
|
|
290
|
-
} else {
|
|
291
|
-
idToImportMap.set(spec.local.name, importId);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
for (const node of ast.body) {
|
|
297
|
-
if (node.type === "ExportNamedDeclaration") {
|
|
298
|
-
if (node.declaration) {
|
|
299
|
-
if (node.declaration.type === "FunctionDeclaration" || node.declaration.type === "ClassDeclaration") {
|
|
300
|
-
defineExport(node.end, node.declaration.id.name);
|
|
301
|
-
} else {
|
|
302
|
-
for (const declaration of node.declaration.declarations) {
|
|
303
|
-
const names = extract_names(declaration.id);
|
|
304
|
-
for (const name of names)
|
|
305
|
-
defineExport(node.end, name);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
s.remove(node.start, node.declaration.start);
|
|
309
|
-
} else {
|
|
310
|
-
s.remove(node.start, node.end);
|
|
311
|
-
if (node.source) {
|
|
312
|
-
const importId = defineImportAll(node.source.value);
|
|
313
|
-
for (const spec of node.specifiers) {
|
|
314
|
-
defineExport(
|
|
315
|
-
hoistIndex,
|
|
316
|
-
spec.exported.name,
|
|
317
|
-
`${importId}.${spec.local.name}`
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
} else {
|
|
321
|
-
for (const spec of node.specifiers) {
|
|
322
|
-
const local = spec.local.name;
|
|
323
|
-
const binding = idToImportMap.get(local);
|
|
324
|
-
defineExport(node.end, spec.exported.name, binding || local);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
if (node.type === "ExportDefaultDeclaration") {
|
|
330
|
-
const expressionTypes = ["FunctionExpression", "ClassExpression"];
|
|
331
|
-
if ("id" in node.declaration && node.declaration.id && !expressionTypes.includes(node.declaration.type)) {
|
|
332
|
-
const { name } = node.declaration.id;
|
|
333
|
-
s.remove(
|
|
334
|
-
node.start,
|
|
335
|
-
node.start + 15
|
|
336
|
-
/* 'export default '.length */
|
|
337
|
-
);
|
|
338
|
-
s.append(
|
|
339
|
-
`
|
|
340
|
-
Object.defineProperty(${viInjectedKey}, "default", { enumerable: true, configurable: true, value: ${name} });`
|
|
341
|
-
);
|
|
342
|
-
} else {
|
|
343
|
-
s.update(
|
|
344
|
-
node.start,
|
|
345
|
-
node.start + 14,
|
|
346
|
-
`${viInjectedKey}.default =`
|
|
347
|
-
);
|
|
348
|
-
s.append(`
|
|
349
|
-
export default { ${viInjectedKey}: ${viInjectedKey}.default };
|
|
350
|
-
`);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
if (node.type === "ExportAllDeclaration") {
|
|
354
|
-
s.remove(node.start, node.end);
|
|
355
|
-
const importId = defineImportAll(node.source.value);
|
|
356
|
-
if (node.exported)
|
|
357
|
-
defineExport(hoistIndex, node.exported.name, `${importId}`);
|
|
358
|
-
else
|
|
359
|
-
s.appendLeft(hoistIndex, `${viExportAllHelper}(${viInjectedKey}, ${importId});
|
|
360
|
-
`);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
esmWalker(ast, {
|
|
364
|
-
onIdentifier(id2, info, parentStack) {
|
|
365
|
-
const binding = idToImportMap.get(id2.name);
|
|
366
|
-
if (!binding)
|
|
367
|
-
return;
|
|
368
|
-
if (info.hasBindingShortcut) {
|
|
369
|
-
s.appendLeft(id2.end, `: ${binding}`);
|
|
370
|
-
} else if (info.classDeclaration) {
|
|
371
|
-
if (!declaredConst.has(id2.name)) {
|
|
372
|
-
declaredConst.add(id2.name);
|
|
373
|
-
const topNode = parentStack[parentStack.length - 2];
|
|
374
|
-
s.prependRight(topNode.start, `const ${id2.name} = ${binding};
|
|
375
|
-
`);
|
|
376
|
-
}
|
|
377
|
-
} else if (
|
|
378
|
-
// don't transform class name identifier
|
|
379
|
-
!info.classExpression
|
|
380
|
-
) {
|
|
381
|
-
s.update(id2.start, id2.end, binding);
|
|
382
|
-
}
|
|
383
|
-
},
|
|
384
|
-
// TODO: make env updatable
|
|
385
|
-
onImportMeta() {
|
|
386
|
-
},
|
|
387
|
-
onDynamicImport(node) {
|
|
388
|
-
const replace = "__vitest_browser_runner__.wrapModule(import(";
|
|
389
|
-
s.overwrite(node.start, node.source.start, replace);
|
|
390
|
-
s.overwrite(node.end - 1, node.end, "))");
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
s.prepend(`const ${viInjectedKey} = { [Symbol.toStringTag]: "Module" };
|
|
394
|
-
`);
|
|
395
|
-
s.append(`
|
|
396
|
-
export { ${viInjectedKey} }`);
|
|
397
|
-
return {
|
|
398
|
-
ast,
|
|
399
|
-
code: s.toString(),
|
|
400
|
-
map: s.generateMap({ hires: "boundary", source: id })
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
|
|
404
162
|
function assertFileAccess(path, project) {
|
|
405
163
|
if (!isFileServingAllowed(path, project.server) && !isFileServingAllowed(path, project.ctx.server))
|
|
406
164
|
throw new Error(`Access denied to "${path}". See Vite config documentation for "server.fs": https://vitejs.dev/config/server-options.html#server-fs-strict.`);
|
|
@@ -531,11 +289,13 @@ function generateContextFile(project) {
|
|
|
531
289
|
}).join("\n");
|
|
532
290
|
return `
|
|
533
291
|
const rpc = () => __vitest_worker__.rpc
|
|
292
|
+
const channel = new BroadcastChannel('vitest')
|
|
534
293
|
|
|
535
294
|
export const server = {
|
|
536
295
|
platform: ${JSON.stringify(process.platform)},
|
|
537
296
|
version: ${JSON.stringify(process.version)},
|
|
538
297
|
provider: ${JSON.stringify(project.browserProvider.name)},
|
|
298
|
+
browser: ${JSON.stringify(project.config.browser.name)},
|
|
539
299
|
commands: {
|
|
540
300
|
${commandsCode}
|
|
541
301
|
}
|
|
@@ -544,15 +304,227 @@ export const commands = server.commands
|
|
|
544
304
|
export const page = {
|
|
545
305
|
get config() {
|
|
546
306
|
return __vitest_browser_runner__.config
|
|
307
|
+
},
|
|
308
|
+
viewport(width, height) {
|
|
309
|
+
const id = __vitest_browser_runner__.iframeId
|
|
310
|
+
channel.postMessage({ type: 'viewport', width, height, id })
|
|
311
|
+
return new Promise((resolve, reject) => {
|
|
312
|
+
channel.addEventListener('message', function handler(e) {
|
|
313
|
+
if (e.data.type === 'viewport:done' && e.data.id === id) {
|
|
314
|
+
channel.removeEventListener('message', handler)
|
|
315
|
+
resolve()
|
|
316
|
+
}
|
|
317
|
+
if (e.data.type === 'viewport:fail' && e.data.id === id) {
|
|
318
|
+
channel.removeEventListener('message', handler)
|
|
319
|
+
reject(new Error(e.data.error))
|
|
320
|
+
}
|
|
321
|
+
})
|
|
322
|
+
})
|
|
547
323
|
}
|
|
548
324
|
}
|
|
549
325
|
`;
|
|
550
326
|
}
|
|
551
327
|
|
|
328
|
+
function automockModule(code, parse) {
|
|
329
|
+
const ast = parse(code);
|
|
330
|
+
const m = new MagicString(code);
|
|
331
|
+
const allSpecifiers = [];
|
|
332
|
+
let importIndex = 0;
|
|
333
|
+
for (const _node of ast.body) {
|
|
334
|
+
if (_node.type === "ExportAllDeclaration") {
|
|
335
|
+
throw new Error(
|
|
336
|
+
`automocking files with \`export *\` is not supported in browser mode because it cannot be statically analysed`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
if (_node.type === "ExportNamedDeclaration") {
|
|
340
|
+
let traversePattern2 = function(expression) {
|
|
341
|
+
if (expression.type === "Identifier") {
|
|
342
|
+
allSpecifiers.push({ name: expression.name });
|
|
343
|
+
} else if (expression.type === "ArrayPattern") {
|
|
344
|
+
expression.elements.forEach((element) => {
|
|
345
|
+
if (!element)
|
|
346
|
+
return;
|
|
347
|
+
traversePattern2(element);
|
|
348
|
+
});
|
|
349
|
+
} else if (expression.type === "ObjectPattern") {
|
|
350
|
+
expression.properties.forEach((property) => {
|
|
351
|
+
if (property.type === "RestElement")
|
|
352
|
+
traversePattern2(property);
|
|
353
|
+
else if (property.type === "Property")
|
|
354
|
+
traversePattern2(property.value);
|
|
355
|
+
else
|
|
356
|
+
;
|
|
357
|
+
});
|
|
358
|
+
} else if (expression.type === "RestElement") {
|
|
359
|
+
traversePattern2(expression.argument);
|
|
360
|
+
} else if (expression.type === "AssignmentPattern") {
|
|
361
|
+
throw new Error(`AssignmentPattern is not supported. Please open a new bug report.`);
|
|
362
|
+
} else if (expression.type === "MemberExpression") {
|
|
363
|
+
throw new Error(`MemberExpression is not supported. Please open a new bug report.`);
|
|
364
|
+
} else ;
|
|
365
|
+
};
|
|
366
|
+
const node = _node;
|
|
367
|
+
const declaration = node.declaration;
|
|
368
|
+
if (declaration) {
|
|
369
|
+
if (declaration.type === "FunctionDeclaration") {
|
|
370
|
+
allSpecifiers.push({ name: declaration.id.name });
|
|
371
|
+
} else if (declaration.type === "VariableDeclaration") {
|
|
372
|
+
declaration.declarations.forEach((declaration2) => {
|
|
373
|
+
traversePattern2(declaration2.id);
|
|
374
|
+
});
|
|
375
|
+
} else if (declaration.type === "ClassDeclaration") {
|
|
376
|
+
allSpecifiers.push({ name: declaration.id.name });
|
|
377
|
+
} else ;
|
|
378
|
+
m.remove(node.start, declaration.start);
|
|
379
|
+
}
|
|
380
|
+
const specifiers = node.specifiers || [];
|
|
381
|
+
const source = node.source;
|
|
382
|
+
if (!source && specifiers.length) {
|
|
383
|
+
specifiers.forEach((specifier) => {
|
|
384
|
+
const exported = specifier.exported;
|
|
385
|
+
allSpecifiers.push({
|
|
386
|
+
alias: exported.type === "Literal" ? exported.raw : exported.name,
|
|
387
|
+
name: specifier.local.name
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
m.remove(node.start, node.end);
|
|
391
|
+
} else if (source && specifiers.length) {
|
|
392
|
+
const importNames = [];
|
|
393
|
+
specifiers.forEach((specifier) => {
|
|
394
|
+
const importedName = `__vitest_imported_${importIndex++}__`;
|
|
395
|
+
const exported = specifier.exported;
|
|
396
|
+
importNames.push([specifier.local.name, importedName]);
|
|
397
|
+
allSpecifiers.push({
|
|
398
|
+
name: importedName,
|
|
399
|
+
alias: exported.type === "Literal" ? exported.raw : exported.name
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
const importString = `import { ${importNames.map(([name, alias]) => `${name} as ${alias}`).join(", ")} } from '${source.value}'`;
|
|
403
|
+
m.overwrite(node.start, node.end, importString);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
if (_node.type === "ExportDefaultDeclaration") {
|
|
407
|
+
const node = _node;
|
|
408
|
+
const declaration = node.declaration;
|
|
409
|
+
allSpecifiers.push({ name: "__vitest_default", alias: "default" });
|
|
410
|
+
m.overwrite(node.start, declaration.start, `const __vitest_default = `);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
const moduleObject = `
|
|
414
|
+
const __vitest_es_current_module__ = {
|
|
415
|
+
__esModule: true,
|
|
416
|
+
${allSpecifiers.map(({ name }) => `["${name}"]: ${name},`).join("\n ")}
|
|
417
|
+
}
|
|
418
|
+
const __vitest_mocked_module__ = __vitest_mocker__.mockObject(__vitest_es_current_module__)
|
|
419
|
+
`;
|
|
420
|
+
const assigning = allSpecifiers.map(({ name }, index) => {
|
|
421
|
+
return `const __vitest_mocked_${index}__ = __vitest_mocked_module__["${name}"]`;
|
|
422
|
+
}).join("\n");
|
|
423
|
+
const redeclarations = allSpecifiers.map(({ name, alias }, index) => {
|
|
424
|
+
return ` __vitest_mocked_${index}__ as ${alias || name},`;
|
|
425
|
+
}).join("\n");
|
|
426
|
+
const specifiersExports = `
|
|
427
|
+
export {
|
|
428
|
+
${redeclarations}
|
|
429
|
+
}
|
|
430
|
+
`;
|
|
431
|
+
m.append(moduleObject + assigning + specifiersExports);
|
|
432
|
+
return m;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
var BrowserMocker = (project) => {
|
|
436
|
+
return [
|
|
437
|
+
{
|
|
438
|
+
name: "vitest:browser:mocker",
|
|
439
|
+
enforce: "pre",
|
|
440
|
+
async load(id) {
|
|
441
|
+
const data = project.browserMocker.mocks.get(id);
|
|
442
|
+
if (!data)
|
|
443
|
+
return;
|
|
444
|
+
const { mock, sessionId } = data;
|
|
445
|
+
if (mock === void 0) {
|
|
446
|
+
const rpc = project.browserRpc.testers.get(sessionId);
|
|
447
|
+
if (!rpc)
|
|
448
|
+
throw new Error(`WebSocket rpc was destroyed for session ${sessionId}`);
|
|
449
|
+
const exports = await rpc.startMocking(id);
|
|
450
|
+
const module = `const module = __vitest_mocker__.get('${id}');`;
|
|
451
|
+
const keys = exports.map((name) => {
|
|
452
|
+
if (name === "default")
|
|
453
|
+
return `export default module['default'];`;
|
|
454
|
+
return `export const ${name} = module['${name}'];`;
|
|
455
|
+
}).join("\n");
|
|
456
|
+
return `${module}
|
|
457
|
+
${keys}`;
|
|
458
|
+
}
|
|
459
|
+
if (mock === null)
|
|
460
|
+
return;
|
|
461
|
+
return readFile$1(mock, "utf-8");
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
name: "vitest:browser:automocker",
|
|
466
|
+
enforce: "post",
|
|
467
|
+
transform(code, id) {
|
|
468
|
+
const data = project.browserMocker.mocks.get(id);
|
|
469
|
+
if (!data)
|
|
470
|
+
return;
|
|
471
|
+
if (data.mock === null) {
|
|
472
|
+
const m = automockModule(code, this.parse);
|
|
473
|
+
return {
|
|
474
|
+
code: m.toString(),
|
|
475
|
+
map: m.generateMap({ hires: "boundary", source: id })
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
];
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
function injectDynamicImport(code, id, parse) {
|
|
484
|
+
const s = new MagicString(code);
|
|
485
|
+
let ast;
|
|
486
|
+
try {
|
|
487
|
+
ast = parse(code);
|
|
488
|
+
} catch (err) {
|
|
489
|
+
console.error(`Cannot parse ${id}:
|
|
490
|
+
${err.message}`);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
esmWalker(ast, {
|
|
494
|
+
// TODO: make env updatable
|
|
495
|
+
onImportMeta() {
|
|
496
|
+
},
|
|
497
|
+
onDynamicImport(node) {
|
|
498
|
+
const replace = "__vitest_browser_runner__.wrapModule(() => import(";
|
|
499
|
+
s.overwrite(node.start, node.source.start, replace);
|
|
500
|
+
s.overwrite(node.end - 1, node.end, "))");
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
return {
|
|
504
|
+
ast,
|
|
505
|
+
code: s.toString(),
|
|
506
|
+
map: s.generateMap({ hires: "boundary", source: id })
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const regexDynamicImport = /import\s*\(/;
|
|
511
|
+
var DynamicImport = () => {
|
|
512
|
+
return {
|
|
513
|
+
name: "vitest:browser:esm-injector",
|
|
514
|
+
enforce: "post",
|
|
515
|
+
transform(source, id) {
|
|
516
|
+
if (!regexDynamicImport.test(source))
|
|
517
|
+
return;
|
|
518
|
+
return injectDynamicImport(source, id, this.parse);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
};
|
|
522
|
+
|
|
552
523
|
var index = (project, base = "/") => {
|
|
553
524
|
const pkgRoot = resolve(fileURLToPath(import.meta.url), "../..");
|
|
554
525
|
const distRoot = resolve(pkgRoot, "dist");
|
|
555
526
|
return [
|
|
527
|
+
...BrowserMocker(project),
|
|
556
528
|
{
|
|
557
529
|
enforce: "pre",
|
|
558
530
|
name: "vitest:browser",
|
|
@@ -565,8 +537,11 @@ var index = (project, base = "/") => {
|
|
|
565
537
|
},
|
|
566
538
|
async configureServer(server) {
|
|
567
539
|
const testerHtml = readFile$1(resolve(distRoot, "client/tester.html"), "utf8");
|
|
568
|
-
const
|
|
540
|
+
const orchestratorHtml = project.config.browser.ui ? readFile$1(resolve(distRoot, "client/__vitest__/index.html"), "utf8") : readFile$1(resolve(distRoot, "client/orchestrator.html"), "utf8");
|
|
569
541
|
const injectorJs = readFile$1(resolve(distRoot, "client/esm-client-injector.js"), "utf8");
|
|
542
|
+
const manifest = (async () => {
|
|
543
|
+
return JSON.parse(await readFile$1(`${distRoot}/client/.vite/manifest.json`, "utf8"));
|
|
544
|
+
})();
|
|
570
545
|
const favicon = `${base}favicon.svg`;
|
|
571
546
|
const testerPrefix = `${base}__vitest_test__/__test__/`;
|
|
572
547
|
server.middlewares.use((_req, res, next) => {
|
|
@@ -593,12 +568,26 @@ var index = (project, base = "/") => {
|
|
|
593
568
|
config.env.VITEST_BROWSER_DEBUG = process.env.VITEST_BROWSER_DEBUG || "";
|
|
594
569
|
const injector = replacer(await injectorJs, {
|
|
595
570
|
__VITEST_CONFIG__: JSON.stringify(config),
|
|
596
|
-
__VITEST_FILES__: JSON.stringify(files)
|
|
571
|
+
__VITEST_FILES__: JSON.stringify(files),
|
|
572
|
+
__VITEST_TYPE__: url.pathname === base ? '"orchestrator"' : '"tester"'
|
|
597
573
|
});
|
|
598
574
|
if (url.pathname === base) {
|
|
599
575
|
if (!indexScripts)
|
|
600
576
|
indexScripts = await formatScripts(project.config.browser.indexScripts, server);
|
|
601
|
-
|
|
577
|
+
let baseHtml = await orchestratorHtml;
|
|
578
|
+
if (project.config.browser.ui) {
|
|
579
|
+
const manifestContent = await manifest;
|
|
580
|
+
const jsEntry = manifestContent["orchestrator.html"].file;
|
|
581
|
+
baseHtml = baseHtml.replaceAll("./assets/", `${base}__vitest__/assets/`).replace(
|
|
582
|
+
"<!-- !LOAD_METADATA! -->",
|
|
583
|
+
[
|
|
584
|
+
"<script>{__VITEST_INJECTOR__}<\/script>",
|
|
585
|
+
"{__VITEST_SCRIPTS__}",
|
|
586
|
+
`<script type="module" crossorigin src="${jsEntry}"><\/script>`
|
|
587
|
+
].join("\n")
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
const html2 = replacer(baseHtml, {
|
|
602
591
|
__VITEST_FAVICON__: favicon,
|
|
603
592
|
__VITEST_TITLE__: "Vitest Browser Runner",
|
|
604
593
|
__VITEST_SCRIPTS__: indexScripts,
|
|
@@ -610,6 +599,7 @@ var index = (project, base = "/") => {
|
|
|
610
599
|
}
|
|
611
600
|
const decodedTestFile = decodeURIComponent(url.pathname.slice(testerPrefix.length));
|
|
612
601
|
const tests = decodedTestFile === "__vitest_all__" || !files.includes(decodedTestFile) ? "__vitest_browser_runner__.files" : JSON.stringify([decodedTestFile]);
|
|
602
|
+
const iframeId = decodedTestFile === "__vitest_all__" ? '"__vitest_all__"' : JSON.stringify(decodedTestFile);
|
|
613
603
|
if (!testerScripts)
|
|
614
604
|
testerScripts = await formatScripts(project.config.browser.testerScripts, server);
|
|
615
605
|
const html = replacer(await testerHtml, {
|
|
@@ -621,6 +611,7 @@ var index = (project, base = "/") => {
|
|
|
621
611
|
// TODO: have only a single global variable to not pollute the global scope
|
|
622
612
|
`<script type="module">
|
|
623
613
|
__vitest_browser_runner__.runningFiles = ${tests}
|
|
614
|
+
__vitest_browser_runner__.iframeId = ${iframeId}
|
|
624
615
|
__vitest_browser_runner__.runTests(__vitest_browser_runner__.runningFiles)
|
|
625
616
|
<\/script>`
|
|
626
617
|
)
|
|
@@ -677,6 +668,9 @@ var index = (project, base = "/") => {
|
|
|
677
668
|
"vitest/browser",
|
|
678
669
|
"vitest/runners",
|
|
679
670
|
"@vitest/utils",
|
|
671
|
+
"std-env",
|
|
672
|
+
"tinybench",
|
|
673
|
+
"tinyspy",
|
|
680
674
|
// loupe is manually transformed
|
|
681
675
|
"loupe"
|
|
682
676
|
],
|
|
@@ -714,16 +708,7 @@ export default globalThis.loupe`;
|
|
|
714
708
|
}
|
|
715
709
|
},
|
|
716
710
|
BrowserContext(project),
|
|
717
|
-
|
|
718
|
-
name: "vitest:browser:esm-injector",
|
|
719
|
-
enforce: "post",
|
|
720
|
-
transform(source, id) {
|
|
721
|
-
const hijackESM = project.config.browser.slowHijackESM ?? false;
|
|
722
|
-
if (!hijackESM)
|
|
723
|
-
return;
|
|
724
|
-
return injectVitestModule(source, id, this.parse);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
711
|
+
DynamicImport()
|
|
727
712
|
];
|
|
728
713
|
};
|
|
729
714
|
function resolveCoverageFolder(project) {
|
|
@@ -736,7 +721,7 @@ function resolveCoverageFolder(project) {
|
|
|
736
721
|
if (!htmlReporter)
|
|
737
722
|
return void 0;
|
|
738
723
|
const root = resolve(
|
|
739
|
-
options.root ||
|
|
724
|
+
options.root || process.cwd(),
|
|
740
725
|
options.coverage.reportsDirectory || coverageConfigDefaults.reportsDirectory
|
|
741
726
|
);
|
|
742
727
|
const subdir = Array.isArray(htmlReporter) && htmlReporter.length > 1 && "subdir" in htmlReporter[1] ? htmlReporter[1].subdir : void 0;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest/browser",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.6",
|
|
5
5
|
"description": "Browser running for Vitest",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://opencollective.com/vitest",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"playwright": "*",
|
|
49
49
|
"webdriverio": "*",
|
|
50
|
-
"vitest": "2.0.0-beta.
|
|
50
|
+
"vitest": "2.0.0-beta.6"
|
|
51
51
|
},
|
|
52
52
|
"peerDependenciesMeta": {
|
|
53
53
|
"playwright": {
|
|
@@ -63,20 +63,22 @@
|
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"magic-string": "^0.30.10",
|
|
65
65
|
"sirv": "^2.0.4",
|
|
66
|
-
"@vitest/utils": "2.0.0-beta.
|
|
66
|
+
"@vitest/utils": "2.0.0-beta.6"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@types/ws": "^8.5.10",
|
|
70
70
|
"@wdio/protocols": "^8.32.0",
|
|
71
|
+
"birpc": "0.2.17",
|
|
72
|
+
"flatted": "^3.3.1",
|
|
71
73
|
"periscopic": "^4.0.2",
|
|
72
74
|
"playwright": "^1.44.0",
|
|
73
75
|
"playwright-core": "^1.44.0",
|
|
74
76
|
"safaridriver": "^0.1.2",
|
|
75
77
|
"webdriverio": "^8.36.1",
|
|
76
|
-
"@vitest/
|
|
77
|
-
"@vitest/
|
|
78
|
-
"@vitest/ws-client": "2.0.0-beta.
|
|
79
|
-
"vitest": "2.0.0-beta.
|
|
78
|
+
"@vitest/ui": "2.0.0-beta.6",
|
|
79
|
+
"@vitest/runner": "2.0.0-beta.6",
|
|
80
|
+
"@vitest/ws-client": "2.0.0-beta.6",
|
|
81
|
+
"vitest": "2.0.0-beta.6"
|
|
80
82
|
},
|
|
81
83
|
"scripts": {
|
|
82
84
|
"build": "rimraf dist && pnpm build:node && pnpm build:client",
|