@modern-js/main-doc 2.58.2 → 2.59.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/apis/app/runtime/core/use-loader.mdx +1 -1
- package/docs/en/community/blog/_meta.json +1 -6
- package/docs/en/components/deploy.mdx +1 -1
- package/docs/en/components/init-app.mdx +0 -1
- package/docs/en/components/init-rspack-app.mdx +0 -1
- package/docs/en/components/ssr-monitor.mdx +3 -0
- package/docs/en/configure/_meta.json +1 -1
- package/docs/en/configure/app/output/ssg.mdx +52 -141
- package/docs/en/configure/app/tools/swc.mdx +1 -1
- package/docs/en/configure/app/tools/tailwindcss.mdx +1 -1
- package/docs/en/guides/advanced-features/_meta.json +0 -8
- package/docs/en/guides/advanced-features/bff/_meta.json +1 -6
- package/docs/en/guides/advanced-features/rsbuild-plugin.mdx +2 -2
- package/docs/en/guides/advanced-features/rspack-start.mdx +7 -22
- package/docs/en/guides/basic-features/_meta.json +31 -9
- package/docs/en/guides/basic-features/css/_meta.json +1 -0
- package/docs/en/guides/basic-features/css/css-in-js.mdx +34 -0
- package/docs/en/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -4
- package/docs/en/guides/basic-features/css/css.mdx +25 -0
- package/docs/en/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +5 -66
- package/docs/en/guides/basic-features/data/_meta.json +1 -4
- package/docs/en/guides/basic-features/data/data-fetch.mdx +134 -235
- package/docs/en/guides/basic-features/data/data-write.mdx +66 -77
- package/docs/en/guides/basic-features/debug/_meta.json +1 -0
- package/docs/en/guides/basic-features/debug/rsdoctor.mdx +57 -0
- package/docs/en/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +2 -0
- package/docs/en/guides/basic-features/render/_meta.json +1 -0
- package/docs/en/guides/basic-features/render/ssg.mdx +208 -0
- package/docs/en/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +38 -50
- package/docs/en/guides/basic-features/render/ssr.mdx +301 -0
- package/docs/en/guides/basic-features/render/streaming-ssr.mdx +230 -0
- package/docs/en/guides/basic-features/routes.mdx +275 -263
- package/docs/en/guides/basic-features/static-assets/_meta.json +1 -0
- package/docs/en/guides/basic-features/static-assets.mdx +1 -1
- package/docs/en/guides/basic-features/testing/_meta.json +1 -0
- package/docs/en/guides/basic-features/testing/cypress.mdx +95 -0
- package/docs/en/guides/basic-features/testing/jest.mdx +148 -0
- package/docs/en/guides/basic-features/testing/playwright.mdx +111 -0
- package/docs/en/guides/basic-features/testing/vitest.mdx +100 -0
- package/docs/en/guides/concept/_meta.json +1 -4
- package/docs/en/guides/concept/entries.mdx +78 -47
- package/docs/en/guides/get-started/_meta.json +1 -7
- package/docs/en/guides/get-started/introduction.mdx +1 -1
- package/docs/en/guides/get-started/quick-start.mdx +1 -2
- package/docs/en/guides/get-started/tech-stack.mdx +4 -6
- package/docs/en/guides/get-started/upgrade.mdx +16 -2
- package/docs/en/guides/topic-detail/framework-plugin/_meta.json +1 -1
- package/docs/en/guides/topic-detail/generator/_meta.json +1 -1
- package/docs/en/guides/topic-detail/generator/create/_meta.json +1 -5
- package/docs/en/guides/topic-detail/generator/create/config.mdx +0 -10
- package/docs/en/guides/topic-detail/generator/create/use.mdx +0 -1
- package/docs/en/guides/topic-detail/generator/new/_meta.json +1 -5
- package/docs/en/guides/topic-detail/generator/plugin/_meta.json +1 -1
- package/docs/en/guides/troubleshooting/_meta.json +1 -6
- package/docs/en/tutorials/first-app/c03-css.mdx +1 -1
- package/docs/zh/apis/app/runtime/core/use-loader.mdx +1 -1
- package/docs/zh/community/blog/_meta.json +1 -6
- package/docs/zh/components/deploy.mdx +1 -1
- package/docs/zh/components/init-app.mdx +0 -1
- package/docs/zh/components/init-rspack-app.mdx +0 -1
- package/docs/zh/components/ssr-monitor.mdx +3 -0
- package/docs/zh/configure/_meta.json +1 -1
- package/docs/zh/configure/app/output/ssg.mdx +49 -139
- package/docs/zh/configure/app/tools/swc.mdx +1 -1
- package/docs/zh/configure/app/tools/tailwindcss.mdx +1 -1
- package/docs/zh/guides/advanced-features/_meta.json +0 -8
- package/docs/zh/guides/advanced-features/bff/_meta.json +1 -6
- package/docs/zh/guides/advanced-features/rsbuild-plugin.mdx +2 -2
- package/docs/zh/guides/advanced-features/rspack-start.mdx +8 -24
- package/docs/zh/guides/basic-features/_meta.json +31 -9
- package/docs/zh/guides/basic-features/css/_meta.json +1 -0
- package/docs/zh/guides/basic-features/css/css-in-js.mdx +34 -0
- package/docs/zh/guides/basic-features/css/css.mdx +25 -0
- package/docs/zh/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +3 -64
- package/docs/zh/guides/basic-features/data/_meta.json +1 -4
- package/docs/zh/guides/basic-features/data/data-fetch.mdx +98 -214
- package/docs/zh/guides/basic-features/data/data-write.mdx +54 -55
- package/docs/zh/guides/basic-features/debug/_meta.json +1 -0
- package/docs/zh/guides/basic-features/debug/rsdoctor.mdx +57 -0
- package/docs/zh/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +1 -1
- package/docs/zh/guides/basic-features/render/_meta.json +1 -0
- package/docs/zh/guides/basic-features/render/ssg.mdx +210 -0
- package/docs/zh/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +16 -26
- package/docs/zh/guides/basic-features/render/ssr.mdx +309 -0
- package/docs/zh/guides/{advanced-features/ssr/stream.mdx → basic-features/render/streaming-ssr.mdx} +22 -37
- package/docs/zh/guides/basic-features/routes.mdx +252 -237
- package/docs/zh/guides/basic-features/static-assets/_meta.json +1 -0
- package/docs/zh/guides/basic-features/static-assets.mdx +2 -6
- package/docs/zh/guides/basic-features/testing/_meta.json +1 -0
- package/docs/zh/guides/basic-features/testing/cypress.mdx +95 -0
- package/docs/zh/guides/basic-features/testing/jest.mdx +148 -0
- package/docs/zh/guides/basic-features/testing/playwright.mdx +112 -0
- package/docs/zh/guides/basic-features/testing/vitest.mdx +100 -0
- package/docs/zh/guides/concept/_meta.json +1 -4
- package/docs/zh/guides/concept/entries.mdx +80 -58
- package/docs/zh/guides/get-started/_meta.json +1 -7
- package/docs/zh/guides/get-started/introduction.mdx +2 -2
- package/docs/zh/guides/get-started/quick-start.mdx +1 -2
- package/docs/zh/guides/get-started/tech-stack.mdx +8 -10
- package/docs/zh/guides/get-started/upgrade.mdx +15 -1
- package/docs/zh/guides/topic-detail/framework-plugin/_meta.json +1 -1
- package/docs/zh/guides/topic-detail/generator/_meta.json +1 -1
- package/docs/zh/guides/topic-detail/generator/create/_meta.json +1 -5
- package/docs/zh/guides/topic-detail/generator/create/config.mdx +0 -10
- package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -1
- package/docs/zh/guides/topic-detail/generator/new/_meta.json +1 -5
- package/docs/zh/guides/topic-detail/generator/plugin/_meta.json +1 -1
- package/docs/zh/guides/troubleshooting/_meta.json +1 -6
- package/docs/zh/tutorials/first-app/c03-css.mdx +1 -1
- package/i18n.json +16 -4
- package/package.json +6 -6
- package/rspress.config.ts +1 -1
- package/src/components/ContentCard/index.tsx +1 -1
- package/src/components/Sandpack/index.tsx +1 -1
- package/src/components/ShowcaseList/index.tsx +1 -1
- package/src/i18n/index.ts +1 -1
- package/src/pages/index.tsx +2 -2
- package/docs/en/apis/app/hooks/config/storybook.mdx +0 -37
- package/docs/en/guides/advanced-features/ssg.mdx +0 -116
- package/docs/en/guides/advanced-features/ssr/_meta.json +0 -5
- package/docs/en/guides/advanced-features/ssr/index.mdx +0 -23
- package/docs/en/guides/advanced-features/ssr/stream.mdx +0 -248
- package/docs/en/guides/advanced-features/ssr/usage.mdx +0 -341
- package/docs/en/guides/advanced-features/ssr.mdx +0 -555
- package/docs/zh/apis/app/hooks/config/storybook.mdx +0 -38
- package/docs/zh/guides/advanced-features/ssg.mdx +0 -116
- package/docs/zh/guides/advanced-features/ssr/_meta.json +0 -5
- package/docs/zh/guides/advanced-features/ssr/index.mdx +0 -23
- package/docs/zh/guides/advanced-features/ssr/usage.mdx +0 -329
- /package/docs/en/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
- /package/docs/en/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
- /package/docs/en/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
- /package/docs/en/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
- /package/docs/en/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
["json-files", "svg-assets", "wasm-assets"]
|
@@ -1,7 +1,3 @@
|
|
1
|
-
---
|
2
|
-
sidebar_position: 10
|
3
|
-
---
|
4
|
-
|
5
1
|
# 引用静态资源
|
6
2
|
|
7
3
|
Modern.js 支持在代码中引用图片、字体、媒体类型的静态资源。
|
@@ -21,7 +17,7 @@ Modern.js 支持在代码中引用图片、字体、媒体类型的静态资源
|
|
21
17
|
如果你需要引用其他格式的静态资源,请参考 [扩展静态资源类型](#扩展静态资源类型)。
|
22
18
|
|
23
19
|
:::tip SVG 图片
|
24
|
-
SVG 图片是一种特殊情况,Modern.js 提供了 SVG 转 React 组件的能力,对 SVG 进行单独处理,详见 [引用 SVG 资源](/guides/basic-features/svg-assets.html)。
|
20
|
+
SVG 图片是一种特殊情况,Modern.js 提供了 SVG 转 React 组件的能力,对 SVG 进行单独处理,详见 [引用 SVG 资源](/guides/basic-features/static-assets/svg-assets.html)。
|
25
21
|
:::
|
26
22
|
|
27
23
|
## 在 JS 文件中引用
|
@@ -162,4 +158,4 @@ console.log(myFile); // "/static/myFile.6c12aba3.pdf"
|
|
162
158
|
| PNG | 无损压缩,不会丢失图片细节,不失真,支持半透明 | 不适合色表复杂的图片 | 适合颜色数量少,边界层次分明的图片,适合用在 logo、icon、透明图等场景 |
|
163
159
|
| JPG | 颜色丰富 | 有损压缩,会导致图片失真,不支持透明度 | 适合颜色数量多,颜色带有渐变、过度复杂的图片,适合用在人像照片、风景图等场景 |
|
164
160
|
| WebP | 同时支持有损压缩与无损压缩,支持透明度,体积比 PNG 和 JPG 小很多 | iOS 兼容性不好 | 几乎任何场景的像素图片,支持 WebP 的宿主环境,都应该首选 WebP 图片格式 |
|
165
|
-
| SVG |
|
161
|
+
| SVG | 无损格式,不失真,支持透明度 | 不适合复杂图形 | 适合矢量图,适合用于 icon |
|
@@ -0,0 +1 @@
|
|
1
|
+
["playwright", "vitest", "jest", "cypress"]
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Cypress
|
2
|
+
|
3
|
+
Cypress 是一个用于 E2E 测试和组件测试的框架。
|
4
|
+
|
5
|
+
在 Modern.js 中使用 Cypress 需要先安装依赖,可以执行以下命令:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{ npm: "npm install -D cypress", yarn: "yarn add -D cypress", pnpm: "pnpm install -D cypress" }} />
|
10
|
+
|
11
|
+
接下来,创建 `cypress.config.ts` 文件,并添加以下内容:
|
12
|
+
|
13
|
+
```ts
|
14
|
+
import { defineConfig } from 'cypress'
|
15
|
+
|
16
|
+
export default defineConfig({
|
17
|
+
e2e: {
|
18
|
+
setupNodeEvents(on, config) {},
|
19
|
+
},
|
20
|
+
})
|
21
|
+
```
|
22
|
+
|
23
|
+
## 编写测试用例
|
24
|
+
|
25
|
+
现在,使用 Cypress 来编写一个 E2E 用例,首先创建两张 Modern.js 的页面。
|
26
|
+
|
27
|
+
```tsx title="routes/page.tsx"
|
28
|
+
import { Link } from '@modern-js/runtime/router';
|
29
|
+
|
30
|
+
const Index = () => (
|
31
|
+
<div>
|
32
|
+
<h1>Home</h1>
|
33
|
+
<Link to="/about">About</Link>
|
34
|
+
</div>
|
35
|
+
);
|
36
|
+
|
37
|
+
export default Index;
|
38
|
+
```
|
39
|
+
|
40
|
+
```tsx title="routes/about/page.tsx"
|
41
|
+
import { Link } from '@modern-js/runtime/router';
|
42
|
+
|
43
|
+
const Index = () => (
|
44
|
+
<div>
|
45
|
+
<h1>About</h1>
|
46
|
+
<Link to="/">Home</Link>
|
47
|
+
</div>
|
48
|
+
);
|
49
|
+
|
50
|
+
export default Index;
|
51
|
+
```
|
52
|
+
|
53
|
+
接下来,创建测试用例文件:
|
54
|
+
|
55
|
+
```ts title="cypress/e2e/app.cy.ts"
|
56
|
+
describe('Navigation', () => {
|
57
|
+
it('should navigate to the about page', () => {
|
58
|
+
// Start from the index page
|
59
|
+
cy.visit('http://localhost:8080/')
|
60
|
+
|
61
|
+
// Find a link with an href attribute containing "about" and click it
|
62
|
+
cy.get('a[href*="about"]').click()
|
63
|
+
|
64
|
+
// The new url should include "/about"
|
65
|
+
cy.url().should('include', '/about')
|
66
|
+
|
67
|
+
// The new page should contain an h1 with "About"
|
68
|
+
cy.get('h1').contains('About')
|
69
|
+
})
|
70
|
+
})
|
71
|
+
```
|
72
|
+
|
73
|
+
测试文件可能会缺少 API 的类型,你可以参考 [Cypress - Typescript](https://docs.cypress.io/guides/tooling/typescript-support#Configure-tsconfigjson) 文档解决。
|
74
|
+
|
75
|
+
你可以将命令添加到 `package.json` 中:
|
76
|
+
|
77
|
+
```json title="package.json"
|
78
|
+
{
|
79
|
+
"scripts": {
|
80
|
+
"test": "cypress open"
|
81
|
+
}
|
82
|
+
}
|
83
|
+
```
|
84
|
+
|
85
|
+
## 运行测试用例
|
86
|
+
|
87
|
+
执行上述 `test` 命令,运行测试用例:
|
88
|
+
|
89
|
+
```bash
|
90
|
+
DevTools listening on ws://127.0.0.1:55203/devtools/browser/xxxxx
|
91
|
+
```
|
92
|
+
|
93
|
+
Cypress 会打开一个无头浏览器,按照提示你可以找到对应的测试文件,并自动运行 E2E 测试:
|
94
|
+
|
95
|
+

|
@@ -0,0 +1,148 @@
|
|
1
|
+
# Jest
|
2
|
+
|
3
|
+
Jest 是一个 JavaScript 测试框架,它主要和 React Testing Library 一起用于单元测试和 Snapshot 测试。
|
4
|
+
|
5
|
+
在 Modern.js 中使用 Jest 需要先安装依赖,可以执行以下命令:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{
|
10
|
+
npm: "npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom",
|
11
|
+
yarn: "yarn add -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom",
|
12
|
+
pnpm: "pnpm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom"
|
13
|
+
}} />
|
14
|
+
|
15
|
+
随后,你可以运行以下命令,这将自动在项目中初始化 Jets,并生成一个基础的 `jest.config.[jt]s` 配置:
|
16
|
+
|
17
|
+
<PackageManagerTabs command={{
|
18
|
+
npm: "npm init jest@latest",
|
19
|
+
yarn: "yarn create jest@latest",
|
20
|
+
pnpm: "pnpm create jest@latest"
|
21
|
+
}} />
|
22
|
+
|
23
|
+
## 配置文件
|
24
|
+
|
25
|
+
:::note
|
26
|
+
本章节会使用 `.ts` 文件来完成 Jest 测试。
|
27
|
+
:::
|
28
|
+
|
29
|
+
相比于其他的测试框架,Jest 在构建层面需要更多的配置,例如处理 JSX 和 ESM 语法,因此首先需要安装一些额外的依赖:
|
30
|
+
|
31
|
+
<PackageManagerTabs command={{
|
32
|
+
npm: "npm install -D babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript",
|
33
|
+
yarn: "yarn add -D babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript",
|
34
|
+
pnpm: "pnpm install -D babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript"
|
35
|
+
}} />
|
36
|
+
|
37
|
+
### 配置 Jest
|
38
|
+
|
39
|
+
你需要进一步配置 `jest.config.ts` 文件,以便让 Jest 能够正确地编译和运行测试用例。下面是一个最基本的配置:
|
40
|
+
|
41
|
+
```ts title="jest.config.ts"
|
42
|
+
import type { Config } from 'jest';
|
43
|
+
|
44
|
+
const config: Config = {
|
45
|
+
coverageProvider: 'babel',
|
46
|
+
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
|
47
|
+
testEnvironment: 'jsdom',
|
48
|
+
transform: {
|
49
|
+
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
|
50
|
+
},
|
51
|
+
transformIgnorePatterns: [],
|
52
|
+
};
|
53
|
+
|
54
|
+
export default config;
|
55
|
+
```
|
56
|
+
|
57
|
+
配置中,将 `transformIgnorePatterns` 设置为了空数组,意味着所有的文件都会经过编译,如果你希望提升测试运行的速度,可以按需配置。
|
58
|
+
|
59
|
+
`setupFilesAfterEnv` 会在启动时执行,在 `jest.setup.ts` 中,可以引入 `@testing-library/jest-dom`。它包含了一组便捷的自定义匹配器,例如 `.toBeInTheDocument()`,使编写测试变得更容易:
|
60
|
+
|
61
|
+
```ts title="jest.setup.ts"
|
62
|
+
import '@testing-library/jest-dom';
|
63
|
+
```
|
64
|
+
|
65
|
+
### 配置 Babel
|
66
|
+
|
67
|
+
你需要配置 Babel 让 Jest 能够自动编译 JSX 等语法,下面是一个基本的配置:
|
68
|
+
|
69
|
+
```js title="babel.config.js"
|
70
|
+
module.exports = {
|
71
|
+
presets: [
|
72
|
+
['@babel/preset-env', { targets: { node: 'current' } }],
|
73
|
+
['@babel/preset-react', { runtime: 'automatic' }],
|
74
|
+
'@babel/preset-typescript',
|
75
|
+
],
|
76
|
+
};
|
77
|
+
```
|
78
|
+
|
79
|
+
## 编写测试用例
|
80
|
+
|
81
|
+
现在,你可以开始编写测试用了,首先在 `package.json` 中添加一个 `test` 命令:
|
82
|
+
|
83
|
+
```json title="package.json"
|
84
|
+
{
|
85
|
+
"scripts": {
|
86
|
+
"test": "jest"
|
87
|
+
}
|
88
|
+
}
|
89
|
+
```
|
90
|
+
|
91
|
+
创建一个简单的页面用于测试:
|
92
|
+
|
93
|
+
```tsx title="routes/page.tsx"
|
94
|
+
import { Link } from '@modern-js/runtime/router';
|
95
|
+
|
96
|
+
const Index = () => (
|
97
|
+
<div>
|
98
|
+
<h1>Home</h1>
|
99
|
+
<Link to="/about">About</Link>
|
100
|
+
</div>
|
101
|
+
);
|
102
|
+
|
103
|
+
export default Index;
|
104
|
+
```
|
105
|
+
|
106
|
+
添加测试用例,检测页面中是否有预期的文本:
|
107
|
+
|
108
|
+
```tsx title="__tests__/page.test.tsx"
|
109
|
+
import '@testing-library/jest-dom';
|
110
|
+
import { render, screen } from '@testing-library/react';
|
111
|
+
import { BrowserRouter as Router } from '@modern-js/runtime/router';
|
112
|
+
import Page from '../routes/page';
|
113
|
+
|
114
|
+
describe('Page', () => {
|
115
|
+
it('renders a heading', () => {
|
116
|
+
render(
|
117
|
+
<Router>
|
118
|
+
<Page />
|
119
|
+
</Router>,
|
120
|
+
);
|
121
|
+
|
122
|
+
const heading = screen.getByRole('heading', { level: 1 });
|
123
|
+
|
124
|
+
expect(heading).toBeInTheDocument();
|
125
|
+
});
|
126
|
+
});
|
127
|
+
```
|
128
|
+
|
129
|
+
上述用例中,我们从 `@modern-js/runtime/router` 引入了 `<Router>` 组件,这是因为 React Router 在渲染部分路由相关组件时,必须要有对应的上下文。
|
130
|
+
|
131
|
+
:::note
|
132
|
+
直接在 Modern.js 应用中运行时,`<Router>` 组件会自动注入。
|
133
|
+
:::
|
134
|
+
|
135
|
+
## 运行测试用例
|
136
|
+
|
137
|
+
执行上述 `test` 命令,运行测试用例:
|
138
|
+
|
139
|
+
```bash
|
140
|
+
PASS src/__tests__/page.test.tsx
|
141
|
+
Page
|
142
|
+
✓ renders a heading (31 ms)
|
143
|
+
|
144
|
+
Test Suites: 1 passed, 1 total
|
145
|
+
Tests: 1 passed, 1 total
|
146
|
+
Snapshots: 0 total
|
147
|
+
Time: 0.959 s, estimated 1 s
|
148
|
+
```
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Playwright
|
2
|
+
|
3
|
+
Playwright 是一个测试框架,它允许你使用单一的 API,自动的在 Chromium、Firefox 和 WebKit 环境中运行测试用例,你可以使用它来**编写 E2E 测试**。
|
4
|
+
|
5
|
+
在 Modern.js 中使用 Playwright 需要先安装依赖,可以执行以下命令:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{ npm: "npm init playwright", yarn: "yarn create playwright", pnpm: "pnpm create playwright" }} />
|
10
|
+
|
11
|
+
|
12
|
+
上述命令会自动安装 Playwright 依赖,并通过一系列提示帮助你在项目中安装和配置,包括添加一个 `playwright.config.ts` 文件。
|
13
|
+
|
14
|
+
:::info
|
15
|
+
参考 Playwright 官方文档,[安装 Playwright](https://playwright.dev/docs/intro#installation) 查阅更详细的指南。
|
16
|
+
:::
|
17
|
+
|
18
|
+
按照默认配置创建后,可以在项目中看到以下文件:
|
19
|
+
|
20
|
+
```ts title="tests/example.spec.ts"
|
21
|
+
import { test, expect } from '@playwright/test';
|
22
|
+
|
23
|
+
test('has title', async ({ page }) => {
|
24
|
+
await page.goto('https://playwright.dev/');
|
25
|
+
|
26
|
+
// Expect a title "to contain" a substring.
|
27
|
+
await expect(page).toHaveTitle(/Playwright/);
|
28
|
+
});
|
29
|
+
|
30
|
+
test('get started link', async ({ page }) => {
|
31
|
+
await page.goto('https://playwright.dev/');
|
32
|
+
|
33
|
+
// Click the get started link.
|
34
|
+
await page.getByRole('link', { name: 'Get started' }).click();
|
35
|
+
|
36
|
+
// Expects page to have a heading with the name of Installation.
|
37
|
+
await expect(
|
38
|
+
page.getByRole('heading', { name: 'Installation' }),
|
39
|
+
).toBeVisible();
|
40
|
+
});
|
41
|
+
```
|
42
|
+
|
43
|
+
这是默认的测试文件,现在创建一些新的页面,并测试它们。
|
44
|
+
|
45
|
+
## 创建 E2E 测试
|
46
|
+
|
47
|
+
首先创建两张 Modern.js 的页面。
|
48
|
+
|
49
|
+
```tsx title="routes/page.tsx"
|
50
|
+
import { Link } from '@modern-js/runtime/router';
|
51
|
+
|
52
|
+
const Index = () => (
|
53
|
+
<div>
|
54
|
+
<h1>Home</h1>
|
55
|
+
<Link to="/about">About</Link>
|
56
|
+
</div>
|
57
|
+
);
|
58
|
+
|
59
|
+
export default Index;
|
60
|
+
```
|
61
|
+
|
62
|
+
```tsx title="routes/about/page.tsx"
|
63
|
+
import { Link } from '@modern-js/runtime/router';
|
64
|
+
|
65
|
+
const Index = () => (
|
66
|
+
<div>
|
67
|
+
<h1>About</h1>
|
68
|
+
<Link to="/">Home</Link>
|
69
|
+
</div>
|
70
|
+
);
|
71
|
+
|
72
|
+
export default Index;
|
73
|
+
```
|
74
|
+
|
75
|
+
接下来,添加测试用例,来保证你页面的链接能够正常工作。
|
76
|
+
|
77
|
+
```ts title="tests/example.spec.ts"
|
78
|
+
import { test, expect } from '@playwright/test'
|
79
|
+
|
80
|
+
test('should navigate to the about page', async ({ page }) => {
|
81
|
+
// Start from the index page (the baseURL is set via the webServer in the playwright.config.ts)
|
82
|
+
await page.goto('http://localhost:8080/')
|
83
|
+
// Find an element with the text 'About' and click on it
|
84
|
+
await page.click('text=About')
|
85
|
+
// The new URL should be "/about" (baseURL is used there)
|
86
|
+
await expect(page).toHaveURL('http://localhost:8080/about')
|
87
|
+
// The new page should contain an h1 with "About"
|
88
|
+
await expect(page.locator('h1')).toContainText('About')
|
89
|
+
})
|
90
|
+
```
|
91
|
+
|
92
|
+
## 运行测试用例
|
93
|
+
|
94
|
+
Playwright 需要你的 Modern.js 服务器保持运行。我们推荐在生产环境产物下运行你的测试用例,你可以执行 `pnpm run build` 和 `pnpm run serve` 在本地模拟生产环境。
|
95
|
+
|
96
|
+
```bash
|
97
|
+
info Starting production server...
|
98
|
+
|
99
|
+
> Local: http://localhost:8080/
|
100
|
+
> Network: http://10.94.59.30:8080/
|
101
|
+
```
|
102
|
+
|
103
|
+
当项目正常构建运行后,可以在另一个终端内执行 `npx playwright test`,运行 Playwright 用例:
|
104
|
+
|
105
|
+
```bash
|
106
|
+
Running 3 tests using 3 workers
|
107
|
+
3 passed (2.0s)
|
108
|
+
|
109
|
+
To open last HTML report run:
|
110
|
+
|
111
|
+
npx playwright show-report
|
112
|
+
```
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Vitest
|
2
|
+
|
3
|
+
Vitest 是由 Vite 驱动的测试框架,和 React Testing Library 配合可以用于单元测试。
|
4
|
+
|
5
|
+
在 Modern.js 中使用 Vitest 需要先安装依赖,可以执行以下命令:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{
|
10
|
+
npm: "npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom",
|
11
|
+
yarn: "yarn add -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom",
|
12
|
+
pnpm: "pnpm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom",
|
13
|
+
bun: "bun add -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom"
|
14
|
+
}} />
|
15
|
+
|
16
|
+
接下来,你需要创建一个 Vitest 配置文件 `vitest.config.ts`,内容如下:
|
17
|
+
|
18
|
+
```ts title="vitest.config.ts"
|
19
|
+
import { defineConfig } from 'vitest/config'
|
20
|
+
import react from '@vitejs/plugin-react'
|
21
|
+
|
22
|
+
export default defineConfig({
|
23
|
+
plugins: [react()],
|
24
|
+
test: {
|
25
|
+
environment: 'jsdom',
|
26
|
+
},
|
27
|
+
})
|
28
|
+
```
|
29
|
+
|
30
|
+
更多关于 Vitest 配置的信息,可以参考 [Vitest 配置文档](https://vitest.dev/config/#configuration)。
|
31
|
+
|
32
|
+
你可以选择性的将 `vitest` 命令添加到 `package.json` 中:
|
33
|
+
|
34
|
+
```json title="package.json"
|
35
|
+
{
|
36
|
+
"scripts": {
|
37
|
+
"test": "vitest"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
```
|
41
|
+
|
42
|
+
运行该命令后,Vitest 会自动监听你的文件变化,并重新运行用例。
|
43
|
+
|
44
|
+
## 创建单元测试
|
45
|
+
|
46
|
+
首先,创建一个简单的页面用于测试:
|
47
|
+
|
48
|
+
```tsx title="routes/page.tsx"
|
49
|
+
import { Link } from '@modern-js/runtime/router';
|
50
|
+
|
51
|
+
const Index = () => (
|
52
|
+
<div>
|
53
|
+
<h1>Home</h1>
|
54
|
+
<Link to="/about">About</Link>
|
55
|
+
</div>
|
56
|
+
);
|
57
|
+
|
58
|
+
export default Index;
|
59
|
+
```
|
60
|
+
|
61
|
+
添加测试用例,检测页面中是否有预期的文本:
|
62
|
+
|
63
|
+
```tsx title="__tests__/page.test.tsx"
|
64
|
+
import { expect, test } from 'vitest';
|
65
|
+
import { render, screen } from '@testing-library/react';
|
66
|
+
import { BrowserRouter as Router } from '@modern-js/runtime/router';
|
67
|
+
import Page from '../routes/page';
|
68
|
+
|
69
|
+
test('Page', () => {
|
70
|
+
render(
|
71
|
+
<Router>
|
72
|
+
<Page />
|
73
|
+
</Router>,
|
74
|
+
);
|
75
|
+
expect(screen.getByRole('heading', { level: 1, name: 'Home' })).toBeDefined();
|
76
|
+
});
|
77
|
+
```
|
78
|
+
|
79
|
+
上述用例中,我们从 `@modern-js/runtime/router` 引入了 `<Router>` 组件,这是因为 React Router 在渲染部分路由相关组件时,必须要有对应的上下文。
|
80
|
+
|
81
|
+
:::note
|
82
|
+
直接在 Modern.js 应用中运行时,`<Router>` 组件会自动注入。
|
83
|
+
:::
|
84
|
+
|
85
|
+
## 运行测试用例
|
86
|
+
|
87
|
+
执行上述 `test` 命令,运行测试用例:
|
88
|
+
|
89
|
+
```bash
|
90
|
+
✓ src/__tests__/page.test.tsx (1)
|
91
|
+
✓ Page
|
92
|
+
|
93
|
+
Test Files 1 passed (1)
|
94
|
+
Tests 1 passed (1)
|
95
|
+
Start at 15:37:12
|
96
|
+
Duration 999ms (transform 119ms, setup 0ms, collect 365ms, tests 33ms, environment 421ms, prepare 44ms)
|
97
|
+
|
98
|
+
|
99
|
+
PASS Waiting for file changes...
|
100
|
+
```
|