Skip to content

Commit

Permalink
Merge branch 'main' into feature-vitest-ui-workspace-scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
DevJoaoLopes authored Jan 8, 2025
2 parents 5359168 + 57b671d commit b895c02
Show file tree
Hide file tree
Showing 124 changed files with 886 additions and 255 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@
"json",
"jsonc",
"yaml"
]
],
"testing.automaticallyOpenTestResults": "neverOpen"
}
2 changes: 1 addition & 1 deletion docs/advanced/api/vitest.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ This method doesn't trigger `onWatcherRerun`, `onWatcherStart` and `onTestsRerun
## rerunTestSpecifications

```ts
function runTestSpecifications(
function rerunTestSpecifications(
specifications: TestSpecification[],
allTestsRun = false
): Promise<TestRunResult>
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/guide/tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Breaking changes might not follow SemVer, please pin Vitest's version when using

Vitest exposes two methods to initiate Vitest:

- `startVitest` initiates Vitest, validates the packages are installed and runs tests immidiatly
- `startVitest` initiates Vitest, validates the packages are installed and runs tests immediately
- `createVitest` only initiates Vitest and doesn't run any tests

## `startVitest`
Expand Down
4 changes: 2 additions & 2 deletions docs/api/assert.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ Asserts that `value` is not null.
```ts
import { assert, test } from 'vitest'

const error = { message: 'error was occured' }
const error = { message: 'error was occurred' }

