diff --git a/api/browser/locators.md b/api/browser/locators.md index a63c04b1..023a8bc1 100644 --- a/api/browser/locators.md +++ b/api/browser/locators.md @@ -12,6 +12,29 @@ outline: [2, 3] ::: tip 本页介绍了 API 的使用。为了更好地了解定位器及其用法,请阅读 [Playwright 的“定位器”文档](https://playwright.dev/docs/locators)。 ::: + +::: tip Difference from `testing-library` +Vitest's `page.getBy*` methods return a locator object, not a DOM element. This makes locator queries composable and allows Vitest to retry interactions and assertions when needed. + +Compared to testing-library queries: + +- Use locator chaining (`.getBy*`, `.filter`, `.nth`) instead of `within(...)`. +- Keep locators around and interact with them later (`await locator.click()`), instead of resolving elements up front. +- Single-element escape hatches like `.element()` and `.query()` are strict and throw if multiple elements match. + +```ts +import { expect } from 'vitest' +import { page } from 'vitest/browser' + +const deleteButton = page + .getByRole('row') + .filter({ hasText: 'Vitest' }) + .getByRole('button', { name: /delete/i }) + +await deleteButton.click() +await expect.element(deleteButton).toBeEnabled() +``` +::: ## getByRole diff --git a/guide/common-errors.md b/guide/common-errors.md index 6142093a..ae7bbf0a 100644 --- a/guide/common-errors.md +++ b/guide/common-errors.md @@ -123,3 +123,47 @@ vitest --pool=forks ``` ::: + +## Unhandled Promise Rejection + +This error happens when a Promise rejects but no `.catch()` handler or `await` is attached to it before the microtask queue flushes. This behavior comes from JavaScript itself and is not specific to Vitest. Learn more in the [Node.js documentation](https://nodejs.org/api/process.html#event-unhandledrejection). + +A common cause is calling an async function without `await`ing it: + +```ts +async function fetchUser(id) { + const res = await fetch(`/api/users/${id}`) + if (!res.ok) { + throw new Error(`User ${id} not found`) // [!code highlight] + } + return res.json() +} + +test('fetches user', async () => { + fetchUser(123) // [!code error] +}) +``` + +Because `fetchUser()` is not `await`ed, its rejection has no handler and Vitest reports: + +``` +Unhandled Rejection: Error: User 123 not found +``` + +### Fix + +`await` the promise so Vitest can catch the error: + +```ts +test('fetches user', async () => { + await fetchUser(123) // [!code ++] +}) +``` + +If you expect the call to throw, use [`expect().rejects`](/api/expect#rejects): + +```ts +test('rejects for missing user', async () => { + await expect(fetchUser(123)).rejects.toThrow('User 123 not found') +}) +``` diff --git a/guide/recipes.md b/guide/recipes.md index f14da9ca..973c0659 100644 --- a/guide/recipes.md +++ b/guide/recipes.md @@ -15,15 +15,19 @@ export default defineConfig({ test: { projects: [ { - // 禁用隔离的单元测试 - name: 'Unit tests', - isolate: false, - exclude: ['**.integration.test.ts'], + test: { + // Non-isolated unit tests + name: 'Unit tests', + isolate: false, + exclude: ['**.integration.test.ts'], + }, }, { - // 集成隔离的测试 - name: 'Integration tests', - include: ['**.integration.test.ts'], + test: { + // Isolated integration tests + name: 'Integration tests', + include: ['**.integration.test.ts'], + }, }, ], }, @@ -41,13 +45,17 @@ export default defineConfig({ test: { projects: [ { - name: 'Parallel', - exclude: ['**.sequential.test.ts'], + test: { + name: 'Parallel', + exclude: ['**.sequential.test.ts'], + }, }, { - name: 'Sequential', - include: ['**.sequential.test.ts'], - fileParallelism: false, + test: { + name: 'Sequential', + include: ['**.sequential.test.ts'], + fileParallelism: false, + }, }, ], },