Skip to content

Commit 9cdc803

Browse files
Aslemammadchristian-bromannsheremet-vauserquindammy001
authored
feat: webdriverio (+ custom providers) integration for browser mode (#2999)
Co-authored-by: Christian Bromann <git@bromann.dev> Co-authored-by: Vladimir <sleuths.slews0s@icloud.com> Co-authored-by: userquin <userquin@gmail.com> Co-authored-by: Anjorin Damilare <damilareanjorin1@gmail.com>
1 parent cc5779d commit 9cdc803

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1505
-158
lines changed

.github/workflows/ci.yml

+58
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,61 @@ jobs:
101101

102102
- name: Test UI
103103
run: pnpm run ui:test
104+
105+
test-browser:
106+
runs-on: ubuntu-latest
107+
strategy:
108+
matrix:
109+
browser: [chrome, firefox, edge]
110+
111+
timeout-minutes: 10
112+
113+
env:
114+
BROWSER: ${{ matrix.browser }}
115+
steps:
116+
- uses: actions/checkout@v3
117+
118+
- uses: ./.github/actions/setup-and-cache
119+
with:
120+
node-version: 18
121+
122+
- uses: browser-actions/setup-chrome@v1
123+
- uses: browser-actions/setup-firefox@v1
124+
- uses: browser-actions/setup-edge@v1
125+
126+
- name: Install
127+
run: pnpm i
128+
129+
- name: Build
130+
run: pnpm run build
131+
132+
- name: Test Browser
133+
run: pnpm run browser:test
134+
135+
test-browser-safari:
136+
runs-on: macos-latest
137+
timeout-minutes: 10
138+
139+
env:
140+
BROWSER: safari
141+
steps:
142+
- uses: actions/checkout@v3
143+
144+
- uses: ./.github/actions/setup-and-cache
145+
with:
146+
node-version: 18
147+
148+
- name: Info
149+
run: system_profiler SPSoftwareDataType
150+
151+
- name: Install
152+
run: pnpm i
153+
154+
- name: Build
155+
run: pnpm run build
156+
157+
- name: Enable
158+
run: sudo safaridriver --enable
159+
160+
- name: Test Browser
161+
run: sudo pnpm run browser:test

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ltex*
1616
.DS_Store
1717
bench/test/*/*/
1818
**/benchmark/bench.json
19+
**/browser/browser.json
1920
cypress/videos
2021
cypress/downloads
2122
cypress/screenshots

docs/.vitepress/config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ export default withPwa(defineConfig({
175175
text: 'Vitest UI',
176176
link: '/guide/ui',
177177
},
178+
{
179+
text: 'Browser Mode',
180+
link: '/guide/browser',
181+
},
178182
{
179183
text: 'In-source Testing',
180184
link: '/guide/in-source',

docs/config/index.md

+78-2
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ export default defineConfig({
383383

384384
### poolMatchGlobs
385385

386-
- **Type:** `[string, 'threads' | 'child_process'][]`
386+
- **Type:** `[string, 'browser' | 'threads' | 'child_process'][]`
387387
- **Default:** `[]`
388388
- **Version:** Since Vitest 0.29.4
389389

@@ -399,7 +399,9 @@ export default defineConfig({
399399
poolMatchGlobs: [
400400
// all tests in "worker-specific" directory will run inside a worker as if you enabled `--threads` for them,
401401
['**/tests/worker-specific/**', 'threads'],
402-
// all other tests will run based on "threads" option, if you didn't specify other globs
402+
// run all tests in "browser" directory in an actual browser
403+
['**/tests/browser/**', 'browser'],
404+
// all other tests will run based on "browser.enabled" and "threads" options, if you didn't specify other globs
403405
// ...
404406
]
405407
}
@@ -992,6 +994,80 @@ Open Vitest UI (WIP)
992994

993995
Listen to port and serve API. When set to true, the default port is 51204
994996

997+
### browser
998+
999+
- **Type:** `{ enabled?, name?, provider?, headless?, api? }`
1000+
- **Default:** `{ enabled: false, headless: process.env.CI, api: 63315 }`
1001+
- **Version:** Since Vitest 0.30.0
1002+
- **CLI:** `--browser`, `--browser=<name>`, `--browser.name=chrome --browser.headless`
1003+
1004+
Run Vitest tests in a browser. If the browser name is not specified, Vitest will try to determine your default browser automatically. We use [WebdriverIO](https://webdriver.io/) for running tests by default, but it can be configured with [browser.provider](/config/#browser-provider) option.
1005+
1006+
::: tip NOTE
1007+
Read more about testing in a real browser in the [guide page](/guide/browser).
1008+
:::
1009+
1010+
::: warning
1011+
This is an experimental feature. Breaking changes might not follow semver, please pin Vitest's version when using it.
1012+
:::
1013+
1014+
#### browser.enabled
1015+
1016+
- **Type:** `boolean`
1017+
- **Default:** `false`
1018+
- **CLI:** `--browser`, `--browser.enabled=false`
1019+
1020+
Run all tests inside a browser by default. Can be overriden with [`poolMatchGlobs`](/config/#poolmatchglobs) option.
1021+
1022+
#### browser&#46;name
1023+
1024+
- **Type:** `string`
1025+
- **Default:** _tries to find default browser automatically_
1026+
- **CLI:** `--browser=safari`
1027+
1028+
Run all tests in a specific browser. If not specified, tries to find a browser automatically.
1029+
1030+
1031+
#### browser.headless
1032+
1033+
- **Type:** `boolean`
1034+
- **Default:** `process.env.CI`
1035+
- **CLI:** `--browser.headless`, `--brower.headless=false`
1036+
1037+
Run the browser in a `headless` mode. If you are running Vitest in CI, it will be enabled by default.
1038+
1039+
#### browser.api
1040+
1041+
- **Type:** `number | { port?, strictPort?, host? }`
1042+
- **Default:** `63315`
1043+
- **CLI:** `--browser.api=63315`, `--browser.api.port=1234, --browser.api.host=example.com`
1044+
1045+
Configure options for Vite server that serves code in the browser. Does not affect [`test.api`](/config/#api) option.
1046+
1047+
#### browser.provider
1048+
1049+
- **Type:** `string`
1050+
- **Default:** `'webdriverio'`
1051+
- **CLI:** `--browser.provider=./custom-provider.ts`
1052+
1053+
Path to a provider that will be used when running browser tests. Provider should be exported using `default` export and have this shape:
1054+
1055+
```ts
1056+
export interface BrowserProvider {
1057+
initialize(ctx: Vitest): Awaitable<void>
1058+
createPool(): {
1059+
runTests: (files: string[], invalidated: string[]) => void
1060+
close: () => Awaited<void>
1061+
}
1062+
// signals that test file stopped running, if it was opened with `id=` query
1063+
testFinished?(testId: string): Awaitable<void>
1064+
}
1065+
```
1066+
1067+
::: warning
1068+
This is an advanced API for library authors. If you just need to run tests in a browser, use the [browser](/config/#browser) option.
1069+
:::
1070+
9951071
### clearMocks
9961072

9971073
- **Type:** `boolean`

docs/guide/browser.md

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
title: Browser mode | Guide
3+
---
4+
5+
# Browser mode (experimental)
6+
7+
This page provides information about the experimental browser mode feature in the Vitest API, which allows you to run your tests in the browser natively, providing access to browser globals like window and document. This feature is currently under development, and APIs may change in the future.
8+
9+
## Configuration
10+
11+
To activate browser mode in your Vitest configuration, you can use the `--browser` flag or set the `browser.enabled` field to `true` in your Vitest configuration file. Here is an example configuration using the browser field:
12+
13+
```ts
14+
export default defineConfig({
15+
test: {
16+
browser: {
17+
enabled: true
18+
},
19+
}
20+
})
21+
```
22+
23+
## Browser Option Types:
24+
25+
The browser option in Vitest can be set to either a boolean or a string type. If set to `true`, Vitest will try to automatically find your default browser. You can also specify a browser by providing its name as a `string`. The available browser options are:
26+
- `firefox`
27+
- `chrome`
28+
- `edge`
29+
- `safari`
30+
31+
Here's an example configuration setting chrome as the browser option:
32+
33+
```ts
34+
export default defineConfig({
35+
test: {
36+
browser: {
37+
enabled: true,
38+
name: 'chrome',
39+
},
40+
}
41+
})
42+
```
43+
44+
## Cross-browser Testing:
45+
46+
When you specify a browser name in the browser option, Vitest will try to run the specified browser using [WebdriverIO](https://webdriver.io/) by default, and then run the tests there. This feature makes cross-browser testing easy to use and configure in environments like a CI. If you don't want to use WebdriverIO, you can configure the custom browser provider by using `browser.provider` option.
47+
48+
To specify a browser using the CLI, use the `--browser` flag followed by the browser name, like this:
49+
50+
```sh
51+
npx vitest --browser=chrome
52+
```
53+
54+
Or if you pass down several options, you dot-syntax:
55+
56+
```sh
57+
npx vitest --browser.name=chrome --browser.headless
58+
```
59+
60+
::: tip NOTE
61+
When using the Safari browser option, the `safaridriver` needs to be activated by running `sudo safaridriver --enable` on your device.
62+
63+
Additionally, when running your tests, Vitest will attempt to install some drivers for compatibility with `safaridriver`.
64+
:::
65+
66+
## Headless
67+
68+
Headless mode is another option available in the browser mode. In headless mode, the browser runs in the background without a user interface, which makes it useful for running automated tests. The headless option in Vitest can be set to a boolean value to enable or disable headless mode.
69+
70+
Here's an example configuration enabling headless mode:
71+
72+
```ts
73+
export default defineConfig({
74+
test: {
75+
browser: {
76+
enabled: true,
77+
headless: true,
78+
},
79+
}
80+
})
81+
```
82+
83+
You can also set headless mode using the `--browser.headless` flag in the CLI, like this:
84+
85+
```sh
86+
npx vitest --browser.name=chrome --browser.headless
87+
```
88+
89+
In this case, Vitest will run in headless mode using the Chrome browser.

docs/guide/cli.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Run only [benchmark](https://vitest.dev/guide/features.html#benchmarking-experim
8484
| `--mode <name>` | Override Vite mode (default: `test`) |
8585
| `--globals` | Inject APIs globally |
8686
| `--dom` | Mock browser api with happy-dom |
87-
| `--browser` | Run tests in browser |
87+
| `--browser [options]` | Run tests in [the browser](/guide/browser) (default: `false`) |
8888
| `--environment <env>` | Runner environment (default: `node`) |
8989
| `--passWithNoTests` | Pass when no tests found |
9090
| `--logHeapUsage` | Show the size of heap for each test |

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"description": "A blazing fast unit test framework powered by Vite",
88
"scripts": {
99
"ci": "ni && nr typecheck && nr lint && nr build && nr test:all",
10-
"build": "pnpm -r --filter='./packages/**' run build",
10+
"build": "pnpm -r --filter='./packages/**' run build && pnpm -C ./packages/browser run copy",
1111
"dev": "NODE_OPTIONS=\"--max-old-space-size=8192\" pnpm -r --parallel --filter='./packages/**' run dev",
1212
"docs": "pnpm -C docs run dev",
1313
"docs:build": "pnpm -C docs run build",
@@ -28,7 +28,8 @@
2828
"typecheck:why": "tsc --noEmit --explainFiles > explainTypes.txt",
2929
"ui:build": "vite build packages/ui",
3030
"ui:dev": "vite packages/ui",
31-
"ui:test": "npm -C packages/ui run test:run"
31+
"ui:test": "npm -C packages/ui run test:run",
32+
"browser:test": "npm -C test/browser run test"
3233
},
3334
"devDependencies": {
3435
"@antfu/eslint-config": "^0.34.1",

packages/browser/package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"stubs"
2525
],
2626
"scripts": {
27-
"build": "rimraf dist && pnpm build:node && pnpm build:client && pnpm copy",
27+
"build": "rimraf dist && pnpm build:node && pnpm build:client",
2828
"build:client": "vite build src/client",
2929
"build:node": "rollup -c",
3030
"dev:client": "vite build src/client --watch",
@@ -33,11 +33,14 @@
3333
"copy": "esno scripts/copy-ui-to-browser.ts",
3434
"prepublishOnly": "pnpm build"
3535
},
36+
"peerDependencies": {
37+
"vitest": ">=0.30.0"
38+
},
3639
"dependencies": {
3740
"@vitest/runner": "workspace:*",
3841
"local-pkg": "^0.4.2",
3942
"mlly": "^1.1.0",
40-
"modern-node-polyfills": "0.0.9",
43+
"modern-node-polyfills": "0.1.0",
4144
"rollup-plugin-node-polyfills": "^0.2.1",
4245
"sirv": "^2.0.2"
4346
},

0 commit comments

Comments
 (0)