test('assert.isNotNull', () => {
assert.isNotNull(error, 'error is not null but object')
Expand All @@ -298,7 +298,7 @@ Asserts that `value` is NaN.
```ts
import { assert, test } from 'vitest'

const calculation = 1 * 'viitest'
const calculation = 1 * 'vitest'

test('assert.isNaN', () => {
assert.isNaN(calculation, '1 * "vitest" is NaN')
Expand Down
2 changes: 1 addition & 1 deletion docs/api/expect.md
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,7 @@ test('spy function resolves bananas on a last call', async () => {

- **Type**: `(time: number, returnValue: any) => Awaitable<void>`

You can call this assertion to check if a function has successfully resolved a certain value on a specific invokation. Requires a spy function to be passed to `expect`.
You can call this assertion to check if a function has successfully resolved a certain value on a specific invocation. Requires a spy function to be passed to `expect`.

If the function returned a promise, but it was not resolved yet, this will fail.

Expand Down
2 changes: 1 addition & 1 deletion docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,7 @@ Here the `afterAll` ensures that `stopMocking` method is called after all tests

## Test Hooks

Vitest provides a few hooks that you can call _during_ the test execution to cleanup the state when the test has finished runnning.
Vitest provides a few hooks that you can call _during_ the test execution to cleanup the state when the test has finished running.

::: warning
These hooks will throw an error if they are called outside of the test body.
Expand Down
32 changes: 29 additions & 3 deletions docs/api/vi.md
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ IntersectionObserver === undefined

## Fake Timers

This sections descibes how to work with [fake timers](/guide/mocking#timers).
This sections describes how to work with [fake timers](/guide/mocking#timers).

### vi.advanceTimersByTime

Expand Down Expand Up @@ -939,14 +939,40 @@ callFunctionWithSideEffect()
+ const { value } = await import('./some/module.js')
```

When running `vitest`, you can do this automatically by using `vi.hoisted` method.
When running `vitest`, you can do this automatically by using `vi.hoisted` method. Under the hood, Vitest will convert static imports into dynamic ones with preserved live-bindings.

```diff
- callFunctionWithSideEffect()
import { value } from './some/module.js'
+ vi.hoisted(() => callFunctionWithSideEffect())
```

::: warning IMPORTS ARE NOT AVAILABLE
Running code before the imports means that you cannot access imported variables because they are not defined yet:

```ts
import { value } from './some/module.js'

vi.hoisted(() => { value }) // throws an error // [!code warning]
```

This code will produce an error:

```
Cannot access '__vi_import_0__' before initialization
```

If you need to access a variable from another module inside of `vi.hoisted`, use dynamic import:

```ts
await vi.hoisted(async () => {
const { value } = await import('./some/module.js')
})
```

However, it is discourage to import anything inside of `vi.hoisted` because imports are already hoisted - if you need to execute something before the tests are running, just execute it in the imported module itself.
:::

This method returns the value that was returned from the factory. You can use that value in your `vi.mock` factories if you need easy access to locally defined variables:

```ts
Expand All @@ -968,7 +994,7 @@ expect(originalMethod()).toBe(100)
Note that this method can also be called asynchronously even if your environment doesn't support top-level await:

```ts
const promised = await vi.hoisted(async () => {
const json = await vi.hoisted(async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts')
return response.json()
})
Expand Down
4 changes: 2 additions & 2 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1069,15 +1069,15 @@ Minimum number or percentage of workers to run tests in. `poolOptions.{threads,v
- **Default:** `5_000` in Node.js, `15_000` if `browser.enabled` is `true`
- **CLI:** `--test-timeout=5000`, `--testTimeout=5000`

Default timeout of a test in milliseconds
Default timeout of a test in milliseconds. Use `0` to disable timeout completely.

### hookTimeout

- **Type:** `number`
- **Default:** `10_000` in Node.js, `30_000` if `browser.enabled` is `true`
- **CLI:** `--hook-timeout=10000`, `--hookTimeout=10000`

Default timeout of a hook in milliseconds
Default timeout of a hook in milliseconds. Use `0` to disable timeout completely.

### teardownTimeout<NonProjectOption />

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/browser/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Custom functions will override built-in ones if they have the same name.
Vitest exposes several `playwright` specific properties on the command context.

- `page` references the full page that contains the test iframe. This is the orchestrator HTML and you most likely shouldn't touch it to not break things.
- `frame` is an async method that will resolve tester [`Frame`](https://playwright.dev/docs/api/class-frame). It has a simillar API to the `page`, but it doesn't support certain methods. If you need to query an element, you should prefer using `context.iframe` instead because it is more stable and faster.
- `frame` is an async method that will resolve tester [`Frame`](https://playwright.dev/docs/api/class-frame). It has a similar API to the `page`, but it doesn't support certain methods. If you need to query an element, you should prefer using `context.iframe` instead because it is more stable and faster.
- `iframe` is a [`FrameLocator`](https://playwright.dev/docs/api/class-framelocator) that should be used to query other elements on the page.
- `context` refers to the unique [BrowserContext](https://playwright.dev/docs/api/class-browsercontext).

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/browser/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ List of available `browser` options:
- [`browser.screenshotDirectory`](#browser-screenshotdirectory)
- [`browser.screenshotFailures`](#browser-screenshotfailures)

By default, Vitest creates an array with a single element which uses the [`browser.name`](#browser-name) field as a `browser`. Note that this behaviour will be removed with Vitets 4.
By default, Vitest creates an array with a single element which uses the [`browser.name`](#browser-name) field as a `browser`. Note that this behaviour will be removed with Vitest 4.

Under the hood, Vitest transforms these instances into separate [test projects](/advanced/api/test-project) sharing a single Vite server for better caching performance.

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/browser/interactivity-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ test('update input', async () => {
```
::: info
Vitest doesn't expose `.type` method on the locator like `input.type` because it exists only for compatiblity with the `userEvent` library. Consider using `.fill` instead as it is faster.
Vitest doesn't expose `.type` method on the locator like `input.type` because it exists only for compatibility with the `userEvent` library. Consider using `.fill` instead as it is faster.
:::
References:
Expand Down
79 changes: 71 additions & 8 deletions docs/guide/browser/locators.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Providing roles via `role` or `aria-*` attributes to built-in elements that alre

- `exact: boolean`

Whether the `name` is matched exactly: case-sensetive and whole-string. Disabled by default. This option is ignored if `name` is a regular expression. Note that exact match still trims whitespace.
Whether the `name` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `name` is a regular expression. Note that exact match still trims whitespace.

```tsx
<button>Hello World</button>
Expand Down Expand Up @@ -213,7 +213,7 @@ page.getByAltText('non existing alt text') // ❌

- `exact: boolean`

Whether the `text` is matched exactly: case-sensetive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.

#### See also

Expand All @@ -228,7 +228,7 @@ function getByLabelText(
): Locator
```

Creates a locator capable of finding an element that has an assosiated label.
Creates a locator capable of finding an element that has an associated label.

The `page.getByLabelText('Username')` locator will find every input in the example bellow:

Expand Down Expand Up @@ -260,7 +260,7 @@ The `page.getByLabelText('Username')` locator will find every input in the examp

- `exact: boolean`

Whether the `text` is matched exactly: case-sensetive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.

#### See also

Expand Down Expand Up @@ -292,7 +292,7 @@ It is generally better to rely on a label using [`getByLabelText`](#getbylabelte

- `exact: boolean`

Whether the `text` is matched exactly: case-sensetive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.

#### See also

Expand Down Expand Up @@ -324,7 +324,7 @@ This locator is useful for locating non-interactive elements. If you need to loc

- `exact: boolean`

Whether the `text` is matched exactly: case-sensetive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.

#### See also

Expand Down Expand Up @@ -352,7 +352,7 @@ page.getByTitle('Create') // ❌

- `exact: boolean`

Whether the `text` is matched exactly: case-sensetive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.

#### See also

Expand Down Expand Up @@ -387,6 +387,69 @@ It is recommended to use this only after the other locators don't work for your

- [testing-library's `ByTestId`](https://testing-library.com/docs/queries/bytestid/)

## nth

```ts
function nth(index: number): Locator
```

This method returns a new locator that matches only a specific index within a multi-element query result. Unlike `elements()[n]`, the `nth` locator will be retried until the element is present.

```html
<div aria-label="one"><input/><input/><input/></div>
<div aria-label="two"><input/></div>
```

```tsx
page.getByRole('textbox').nth(0) // ✅
page.getByRole('textbox').nth(4) // ❌
```

::: tip
Before resorting to `nth`, you may find it useful to use chained locators to narrow down your search.
Sometimes there is no better way to distinguish than by element position; although this can lead to flake, it's better than nothing.
:::

```tsx
page.getByLabel('two').getByRole('input') // ✅ better alternative to page.getByRole('textbox').nth(3)
page.getByLabel('one').getByRole('input') // ❌ too ambiguous
page.getByLabel('one').getByRole('input').nth(1) // ✅ pragmatic compromise
```

## first

```ts
function first(): Locator
```

This method returns a new locator that matches only the first index of a multi-element query result.
It is sugar for `nth(0)`.

```html
<input/> <input/> <input/>
```

```tsx
page.getByRole('textbox').first() // ✅
```

## last

```ts
function last(): Locator
```

This method returns a new locator that matches only the last index of a multi-element query result.
It is sugar for `nth(-1)`.

```html
<input/> <input/> <input/>
```

```tsx
page.getByRole('textbox').last() // ✅
```

## Methods

All methods are asynchronous and must be awaited. Since Vitest 3, tests will fail if a method is not awaited.
Expand Down Expand Up @@ -596,7 +659,7 @@ function query(): Element | null

This method returns a single element matching the locator's selector or `null` if no element is found.

If multilple elements match the selector, this method will throw an error. Use [`.elements()`](#elements) when you need all matching DOM Elements or [`.all()`](#all) if you need an array of locators matching the selector.
If multiple elements match the selector, this method will throw an error. Use [`.elements()`](#elements) when you need all matching DOM Elements or [`.all()`](#all) if you need an array of locators matching the selector.

Consider the following DOM structure:

Expand Down
11 changes: 9 additions & 2 deletions docs/guide/cli-generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@ Show Vitest UI when running tests (default: `!process.env.CI`)

Should browser test files run in parallel. Use `--browser.fileParallelism=false` to disable (default: `true`)

### browser.connectTimeout

- **CLI:** `--browser.connectTimeout <timeout>`
- **Config:** [browser.connectTimeout](/guide/browser/config#browser-connecttimeout)

If connection to the browser takes longer, the test suite will fail (default: `60_000`)

### pool

- **CLI:** `--pool <pool>`
Expand Down Expand Up @@ -654,14 +661,14 @@ Enable Node.js inspector and break before the test starts
- **CLI:** `--testTimeout <timeout>`
- **Config:** [testTimeout](/config/#testtimeout)

Default timeout of a test in milliseconds (default: `5000`)
Default timeout of a test in milliseconds (default: `5000`). Use `0` to disable timeout completely.

### hookTimeout

- **CLI:** `--hookTimeout <timeout>`
- **Config:** [hookTimeout](/config/#hooktimeout)

Default hook timeout in milliseconds (default: `10000`)
Default hook timeout in milliseconds (default: `10000`). Use `0` to disable timeout completely.

### bail

Expand Down
6 changes: 5 additions & 1 deletion docs/guide/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ title: Debugging | Guide
# Debugging

:::tip
When debugging tests you might want to use `--test-timeout` CLI argument to prevent tests from timing out when stopping at breakpoints.
When debugging tests you might want to use following options:

- [`--test-timeout=0`](/guide/cli#testtimeout) to prevent tests from timing out when stopping at breakpoints
- [`--no-file-parallelism`](/guide/cli#fileparallelism) to prevent test files from running parallel

:::

## VS Code
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/mocking.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ When writing tests it's only a matter of time before you need to create a "fake"
Always remember to clear or restore mocks before or after each test run to undo mock state changes between runs! See [`mockReset`](/api/mock#mockreset) docs for more info.
:::

If you are not familliar with `vi.fn`, `vi.mock` or `vi.spyOn` methods, check the [API section](/api/vi) first.
If you are not familiar with `vi.fn`, `vi.mock` or `vi.spyOn` methods, check the [API section](/api/vi) first.

## Dates

Expand Down Expand Up @@ -479,7 +479,7 @@ afterAll(() => server.close())
afterEach(() => server.resetHandlers())
```

> Configuring the server with `onUnhandleRequest: 'error'` ensures that an error is thrown whenever there is a request that does not have a corresponding request handler.
> Configuring the server with `onUnhandledRequest: 'error'` ensures that an error is thrown whenever there is a request that does not have a corresponding request handler.
### More
There is much more to MSW. You can access cookies and query parameters, define mock error responses, and much more! To see all you can do with MSW, read [their documentation](https://mswjs.io/docs).
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/reporters.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ export default defineConfig({
### Blob Reporter

Stores test results on the machine so they can be later merged using [`--merge-reports`](/guide/cli#merge-reports) command.
By default, stores all results in `.vitest-reports` folder, but can be overriden with `--outputFile` or `--outputFile.blob` flags.
By default, stores all results in `.vitest-reports` folder, but can be overridden with `--outputFile` or `--outputFile.blob` flags.

```bash
npx vitest --reporter=blob --outputFile=reports/blob-1.json
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/test-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ const test = base.extend({
url: [
// default value if "url" is not defined in the config
'default',
// mark the fixure as "injected" to allow the override
// mark the fixture as "injected" to allow the override
{ injected: true },
],
})
Expand Down
Loading

0 comments on commit b895c02

Please sign in to comment.