Skip to content

Commit 1216d23

Browse files
NoiseFansheremet-vaPatrick-ClausenPatrick Clausenhi-ogawa
authored
docs(en): merge docs-cn/sync-docs into docs-cn/dev @ b845806 (#987)
* docs: add releases page (#10432) * feat(browser)!: enable `locators.exact` by default (#10430) * fix: forceRerunTriggers uses directory globs against files (fix #10421) (#10420) Co-authored-by: Patrick Clausen <patrick@tourcompass.com> * docs: update vitest-browser-vue/svelte async render (#10441) Co-authored-by: Codex <noreply@openai.com> * docs(cn): dissolve the conflict * fix: lint error * [autofix.ci] apply automated fixes --------- Co-authored-by: Vladimir <sleuths.slews0s@icloud.com> Co-authored-by: Patrick Clausen <clausen.patrick@gmail.com> Co-authored-by: Patrick Clausen <patrick@tourcompass.com> Co-authored-by: Hiroshi Ogawa <hi.ogawa.zz@gmail.com> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: noise <noisefan@163.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2 parents da7ec28 + 06927ea commit 1216d23

10 files changed

Lines changed: 262 additions & 43 deletions

File tree

.vitepress/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ export default ({ mode }: { mode: string }) => {
7878
},
7979
}) as any,
8080
],
81+
define: {
82+
__VITEST_VERSION__: JSON.stringify(version),
83+
},
8184
},
8285
markdown: {
8386
config(md) {
@@ -229,6 +232,10 @@ export default ({ mode }: { mode: string }) => {
229232
text: '团队',
230233
link: '/team',
231234
},
235+
{
236+
text: 'Releases',
237+
link: '/releases',
238+
},
232239
],
233240
},
234241
{
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<script setup lang="ts">
2+
import { computed, ref } from 'vue'
3+
4+
declare const __VITEST_VERSION__: string
5+
6+
const DIGITS_ONLY_RE = /^\d+$/
7+
const NEGATIVE_VERSION_RE = /-\d/
8+
9+
const supportedVersionMessage = {
10+
color: 'var(--vp-c-brand-1)',
11+
text: 'supported',
12+
}
13+
const notSupportedVersionMessage = {
14+
color: 'var(--vp-c-danger-1)',
15+
text: 'not supported',
16+
}
17+
const previousMajorLatestMinors: Record<string, string> = {
18+
1: '1.6',
19+
2: '2.1',
20+
3: '3.2',
21+
4: '4.1',
22+
}
23+
24+
// Current latest Vitest version and support info
25+
const parsedViteVersion = parseVersion(__VITEST_VERSION__)!
26+
const supportInfo = computeSupportInfo(parsedViteVersion)
27+
28+
// Check supported version input
29+
const checkedVersion = ref(`${Math.max(parsedViteVersion.major - 2, 2)}.0.0`)
30+
const checkedResult = computed(() => {
31+
const version = checkedVersion.value
32+
if (!isValidVitestVersion(version)) {
33+
return notSupportedVersionMessage
34+
}
35+
36+
const parsedVersion = parseVersion(checkedVersion.value)
37+
if (!parsedVersion) {
38+
return notSupportedVersionMessage
39+
}
40+
41+
const satisfies = (targetVersion: string) => {
42+
const compared = parseVersion(targetVersion)!
43+
return (
44+
parsedVersion.major === compared.major
45+
&& parsedVersion.minor >= compared.minor
46+
)
47+
}
48+
const satisfiesOneSupportedVersion
49+
= parsedVersion.major >= parsedViteVersion.major // Treat future major versions as supported
50+
|| supportInfo.regularPatches.some(satisfies)
51+
|| supportInfo.importantFixes.some(satisfies)
52+
|| supportInfo.securityPatches.some(satisfies)
53+
54+
return satisfiesOneSupportedVersion
55+
? supportedVersionMessage
56+
: notSupportedVersionMessage
57+
})
58+
59+
function parseVersion(version: string) {
60+
let [major, minor, patch] = version.split('.').map((v) => {
61+
const num = DIGITS_ONLY_RE.exec(v)?.[0]
62+
return num ? Number.parseInt(num) : null
63+
})
64+
if (!major) {
65+
return null
66+
}
67+
minor ??= 0
68+
patch ??= 0
69+
70+
return { major, minor, patch }
71+
}
72+
73+
function computeSupportInfo(
74+
version: NonNullable<ReturnType<typeof parseVersion>>,
75+
) {
76+
const { major, minor } = version
77+
const f = (versions: string[]) => {
78+
return versions
79+
.map(v => previousMajorLatestMinors[v] ?? v)
80+
.filter((version) => {
81+
if (!isValidVitestVersion(version)) {
82+
return false
83+
}
84+
// Negative versions are invalid
85+
if (NEGATIVE_VERSION_RE.test(version)) {
86+
return false
87+
}
88+
return true
89+
})
90+
}
91+
92+
return {
93+
regularPatches: f([`${major}.${minor}`]),
94+
importantFixes: f([`${major - 1}`, `${major}.${minor - 1}`]),
95+
// unlike vite, we only support the last major version
96+
securityPatches: f([`${major - 1}`, `${major}.${minor - 1}`]),
97+
}
98+
}
99+
100+
function versionsToText(versions: string[]) {
101+
versions = versions.map(v => `<code>vitest@${v}</code>`)
102+
if (versions.length === 0) {
103+
return ''
104+
}
105+
if (versions.length === 1) {
106+
return versions[0]
107+
}
108+
return (
109+
`${versions.slice(0, -1).join(', ')} and ${versions.at(-1)}`
110+
)
111+
}
112+
113+
function isValidVitestVersion(version: string) {
114+
if (version.length === 1) {
115+
version += '.'
116+
}
117+
// Vitest 0.x shouldn't be mentioned
118+
if (version.startsWith('0.')) {
119+
return false
120+
}
121+
return true
122+
}
123+
</script>
124+
125+
<template>
126+
<div>
127+
<ul>
128+
<li v-if="supportInfo.regularPatches.length">
129+
Regular patches are released for
130+
<span v-html="versionsToText(supportInfo.regularPatches)" />.
131+
</li>
132+
<li v-if="supportInfo.importantFixes.length">
133+
Important fixes and security patches are backported to
134+
<span v-html="versionsToText(supportInfo.importantFixes)" />.
135+
</li>
136+
<li>
137+
All versions before these are no longer supported. Users should upgrade
138+
to receive updates.
139+
</li>
140+
</ul>
141+
<p>
142+
If you're using Vitest
143+
<input
144+
v-model="checkedVersion"
145+
class="checked-input"
146+
type="text"
147+
placeholder="0.0.0"
148+
>, it is
149+
<strong :style="{ color: checkedResult.color }">{{
150+
checkedResult.text
151+
}}</strong>.
152+
</p>
153+
</div>
154+
</template>
155+
156+
<style scoped>
157+
.checked-input {
158+
display: inline-block;
159+
padding: 0px 5px;
160+
width: 100px;
161+
color: var(--vp-c-text-1);
162+
background: var(--vp-c-bg-soft);
163+
font-size: var(--vp-code-font-size);
164+
font-family: var(--vp-font-family-mono);
165+
border: 1px solid var(--vp-c-divider);
166+
border-radius: 5px;
167+
transition: border-color 0.1s;
168+
}
169+
170+
.checked-input:focus,
171+
.checked-input:hover {
172+
border-color: var(--vp-c-brand);
173+
}
174+
</style>

api/browser/svelte.md

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,11 @@ export function render<C extends Component>(
3939
Component: ComponentImport<C>,
4040
options?: ComponentOptions<C>,
4141
renderOptions?: SetupOptions
42-
): RenderResult<C> & PromiseLike<RenderResult<C>>
42+
): Promise<RenderResult<C>>
4343
```
4444

4545
`render` 函数会记录一个 `svelte.render` 追踪标记,该标记可在 [Trace View](/guide/browser/trace-view) 中查看。
4646

47-
::: warning
48-
同步调用 `render` 的方式已被弃用,并将在下一个主要版本中移除。请始终使用 `await` 处理其返回结果:
49-
50-
```ts
51-
const screen = render(Component) // [!code --]
52-
const screen = await render(Component) // [!code ++]
53-
```
54-
:::
55-
5647
### 选项 {#options}
5748

5849
`render` 函数支持两种传参方式,一种是向 [`mount`](https://svelte.dev/docs/svelte/imperative-component-api#mount) 传入配置选项,另一种则是直接向组件传入属性:
@@ -174,10 +165,6 @@ function unmount(): Promise<void>
174165

175166
卸载并销毁 Svelte 组件。同时会在 [Trace View](/guide/browser/trace-view) 中记录一个 `svelte.unmount` 追踪标记。此功能适用于测试组件从页面中移除时的行为(例如测试是否未遗留事件监听器导致内存泄漏)。
176167

177-
::: warning
178-
同步调用 `unmount` 的方式已被弃用,并将在下一个主要版本中移除。请始终使用 `await` 处理其返回结果:
179-
:::
180-
181168
```ts
182169
import { render } from 'vitest-browser-svelte'
183170

