@vitest/browser-preview 4.0.0-beta.14
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/README.md +49 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +149 -0
- package/dist/locators.js +78 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @vitest/browser-preview
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@vitest/browser-preview)
|
|
4
|
+
|
|
5
|
+
See how your tests look like in a real browser. For proper and stable browser testing, we recommend running tests in a headless browser in your CI instead. For this, you should use either:
|
|
6
|
+
|
|
7
|
+
- [@vitest/browser-playwright](https://www.npmjs.com/package/@vitest/browser-playwright) - run tests using [playwright](https://playwright.dev/)
|
|
8
|
+
- [@vitest/browser-webdriverio](https://www.npmjs.com/package/@vitest/browser-webdriverio) - run tests using [webdriverio](https://webdriver.io/)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Install the package with your favorite package manager:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install -D @vitest/browser-preview
|
|
16
|
+
# or
|
|
17
|
+
yarn add -D @vitest/browser-preview
|
|
18
|
+
# or
|
|
19
|
+
pnpm add -D @vitest/browser-preview
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then specify it in the `browser.provider` field of your Vitest configuration:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
// vitest.config.ts
|
|
26
|
+
import { defineConfig } from 'vitest/config'
|
|
27
|
+
import { preview } from '@vitest/browser-preview'
|
|
28
|
+
|
|
29
|
+
export default defineConfig({
|
|
30
|
+
test: {
|
|
31
|
+
browser: {
|
|
32
|
+
provider: preview(),
|
|
33
|
+
instances: [
|
|
34
|
+
{ name: 'chromium' },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then run Vitest in the browser mode:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
npx vitest --browser
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If browser didn't open automatically, follow the link in the terminal to open the browser preview.
|
|
48
|
+
|
|
49
|
+
[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/browser-preview) | [Documentation](https://vitest.dev/guide/browser/)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BrowserProviderOption, BrowserProvider, TestProject } from 'vitest/node';
|
|
2
|
+
export { defineBrowserCommand } from '@vitest/browser';
|
|
3
|
+
|
|
4
|
+
declare function preview(): BrowserProviderOption;
|
|
5
|
+
declare class PreviewBrowserProvider implements BrowserProvider {
|
|
6
|
+
name: "preview";
|
|
7
|
+
supportsParallelism: boolean;
|
|
8
|
+
private project;
|
|
9
|
+
private open;
|
|
10
|
+
distRoot: string;
|
|
11
|
+
initScripts: string[];
|
|
12
|
+
constructor(project: TestProject);
|
|
13
|
+
isOpen(): boolean;
|
|
14
|
+
getCommandsContext(): {};
|
|
15
|
+
openPage(_sessionId: string, url: string): Promise<void>;
|
|
16
|
+
close(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { PreviewBrowserProvider, preview };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { nextTick } from 'node:process';
|
|
2
|
+
import { defineBrowserProvider } from '@vitest/browser';
|
|
3
|
+
export { defineBrowserCommand } from '@vitest/browser';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
7
|
+
function normalizeWindowsPath(input = "") {
|
|
8
|
+
if (!input) {
|
|
9
|
+
return input;
|
|
10
|
+
}
|
|
11
|
+
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
12
|
+
}
|
|
13
|
+
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
14
|
+
function cwd() {
|
|
15
|
+
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
16
|
+
return process.cwd().replace(/\\/g, "/");
|
|
17
|
+
}
|
|
18
|
+
return "/";
|
|
19
|
+
}
|
|
20
|
+
const resolve = function(...arguments_) {
|
|
21
|
+
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
22
|
+
let resolvedPath = "";
|
|
23
|
+
let resolvedAbsolute = false;
|
|
24
|
+
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
25
|
+
const path = index >= 0 ? arguments_[index] : cwd();
|
|
26
|
+
if (!path || path.length === 0) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
resolvedPath = `${path}/${resolvedPath}`;
|
|
30
|
+
resolvedAbsolute = isAbsolute(path);
|
|
31
|
+
}
|
|
32
|
+
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
33
|
+
if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
|
|
34
|
+
return `/${resolvedPath}`;
|
|
35
|
+
}
|
|
36
|
+
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
37
|
+
};
|
|
38
|
+
function normalizeString(path, allowAboveRoot) {
|
|
39
|
+
let res = "";
|
|
40
|
+
let lastSegmentLength = 0;
|
|
41
|
+
let lastSlash = -1;
|
|
42
|
+
let dots = 0;
|
|
43
|
+
let char = null;
|
|
44
|
+
for (let index = 0; index <= path.length; ++index) {
|
|
45
|
+
if (index < path.length) {
|
|
46
|
+
char = path[index];
|
|
47
|
+
} else if (char === "/") {
|
|
48
|
+
break;
|
|
49
|
+
} else {
|
|
50
|
+
char = "/";
|
|
51
|
+
}
|
|
52
|
+
if (char === "/") {
|
|
53
|
+
if (lastSlash === index - 1 || dots === 1) ; else if (dots === 2) {
|
|
54
|
+
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
55
|
+
if (res.length > 2) {
|
|
56
|
+
const lastSlashIndex = res.lastIndexOf("/");
|
|
57
|
+
if (lastSlashIndex === -1) {
|
|
58
|
+
res = "";
|
|
59
|
+
lastSegmentLength = 0;
|
|
60
|
+
} else {
|
|
61
|
+
res = res.slice(0, lastSlashIndex);
|
|
62
|
+
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
63
|
+
}
|
|
64
|
+
lastSlash = index;
|
|
65
|
+
dots = 0;
|
|
66
|
+
continue;
|
|
67
|
+
} else if (res.length > 0) {
|
|
68
|
+
res = "";
|
|
69
|
+
lastSegmentLength = 0;
|
|
70
|
+
lastSlash = index;
|
|
71
|
+
dots = 0;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (allowAboveRoot) {
|
|
76
|
+
res += res.length > 0 ? "/.." : "..";
|
|
77
|
+
lastSegmentLength = 2;
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
if (res.length > 0) {
|
|
81
|
+
res += `/${path.slice(lastSlash + 1, index)}`;
|
|
82
|
+
} else {
|
|
83
|
+
res = path.slice(lastSlash + 1, index);
|
|
84
|
+
}
|
|
85
|
+
lastSegmentLength = index - lastSlash - 1;
|
|
86
|
+
}
|
|
87
|
+
lastSlash = index;
|
|
88
|
+
dots = 0;
|
|
89
|
+
} else if (char === "." && dots !== -1) {
|
|
90
|
+
++dots;
|
|
91
|
+
} else {
|
|
92
|
+
dots = -1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return res;
|
|
96
|
+
}
|
|
97
|
+
const isAbsolute = function(p) {
|
|
98
|
+
return _IS_ABSOLUTE_RE.test(p);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const pkgRoot = resolve(fileURLToPath(import.meta.url), "../..");
|
|
102
|
+
const distRoot = resolve(pkgRoot, "dist");
|
|
103
|
+
|
|
104
|
+
function preview() {
|
|
105
|
+
return defineBrowserProvider({
|
|
106
|
+
name: "preview",
|
|
107
|
+
providerFactory(project) {
|
|
108
|
+
return new PreviewBrowserProvider(project);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
class PreviewBrowserProvider {
|
|
113
|
+
name = "preview";
|
|
114
|
+
supportsParallelism = false;
|
|
115
|
+
project;
|
|
116
|
+
open = false;
|
|
117
|
+
distRoot = distRoot;
|
|
118
|
+
initScripts = [resolve(distRoot, "locators.js")];
|
|
119
|
+
constructor(project) {
|
|
120
|
+
this.project = project;
|
|
121
|
+
this.open = false;
|
|
122
|
+
if (project.config.browser.headless) {
|
|
123
|
+
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");
|
|
124
|
+
}
|
|
125
|
+
nextTick(() => {
|
|
126
|
+
project.vitest.logger.printBrowserBanner(project);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
isOpen() {
|
|
130
|
+
return this.open;
|
|
131
|
+
}
|
|
132
|
+
getCommandsContext() {
|
|
133
|
+
return {};
|
|
134
|
+
}
|
|
135
|
+
async openPage(_sessionId, url) {
|
|
136
|
+
this.open = true;
|
|
137
|
+
if (!this.project.browser) {
|
|
138
|
+
throw new Error("Browser is not initialized");
|
|
139
|
+
}
|
|
140
|
+
const options = this.project.browser.vite.config.server;
|
|
141
|
+
const _open = options.open;
|
|
142
|
+
options.open = url;
|
|
143
|
+
this.project.browser.vite.openBrowser();
|
|
144
|
+
options.open = _open;
|
|
145
|
+
}
|
|
146
|
+
async close() {}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export { PreviewBrowserProvider, preview };
|
package/dist/locators.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { selectorEngine, getByTitleSelector, getByTextSelector, getByPlaceholderSelector, getByAltTextSelector, getByTestIdSelector, getByRoleSelector, getByLabelSelector, Locator, convertElementToCssSelector } from '@vitest/browser/locators';
|
|
2
|
+
import { page, server, utils, userEvent } from 'vitest/browser';
|
|
3
|
+
import { __INTERNAL } from 'vitest/internal/browser';
|
|
4
|
+
|
|
5
|
+
class PreviewLocator extends Locator {
|
|
6
|
+
constructor(_pwSelector, _container) {
|
|
7
|
+
super();
|
|
8
|
+
this._pwSelector = _pwSelector;
|
|
9
|
+
this._container = _container;
|
|
10
|
+
}
|
|
11
|
+
get selector() {
|
|
12
|
+
const selectors = this.elements().map((element) => convertElementToCssSelector(element));
|
|
13
|
+
if (!selectors.length) {
|
|
14
|
+
throw utils.getElementError(this._pwSelector, this._container || document.body);
|
|
15
|
+
}
|
|
16
|
+
return selectors.join(", ");
|
|
17
|
+
}
|
|
18
|
+
click() {
|
|
19
|
+
return userEvent.click(this.element());
|
|
20
|
+
}
|
|
21
|
+
dblClick() {
|
|
22
|
+
return userEvent.dblClick(this.element());
|
|
23
|
+
}
|
|
24
|
+
tripleClick() {
|
|
25
|
+
return userEvent.tripleClick(this.element());
|
|
26
|
+
}
|
|
27
|
+
hover() {
|
|
28
|
+
return userEvent.hover(this.element());
|
|
29
|
+
}
|
|
30
|
+
unhover() {
|
|
31
|
+
return userEvent.unhover(this.element());
|
|
32
|
+
}
|
|
33
|
+
async fill(text) {
|
|
34
|
+
return userEvent.fill(this.element(), text);
|
|
35
|
+
}
|
|
36
|
+
async upload(file) {
|
|
37
|
+
return userEvent.upload(this.element(), file);
|
|
38
|
+
}
|
|
39
|
+
selectOptions(options) {
|
|
40
|
+
return userEvent.selectOptions(this.element(), options);
|
|
41
|
+
}
|
|
42
|
+
clear() {
|
|
43
|
+
return userEvent.clear(this.element());
|
|
44
|
+
}
|
|
45
|
+
locator(selector) {
|
|
46
|
+
return new PreviewLocator(`${this._pwSelector} >> ${selector}`, this._container);
|
|
47
|
+
}
|
|
48
|
+
elementLocator(element) {
|
|
49
|
+
return new PreviewLocator(selectorEngine.generateSelectorSimple(element), element);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
page.extend({
|
|
53
|
+
getByLabelText(text, options) {
|
|
54
|
+
return new PreviewLocator(getByLabelSelector(text, options));
|
|
55
|
+
},
|
|
56
|
+
getByRole(role, options) {
|
|
57
|
+
return new PreviewLocator(getByRoleSelector(role, options));
|
|
58
|
+
},
|
|
59
|
+
getByTestId(testId) {
|
|
60
|
+
return new PreviewLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute, testId));
|
|
61
|
+
},
|
|
62
|
+
getByAltText(text, options) {
|
|
63
|
+
return new PreviewLocator(getByAltTextSelector(text, options));
|
|
64
|
+
},
|
|
65
|
+
getByPlaceholder(text, options) {
|
|
66
|
+
return new PreviewLocator(getByPlaceholderSelector(text, options));
|
|
67
|
+
},
|
|
68
|
+
getByText(text, options) {
|
|
69
|
+
return new PreviewLocator(getByTextSelector(text, options));
|
|
70
|
+
},
|
|
71
|
+
getByTitle(title, options) {
|
|
72
|
+
return new PreviewLocator(getByTitleSelector(title, options));
|
|
73
|
+
},
|
|
74
|
+
elementLocator(element) {
|
|
75
|
+
return new PreviewLocator(selectorEngine.generateSelectorSimple(element), element);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
__INTERNAL._createLocator = (selector) => new PreviewLocator(selector);
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vitest/browser-preview",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "4.0.0-beta.14",
|
|
5
|
+
"description": "Browser running for Vitest using your browser of choice",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"funding": "https://opencollective.com/vitest",
|
|
8
|
+
"homepage": "https://vitest.dev/guide/browser",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/vitest-dev/vitest.git",
|
|
12
|
+
"directory": "packages/browser-preview"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/vitest-dev/vitest/issues"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./context": {
|
|
24
|
+
"types": "./context.d.ts"
|
|
25
|
+
},
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"module": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "premove dist && pnpm rollup -c",
|
|
36
|
+
"dev": "rollup -c --watch --watch.include 'src/**'"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"vitest": "workspace:*"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@testing-library/dom": "^10.4.1",
|
|
43
|
+
"@testing-library/user-event": "^14.6.1",
|
|
44
|
+
"@vitest/browser": "workspace:*"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"vitest": "workspace:*"
|
|
48
|
+
}
|
|
49
|
+
}
|