@vitest/browser 2.0.0-beta.5 → 2.0.0-beta.7
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 +22 -1
- package/dist/client/.vite/manifest.json +2 -2
- package/dist/client/__vitest__/assets/index-BNIf8EuF.js +51 -0
- package/dist/client/__vitest__/assets/{index-B74JATHR.css → index-DrQA2UkS.css} +1 -1
- package/dist/client/__vitest__/index.html +2 -2
- package/dist/client/__vitest_browser__/{orchestrator-CEB54dI4.js → orchestrator-CTfJ7g35.js} +29 -35
- package/dist/client/__vitest_browser__/{tester-C3Mchfpf.js → tester-Bo1gw1oi.js} +12 -2
- package/dist/client/orchestrator.html +1 -1
- package/dist/client/tester.html +1 -1
- package/dist/index.js +122 -33
- package/dist/providers.js +5 -5
- package/package.json +9 -7
- package/providers.d.ts +5 -5
- package/dist/client/__vitest__/assets/index-BoV0brgU.js +0 -51
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
2
|
import { readFile as readFile$1 } from 'node:fs/promises';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
3
4
|
import sirv from 'sirv';
|
|
4
5
|
import { coverageConfigDefaults } from 'vitest/config';
|
|
5
6
|
import { slash } from '@vitest/utils';
|
|
6
7
|
import fs, { promises } from 'node:fs';
|
|
7
|
-
import { resolve as resolve$1, dirname } from 'node:path';
|
|
8
|
+
import { resolve as resolve$1, dirname as dirname$1 } from 'node:path';
|
|
8
9
|
import { isFileServingAllowed } from 'vitest/node';
|
|
9
10
|
import MagicString from 'magic-string';
|
|
10
11
|
import { esmWalker } from '@vitest/utils/ast';
|
|
@@ -154,32 +155,56 @@ function normalizeString(path, allowAboveRoot) {
|
|
|
154
155
|
const isAbsolute = function(p) {
|
|
155
156
|
return _IS_ABSOLUTE_RE.test(p);
|
|
156
157
|
};
|
|
158
|
+
const dirname = function(p) {
|
|
159
|
+
const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
|
|
160
|
+
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) {
|
|
161
|
+
segments[0] += "/";
|
|
162
|
+
}
|
|
163
|
+
return segments.join("/") || (isAbsolute(p) ? "/" : ".");
|
|
164
|
+
};
|
|
157
165
|
const basename = function(p, extension) {
|
|
158
166
|
const lastSegment = normalizeWindowsPath(p).split("/").pop();
|
|
159
167
|
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
160
168
|
};
|
|
161
169
|
|
|
170
|
+
const click = async ({ provider }, element, options = {}) => {
|
|
171
|
+
if (provider.name === "playwright") {
|
|
172
|
+
const page = provider.page;
|
|
173
|
+
await page.frameLocator("iframe[data-vitest]").locator(`xpath=${element}`).click(options);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (provider.name === "webdriverio") {
|
|
177
|
+
const page = provider.browser;
|
|
178
|
+
const frame = await page.findElement("css selector", "iframe[data-vitest]");
|
|
179
|
+
await page.switchToFrame(frame);
|
|
180
|
+
const xpath = `//${element}`;
|
|
181
|
+
await (await page.$(xpath)).click(options);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
throw new Error(`Provider "${provider.name}" doesn't support click command`);
|
|
185
|
+
};
|
|
186
|
+
|
|
162
187
|
function assertFileAccess(path, project) {
|
|
163
188
|
if (!isFileServingAllowed(path, project.server) && !isFileServingAllowed(path, project.ctx.server))
|
|
164
189
|
throw new Error(`Access denied to "${path}". See Vite config documentation for "server.fs": https://vitejs.dev/config/server-options.html#server-fs-strict.`);
|
|
165
190
|
}
|
|
166
191
|
const readFile = async ({ project, testPath = process.cwd() }, path, options = {}) => {
|
|
167
|
-
const filepath = resolve$1(dirname(testPath), path);
|
|
192
|
+
const filepath = resolve$1(dirname$1(testPath), path);
|
|
168
193
|
assertFileAccess(filepath, project);
|
|
169
194
|
if (typeof options === "object" && !options.encoding)
|
|
170
195
|
options.encoding = "utf-8";
|
|
171
196
|
return promises.readFile(filepath, options);
|
|
172
197
|
};
|
|
173
198
|
const writeFile = async ({ project, testPath = process.cwd() }, path, data, options) => {
|
|
174
|
-
const filepath = resolve$1(dirname(testPath), path);
|
|
199
|
+
const filepath = resolve$1(dirname$1(testPath), path);
|
|
175
200
|
assertFileAccess(filepath, project);
|
|
176
|
-
const dir = dirname(filepath);
|
|
201
|
+
const dir = dirname$1(filepath);
|
|
177
202
|
if (!fs.existsSync(dir))
|
|
178
203
|
await promises.mkdir(dir, { recursive: true });
|
|
179
204
|
await promises.writeFile(filepath, data, options);
|
|
180
205
|
};
|
|
181
206
|
const removeFile = async ({ project, testPath = process.cwd() }, path) => {
|
|
182
|
-
const filepath = resolve$1(dirname(testPath), path);
|
|
207
|
+
const filepath = resolve$1(dirname$1(testPath), path);
|
|
183
208
|
assertFileAccess(filepath, project);
|
|
184
209
|
await promises.rm(filepath);
|
|
185
210
|
};
|
|
@@ -255,11 +280,13 @@ var builtinCommands = {
|
|
|
255
280
|
readFile,
|
|
256
281
|
removeFile,
|
|
257
282
|
writeFile,
|
|
258
|
-
sendKeys
|
|
283
|
+
sendKeys,
|
|
284
|
+
__vitest_click: click
|
|
259
285
|
};
|
|
260
286
|
|
|
261
287
|
const VIRTUAL_ID_CONTEXT = "\0@vitest/browser/context";
|
|
262
288
|
const ID_CONTEXT = "@vitest/browser/context";
|
|
289
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
263
290
|
function BrowserContext(project) {
|
|
264
291
|
project.config.browser.commands ??= {};
|
|
265
292
|
for (const [name, command] of Object.entries(builtinCommands))
|
|
@@ -277,24 +304,28 @@ function BrowserContext(project) {
|
|
|
277
304
|
},
|
|
278
305
|
load(id) {
|
|
279
306
|
if (id === VIRTUAL_ID_CONTEXT)
|
|
280
|
-
return generateContextFile(project);
|
|
307
|
+
return generateContextFile.call(this, project);
|
|
281
308
|
}
|
|
282
309
|
};
|
|
283
310
|
}
|
|
284
|
-
function generateContextFile(project) {
|
|
311
|
+
async function generateContextFile(project) {
|
|
285
312
|
const commands = Object.keys(project.config.browser.commands ?? {});
|
|
286
313
|
const filepathCode = "__vitest_worker__.filepath || __vitest_worker__.current?.file?.filepath || undefined";
|
|
314
|
+
const provider = project.browserProvider;
|
|
287
315
|
const commandsCode = commands.map((command) => {
|
|
288
|
-
return ` ["${command}"]: (...args) => rpc().triggerCommand("${command}",
|
|
316
|
+
return ` ["${command}"]: (...args) => rpc().triggerCommand("${command}", filepath(), args),`;
|
|
289
317
|
}).join("\n");
|
|
318
|
+
const userEventNonProviderImport = await getUserEventImport(provider, this.resolve.bind(this));
|
|
290
319
|
return `
|
|
320
|
+
${userEventNonProviderImport}
|
|
321
|
+
const filepath = () => ${filepathCode}
|
|
291
322
|
const rpc = () => __vitest_worker__.rpc
|
|
292
323
|
const channel = new BroadcastChannel('vitest')
|
|
293
324
|
|
|
294
325
|
export const server = {
|
|
295
326
|
platform: ${JSON.stringify(process.platform)},
|
|
296
327
|
version: ${JSON.stringify(process.version)},
|
|
297
|
-
provider: ${JSON.stringify(
|
|
328
|
+
provider: ${JSON.stringify(provider.name)},
|
|
298
329
|
browser: ${JSON.stringify(project.config.browser.name)},
|
|
299
330
|
commands: {
|
|
300
331
|
${commandsCode}
|
|
@@ -308,7 +339,7 @@ export const page = {
|
|
|
308
339
|
viewport(width, height) {
|
|
309
340
|
const id = __vitest_browser_runner__.iframeId
|
|
310
341
|
channel.postMessage({ type: 'viewport', width, height, id })
|
|
311
|
-
return new Promise((resolve) => {
|
|
342
|
+
return new Promise((resolve, reject) => {
|
|
312
343
|
channel.addEventListener('message', function handler(e) {
|
|
313
344
|
if (e.data.type === 'viewport:done' && e.data.id === id) {
|
|
314
345
|
channel.removeEventListener('message', handler)
|
|
@@ -320,10 +351,56 @@ export const page = {
|
|
|
320
351
|
}
|
|
321
352
|
})
|
|
322
353
|
})
|
|
354
|
+
},
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export const userEvent = ${getUserEventScript(project)}
|
|
358
|
+
|
|
359
|
+
function convertElementToXPath(element) {
|
|
360
|
+
if (!element || !(element instanceof Element)) {
|
|
361
|
+
// TODO: better error message
|
|
362
|
+
throw new Error('Expected element to be an instance of Element')
|
|
363
|
+
}
|
|
364
|
+
return getPathTo(element)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function getPathTo(element) {
|
|
368
|
+
if (element.id !== '')
|
|
369
|
+
return \`id("\${element.id}")\`
|
|
370
|
+
|
|
371
|
+
if (!element.parentNode || element === document.documentElement)
|
|
372
|
+
return element.tagName
|
|
373
|
+
|
|
374
|
+
let ix = 0
|
|
375
|
+
const siblings = element.parentNode.childNodes
|
|
376
|
+
for (let i = 0; i < siblings.length; i++) {
|
|
377
|
+
const sibling = siblings[i]
|
|
378
|
+
if (sibling === element)
|
|
379
|
+
return \`\${getPathTo(element.parentNode)}/\${element.tagName}[\${ix + 1}]\`
|
|
380
|
+
if (sibling.nodeType === 1 && sibling.tagName === element.tagName)
|
|
381
|
+
ix++
|
|
323
382
|
}
|
|
324
383
|
}
|
|
325
384
|
`;
|
|
326
385
|
}
|
|
386
|
+
async function getUserEventImport(provider, resolve) {
|
|
387
|
+
if (provider.name !== "preview")
|
|
388
|
+
return "";
|
|
389
|
+
const resolved = await resolve("@testing-library/user-event", __dirname);
|
|
390
|
+
if (!resolved)
|
|
391
|
+
throw new Error(`Failed to resolve user-event package from ${__dirname}`);
|
|
392
|
+
return `import { userEvent as __vitest_user_event__ } from '${slash(`/@fs/${resolved.id}`)}'`;
|
|
393
|
+
}
|
|
394
|
+
function getUserEventScript(project) {
|
|
395
|
+
if (project.browserProvider?.name === "preview")
|
|
396
|
+
return `__vitest_user_event__`;
|
|
397
|
+
return `{
|
|
398
|
+
async click(element, options) {
|
|
399
|
+
const xpath = convertElementToXPath(element)
|
|
400
|
+
return rpc().triggerCommand('__vitest_click', filepath(), options ? [xpath, options] : [xpath]);
|
|
401
|
+
},
|
|
402
|
+
}`;
|
|
403
|
+
}
|
|
327
404
|
|
|
328
405
|
function automockModule(code, parse) {
|
|
329
406
|
const ast = parse(code);
|
|
@@ -598,8 +675,9 @@ var index = (project, base = "/") => {
|
|
|
598
675
|
return;
|
|
599
676
|
}
|
|
600
677
|
const decodedTestFile = decodeURIComponent(url.pathname.slice(testerPrefix.length));
|
|
601
|
-
const
|
|
602
|
-
const
|
|
678
|
+
const testFiles = await project.globTestFiles();
|
|
679
|
+
const tests = decodedTestFile === "__vitest_all__" || !testFiles.includes(decodedTestFile) ? "__vitest_browser_runner__.files" : JSON.stringify([decodedTestFile]);
|
|
680
|
+
const iframeId = JSON.stringify(decodedTestFile);
|
|
603
681
|
if (!testerScripts)
|
|
604
682
|
testerScripts = await formatScripts(project.config.browser.testerScripts, server);
|
|
605
683
|
const html = replacer(await testerHtml, {
|
|
@@ -643,25 +721,8 @@ var index = (project, base = "/") => {
|
|
|
643
721
|
name: "vitest:browser:tests",
|
|
644
722
|
enforce: "pre",
|
|
645
723
|
async config() {
|
|
646
|
-
const {
|
|
647
|
-
include,
|
|
648
|
-
exclude,
|
|
649
|
-
includeSource,
|
|
650
|
-
dir,
|
|
651
|
-
root
|
|
652
|
-
} = project.config;
|
|
653
|
-
const projectRoot = dir || root;
|
|
654
|
-
const entries = await project.globAllTestFiles(include, exclude, includeSource, projectRoot);
|
|
655
724
|
return {
|
|
656
725
|
optimizeDeps: {
|
|
657
|
-
entries: [
|
|
658
|
-
...entries,
|
|
659
|
-
"vitest",
|
|
660
|
-
"vitest/utils",
|
|
661
|
-
"vitest/browser",
|
|
662
|
-
"vitest/runners",
|
|
663
|
-
"@vitest/utils"
|
|
664
|
-
],
|
|
665
726
|
exclude: [
|
|
666
727
|
"vitest",
|
|
667
728
|
"vitest/utils",
|
|
@@ -671,6 +732,7 @@ var index = (project, base = "/") => {
|
|
|
671
732
|
"std-env",
|
|
672
733
|
"tinybench",
|
|
673
734
|
"tinyspy",
|
|
735
|
+
"pathe",
|
|
674
736
|
// loupe is manually transformed
|
|
675
737
|
"loupe"
|
|
676
738
|
],
|
|
@@ -678,11 +740,14 @@ var index = (project, base = "/") => {
|
|
|
678
740
|
"vitest > @vitest/utils > pretty-format",
|
|
679
741
|
"vitest > @vitest/snapshot > pretty-format",
|
|
680
742
|
"vitest > @vitest/snapshot > magic-string",
|
|
681
|
-
"vitest > diff-sequences",
|
|
682
743
|
"vitest > pretty-format",
|
|
683
744
|
"vitest > pretty-format > ansi-styles",
|
|
684
745
|
"vitest > pretty-format > ansi-regex",
|
|
685
|
-
"vitest > chai"
|
|
746
|
+
"vitest > chai",
|
|
747
|
+
"vitest > @vitest/runner > p-limit",
|
|
748
|
+
"vitest > @vitest/utils > diff-sequences",
|
|
749
|
+
"@vitest/browser > @testing-library/user-event",
|
|
750
|
+
"@vitest/browser > @testing-library/dom"
|
|
686
751
|
]
|
|
687
752
|
}
|
|
688
753
|
};
|
|
@@ -708,7 +773,31 @@ export default globalThis.loupe`;
|
|
|
708
773
|
}
|
|
709
774
|
},
|
|
710
775
|
BrowserContext(project),
|
|
711
|
-
DynamicImport()
|
|
776
|
+
DynamicImport(),
|
|
777
|
+
// TODO: remove this when @testing-library/vue supports ESM
|
|
778
|
+
{
|
|
779
|
+
name: "vitest:browser:support-vue-testing-library",
|
|
780
|
+
config() {
|
|
781
|
+
return {
|
|
782
|
+
optimizeDeps: {
|
|
783
|
+
esbuildOptions: {
|
|
784
|
+
plugins: [
|
|
785
|
+
{
|
|
786
|
+
name: "test-utils-rewrite",
|
|
787
|
+
setup(build) {
|
|
788
|
+
const _require = createRequire(import.meta.url);
|
|
789
|
+
build.onResolve({ filter: /@vue\/test-utils/ }, (args) => {
|
|
790
|
+
const resolved = _require.resolve(args.path, { paths: [args.importer] });
|
|
791
|
+
return { path: resolved };
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
]
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
}
|
|
712
801
|
];
|
|
713
802
|
};
|
|
714
803
|
function resolveCoverageFolder(project) {
|
package/dist/providers.js
CHANGED
|
@@ -104,8 +104,8 @@ class WebdriverBrowserProvider {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
class
|
|
108
|
-
name = "
|
|
107
|
+
class PreviewBrowserProvider {
|
|
108
|
+
name = "preview";
|
|
109
109
|
ctx;
|
|
110
110
|
open = false;
|
|
111
111
|
getSupportedBrowsers() {
|
|
@@ -118,7 +118,7 @@ class NoneBrowserProvider {
|
|
|
118
118
|
this.ctx = ctx;
|
|
119
119
|
this.open = false;
|
|
120
120
|
if (ctx.config.browser.headless)
|
|
121
|
-
throw new Error(`You've enabled headless mode for "
|
|
121
|
+
throw new Error(`You've enabled headless mode for "preview" provider but it doesn't support it. Use "playwright" or "webdriverio" instead: https://vitest.dev/guide/browser#configuration`);
|
|
122
122
|
}
|
|
123
123
|
async openPage(_url) {
|
|
124
124
|
this.open = true;
|
|
@@ -136,6 +136,6 @@ class NoneBrowserProvider {
|
|
|
136
136
|
|
|
137
137
|
const webdriverio = WebdriverBrowserProvider;
|
|
138
138
|
const playwright = PlaywrightBrowserProvider;
|
|
139
|
-
const
|
|
139
|
+
const preview = PreviewBrowserProvider;
|
|
140
140
|
|
|
141
|
-
export {
|
|
141
|
+
export { playwright, preview, webdriverio };
|
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.7",
|
|
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.7"
|
|
51
51
|
},
|
|
52
52
|
"peerDependenciesMeta": {
|
|
53
53
|
"playwright": {
|
|
@@ -61,9 +61,11 @@
|
|
|
61
61
|
}
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
+
"@testing-library/dom": "^9.3.3",
|
|
65
|
+
"@testing-library/user-event": "^14.5.2",
|
|
64
66
|
"magic-string": "^0.30.10",
|
|
65
67
|
"sirv": "^2.0.4",
|
|
66
|
-
"@vitest/utils": "2.0.0-beta.
|
|
68
|
+
"@vitest/utils": "2.0.0-beta.7"
|
|
67
69
|
},
|
|
68
70
|
"devDependencies": {
|
|
69
71
|
"@types/ws": "^8.5.10",
|
|
@@ -75,10 +77,10 @@
|
|
|
75
77
|
"playwright-core": "^1.44.0",
|
|
76
78
|
"safaridriver": "^0.1.2",
|
|
77
79
|
"webdriverio": "^8.36.1",
|
|
78
|
-
"@vitest/
|
|
79
|
-
"
|
|
80
|
-
"@vitest/
|
|
81
|
-
"vitest": "2.0.0-beta.
|
|
80
|
+
"@vitest/ws-client": "2.0.0-beta.7",
|
|
81
|
+
"vitest": "2.0.0-beta.7",
|
|
82
|
+
"@vitest/runner": "2.0.0-beta.7",
|
|
83
|
+
"@vitest/ui": "2.0.0-beta.7"
|
|
82
84
|
},
|
|
83
85
|
"scripts": {
|
|
84
86
|
"build": "rimraf dist && pnpm build:node && pnpm build:client",
|
package/providers.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserProviderModule } from 'vitest/node'
|
|
2
2
|
|
|
3
|
-
declare const webdriverio:
|
|
4
|
-
declare const playwright:
|
|
5
|
-
declare const
|
|
3
|
+
declare const webdriverio: BrowserProviderModule
|
|
4
|
+
declare const playwright: BrowserProviderModule
|
|
5
|
+
declare const preview: BrowserProviderModule
|
|
6
6
|
|
|
7
|
-
export { webdriverio, playwright,
|
|
7
|
+
export { webdriverio, playwright, preview }
|