Skip to content

Commit

Permalink
feat(browser): move page.config to server.config, add more docs (#6252)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Jul 31, 2024
1 parent 1da6ceb commit af2b813
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 88 deletions.
15 changes: 5 additions & 10 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,16 +257,6 @@ export default ({ mode }: { mode: string }) => {
link: '/guide/browser/',
collapsed: false,
items: [
{
text: 'Assertion API',
link: '/guide/browser/assertion-api',
docFooterText: 'Assertion API | Browser Mode',
},
{
text: 'Retry-ability',
link: '/guide/browser/retry-ability',
docFooterText: 'Retry-ability | Browser Mode',
},
{
text: 'Context',
link: '/guide/browser/context',
Expand All @@ -277,6 +267,11 @@ export default ({ mode }: { mode: string }) => {
link: '/guide/browser/interactivity-api',
docFooterText: 'Interactivity API | Browser Mode',
},
{
text: 'Assertion API',
link: '/guide/browser/assertion-api',
docFooterText: 'Assertion API | Browser Mode',
},
{
text: 'Commands',
link: '/guide/browser/commands',
Expand Down
32 changes: 32 additions & 0 deletions docs/guide/browser/assertion-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,35 @@ If you are using TypeScript or want to have correct type hints in `expect`, make
}
```
:::

Tests in the browser might fail inconsistently due to their asynchronous nature. Because of this, it is important to have a way to guarantee that assertions succeed even if the condition is delayed (by a timeout, network request, or animation, for example). For this purpose, Vitest provides retriable assertions out of the box via the [`expect.poll`](/api/expect#poll) and `expect.element` APIs:

```ts
import { expect, test } from 'vitest'
import { screen } from '@testing-library/dom'

test('error banner is rendered', async () => {
triggerError()

// @testing-library provides queries with built-in retry-ability
// It will try to find the banner until it's rendered
const banner = await screen.findByRole('alert', {
name: /error/i,
})

// Vitest provides `expect.element` with built-in retry-ability
// It will check `element.textContent` until it's equal to "Error!"
await expect.element(banner).toHaveTextContent('Error!')
})
```

::: tip
`expect.element` is a shorthand for `expect.poll(() => element)` and works in exactly the same way.

`toHaveTextContent` and all other [`@testing-library/jest-dom`](https://github.com/testing-library/jest-dom) assertions are still available on a regular `expect` without a built-in retry-ability mechanism:

```ts
// will fail immediately if .textContent is not `'Error!'`
expect(banner).toHaveTextContent('Error!')
```
:::
98 changes: 69 additions & 29 deletions docs/guide/browser/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,13 @@ title: Context | Browser Mode

Vitest exposes a context module via `@vitest/browser/context` entry point. As of 2.0, it exposes a small set of utilities that might be useful to you in tests.

```ts
export const server: {
/**
* Platform the Vitest server is running on.
* The same as calling `process.platform` on the server.
*/
platform: Platform
/**
* Runtime version of the Vitest server.
* The same as calling `process.version` on the server.
*/
version: string
/**
* Name of the browser provider.
*/
provider: string
/**
* Name of the current browser.
*/
browser: string
/**
* Available commands for the browser.
*/
commands: BrowserCommands
}
## `userEvent`

::: tip
The `userEvent` API is explained in detail at [Interactivity API](/guide/browser/interactivity-api).
:::

```ts
/**
* Handler for user interactions. The support is implemented by the browser provider (`playwright` or `webdriverio`).
* If used with `preview` provider, fallbacks to simulated events via `@testing-library/user-event`.
Expand All @@ -56,18 +37,32 @@ export const userEvent: {
fill: (element: Element, text: string, options?: UserEventFillOptions) => Promise<void>
dragAndDrop: (source: Element, target: Element, options?: UserEventDragAndDropOptions) => Promise<void>
}
```
## `commands`
::: tip
Commands API is explained in detail at [Commands](/guide/browser/commands).
:::
```ts
/**
* Available commands for the browser.
* A shortcut to `server.commands`.
*/
export const commands: BrowserCommands
```
## `page`
The `page` export provides utilities to interact with the current `page`.
::: warning
While it exposes some utilities from Playwright's `page`, it is not the same object. Since the browser context is evaluated in the browser, your tests don't have access to Playwright's `page` because it runs on the server.
:::
```ts
export const page: {
/**
* Serialized test config.
*/
config: SerializedConfig
/**
* Change the size of iframe's viewport.
*/
Expand All @@ -82,6 +77,51 @@ export const page: {
}>
screenshot(options?: ScreenshotOptions): Promise<string>
}
```
## `cdp`
The `cdp` export returns the current Chrome DevTools Protocol session. It is mostly useful to library authors to build tools on top of it.
::: warning
CDP session works only with `playwright` provider and only when using `chromium` browser. You can read more about it in playwright's [`CDPSession`](https://playwright.dev/docs/api/class-cdpsession) documentation.
:::
```ts
export const cdp: () => CDPSession
```
## `server`
The `server` export represents the Node.js environment where the Vitest server is running. It is mostly useful for debugging.
```ts
export const server: {
/**
* Platform the Vitest server is running on.
* The same as calling `process.platform` on the server.
*/
platform: Platform
/**
* Runtime version of the Vitest server.
* The same as calling `process.version` on the server.
*/
version: string
/**
* Name of the browser provider.
*/
provider: string
/**
* Name of the current browser.
*/
browser: string
/**
* Available commands for the browser.
*/
commands: BrowserCommands
/**
* Serialized test config.
*/
config: SerializedConfig
}
```
6 changes: 6 additions & 0 deletions docs/guide/browser/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,14 @@ bun add -D vitest @vitest/browser

::: warning
However, to run tests in CI you need to install either [`playwright`](https://npmjs.com/package/playwright) or [`webdriverio`](https://www.npmjs.com/package/webdriverio). We also recommend switching to either one of them for testing locally instead of using the default `preview` provider since it relies on simulating events instead of using Chrome DevTools Protocol.

If you don't already use one of these tools, we recommend starting with Playwright because it supports parallel execution, which makes your tests run faster. Additionally, the Chrome DevTools Protocol that Playwright uses is generally faster than WebDriver.
:::

### Using Playwright

[Playwright](https://npmjs.com/package/playwright) is a framework for Web Testing and Automation.

::: code-group
```bash [npm]
npm install -D vitest @vitest/browser playwright
Expand All @@ -68,6 +72,8 @@ bun add -D vitest @vitest/browser playwright

### Using Webdriverio

[WebdriverIO](https://www.npmjs.com/package/webdriverio) allows you to run tests locally using the WebDriver protocol.

::: code-group
```bash [npm]
npm install -D vitest @vitest/browser webdriverio
Expand Down
37 changes: 0 additions & 37 deletions docs/guide/browser/retry-ability.md

This file was deleted.

8 changes: 4 additions & 4 deletions packages/browser/context.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ export const server: {
* @see {@link https://vitest.dev/guide/browser/commands}
*/
commands: BrowserCommands
/**
* Serialized test config.
*/
config: SerializedConfig
}

/**
Expand All @@ -250,10 +254,6 @@ export const userEvent: UserEvent
export const commands: BrowserCommands

export interface BrowserPage {
/**
* Serialized test config.
*/
config: SerializedConfig
/**
* Change the size of iframe's viewport.
*/
Expand Down
3 changes: 0 additions & 3 deletions packages/browser/src/client/tester/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,6 @@ export function cdp() {

const screenshotIds: Record<string, Record<string, string>> = {}
export const page: BrowserPage = {
get config() {
return runner().config
},
viewport(width, height) {
const id = runner().iframeId
channel.postMessage({ type: 'viewport', width, height, id })
Expand Down
3 changes: 2 additions & 1 deletion packages/browser/src/node/plugins/pluginContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ export const server = {
browser: ${JSON.stringify(server.project.config.browser.name)},
commands: {
${commandsCode}
}
},
config: __vitest_browser_runner__.config,
}
export const commands = server.commands
export const userEvent = ${getUserEvent(provider)}
Expand Down
8 changes: 4 additions & 4 deletions test/browser/test/viewport.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { page, server } from '@vitest/browser/context'
import { server } from '@vitest/browser/context'
import { describe, expect, it } from 'vitest'

describe.skipIf(server.provider === 'preview')('viewport window has been properly initialized', () => {
it.skipIf(!page.config.browser.headless)('viewport has proper size', () => {
const { width, height } = page.config.browser.viewport
it.skipIf(!server.config.browser.headless)('viewport has proper size', () => {
const { width, height } = server.config.browser.viewport
const { width: actualWidth, height: actualHeight } = window.document.documentElement.getBoundingClientRect()

expect(actualWidth).toBe(width)
expect(actualHeight).toBe(height)
})

it.skipIf(page.config.browser.headless)('window has been maximized', () => {
it.skipIf(server.config.browser.headless)('window has been maximized', () => {
let topWindow = window
while (topWindow.parent && topWindow !== topWindow.parent) {
topWindow = topWindow.parent as unknown as any
Expand Down

0 comments on commit af2b813

Please sign in to comment.