api/browser/vue.md

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,11 @@ test('counter button increments the count', async () => {
4040
export function render(
4141
component: Component,
4242
options?: ComponentRenderOptions,
43-
): RenderResult & PromiseLike<RenderResult>
43+
): Promise<RenderResult>
4444
```
4545

4646
`render` 函数会记录一个 `vue.render` 追踪标记,该标记可在 [Trace View](/guide/browser/trace-view) 中查看。
4747

48-
::: warning
49-
同步调用 `render` 的方式已被弃用,并将在下一个主要版本中移除。请始终使用 `await` 处理其返回结果:
50-
51-
```ts
52-
const screen = render(Component) // [!code --]
53-
const screen = await render(Component) // [!code ++]
54-
```
55-
:::
56-
5748
### 选项 {#options}
5849

5950
`render` 函数支持 `@vue/test-utils` 中 [`mount` 选项](https://test-utils.vuejs.org/api/#mount) 的全部参数(除 `attachTo` 外,需改用 `container`)。此外还额外支持 `container` 和 `baseElement` 参数。
@@ -136,16 +127,12 @@ function debug(
136127
#### rerender
137128

138129
```ts
139-
function rerender(props: Partial<Props>): void & PromiseLike<void>
130+
function rerender(props: Partial<Props>): Promise<void>
140131
```
141132
同时还会在 [Trace View](/guide/browser/trace-view) 中记录一个 `vue.rerender` 追踪标记。
142133

143134
为了更好地确保组件正确地更新属性,建议测试负责属性更新的组件本身,以避免在测试中依赖实现细节。尽管如此,如果你更倾向于在测试中更新已渲染组件的属性,可以使用此函数来实现。
144135

145-
::: warning
146-
同步调用 `render` 的方式已被弃用,并将在下一个主要版本中移除。请始终使用 `await` 处理其返回结果:
147-
:::
148-
149136
```js
150137
import { render } from 'vitest-browser-vue'
151138
@@ -158,15 +145,11 @@ rerender({ number: 2 })
158145
#### unmount
159146

160147
```ts
161-
function unmount(): void & PromiseLike<void>
148+
function unmount(): Promise<void>
162149
```
163150

164151
该操作会触发组件卸载,同时在 [跟踪视图](/guide/browser/trace-view) 中记录 `vue.unmount` 标记点。此功能特别适用于测试组件从页面移除时的行为(例如验证是否残留事件处理器导致内存泄漏)。
165152

166-
::: warning
167-
同步调用 `unmount` 的方式已被弃用,将在下一主要版本中移除。请使用 `await` 进行异步调用。
168-
:::
169-
170153
#### emitted
171154

172155
```ts

config/browser/locators.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@ outline: deep
1414

1515
用于通过 `getByTestId` 定位器查找元素的属性。
1616

17-
## browser.locators.exact <Version type="experimental">4.1.3</Version> {#browser-locators-exact}
17+
## browser.locators.exact
1818

1919
- **类型:** `boolean`
20-
- **默认值:** `false`
20+
- **默认值:** `true`
2121

2222
当设置为 `true` 时,[定位器](/api/browser/locators) 默认会执行精确文本匹配,要求完全且区分大小写的匹配。单个定位器调用可通过自身的 `exact` 选项覆盖此默认行为。
2323

2424
```ts
25-
// 当 exact: false(默认值)时,会匹配 "Hello, World!"、"Say Hello, World" 等文本
26-
// 当 exact: true 时,仅精确匹配字符串 "Hello, World"
25+
// 当 exact: true(默认值)时,仅精确匹配字符串 "Hello, World"
26+
// 当 exact: false 时,会匹配 "Hello, World!"、"Say Hello, World" 等文本
2727
const locator = page.getByText('Hello, World', { exact: true })
2828
await locator.click()
2929
```

config/forcereruntriggers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ outline: deep
66
# forceRerunTriggers <CRoot />
77

88
- **类型:** `string[]`
9-
- **默认值:** `['**/package.json/**', '**/vitest.config.*/**', '**/vite.config.*/**']`
9+
- **默认值:** `['**/package.json', '**/vitest.config.*', '**/vite.config.*']`
1010

1111
将触发整个测试套件重新运行的文件路径(glob 模式)。当与 `--changed` 参数配合使用时,如果在 git diff 中发现触发文件,就会运行整个测试套件。
1212

guide/browser/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ import { render } from 'vitest-browser-vue'
426426
import Component from './Component.vue'
427427

428428
test('properly handles v-model', async () => {
429-
const screen = render(Component)
429+
const screen = await render(Component)
430430

431431
// 断言初始状态。
432432
await expect.element(screen.getByText('Hi, my name is Alice')).toBeInTheDocument()
@@ -448,7 +448,7 @@ import { render } from 'vitest-browser-svelte'
448448
import Greeter from './greeter.svelte'
449449

450450
test('greeting appears on click', async () => {
451-
const screen = render(Greeter, { name: 'World' })
451+
const screen = await render(Greeter, { name: 'World' })
452452

453453
const button = screen.getByRole('button')
454454
await button.click()

guide/cli-generated.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ UI 模式和 HTML 报告器中提供的 HTML 覆盖率输出目录。
462462
- **命令行终端:** `--browser.locators.exact`
463463
- **配置:** [browser.locators.exact](/config/browser/locators#locators-exact)
464464

465-
定位器是否默认需完全匹配文本内容(默认值:`false`
465+
定位器是否默认需完全匹配文本内容(默认值:`true`
466466

467467
### pool
468468

guide/migration.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ outline: deep
55

66
# 迁移指南 {#migration-guide}
77

8-
[迁移至 Vitest 3.0](https://v3.vitest.dev/guide/migration) | [迁移至 Vitest 2.0](https://v2.vitest.dev/guide/migration)
8+
[迁移至 Vitest 4.0](https://v4.vitest.dev/guide/migration) | [迁移至 Vitest 3.0](https://v3.vitest.dev/guide/migration)
99

1010
## 迁移至 Vitest 5.0 {#vitest-5}
1111

@@ -55,6 +55,17 @@ export async function customClick(
5555
await context.page.locator(selector).click()
5656
}
5757
```
58+
<!-- TODO: translation -->
59+
### Locators are Strict by Default
60+
61+
Browser locators now match the text exactly by default, requiring a full, case-sensitive match. To keep the previous behaviour, you can set [`browser.locators.exact`](/config/browser/locators#browser-locators-exact) to `false`.
62+
63+
```ts
64+
// With exact: true (default), this only matches the string "Hello, World" exactly.
65+
// With exact: false, this matches "Hello, World!", "Say Hello, World", etc.
66+
const locator = page.getByText('Hello, World', { exact: true })
67+
await locator.click()
68+
```
5869

5970
### 移除了已弃用的入口 {#removed-deprecated-entrypoints}
6071

0 commit comments

Comments
 (0)