@modern-js/main-doc 3.2.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/en/community/contributing-guide.mdx +1 -1
- package/docs/en/configure/app/server/tsconfig-path.mdx +63 -0
- package/docs/en/guides/basic-features/testing/_meta.json +1 -1
- package/docs/en/guides/get-started/tech-stack.mdx +6 -0
- package/docs/zh/community/contributing-guide.mdx +1 -1
- package/docs/zh/configure/app/server/tsconfig-path.mdx +63 -0
- package/docs/zh/guides/basic-features/testing/_meta.json +1 -1
- package/docs/zh/guides/get-started/tech-stack.mdx +6 -0
- package/package.json +2 -2
- package/docs/en/guides/basic-features/testing/cypress.mdx +0 -95
- package/docs/en/guides/basic-features/testing/jest.mdx +0 -148
- package/docs/en/guides/basic-features/testing/vitest.mdx +0 -100
- package/docs/zh/guides/basic-features/testing/cypress.mdx +0 -95
- package/docs/zh/guides/basic-features/testing/jest.mdx +0 -148
- package/docs/zh/guides/basic-features/testing/vitest.mdx +0 -100
|
@@ -125,7 +125,7 @@ pnpm run reset
|
|
|
125
125
|
|
|
126
126
|
If you've fixed a bug or added code that should be tested, then add some tests.
|
|
127
127
|
|
|
128
|
-
You can add
|
|
128
|
+
Modern.js uses [Rstest](https://rstest.rs/) for unit tests across the repository. You can add test cases in the `<PACKAGE_DIR>/tests` folder, using Rstest syntax.
|
|
129
129
|
|
|
130
130
|
### Run Unit Tests
|
|
131
131
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: tsconfigPath
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# server.tsconfigPath
|
|
6
|
+
|
|
7
|
+
- **Type:** `string`
|
|
8
|
+
- **Default:** `<appDirectory>/tsconfig.json`
|
|
9
|
+
|
|
10
|
+
Specifies the tsconfig file used by server-side TypeScript processes.
|
|
11
|
+
|
|
12
|
+
This option affects:
|
|
13
|
+
|
|
14
|
+
- BFF / API compilation (`@modern-js/plugin-bff`)
|
|
15
|
+
- Custom server compilation (`*.ts` files under `server/`)
|
|
16
|
+
- Runtime ts-node registration, such as SSR, `modern.config.ts`, and `.ts` files under `config/`
|
|
17
|
+
|
|
18
|
+
When this option is not set, `<appDirectory>/tsconfig.json` is used by default.
|
|
19
|
+
|
|
20
|
+
## When to use
|
|
21
|
+
|
|
22
|
+
Use this option when frontend and server-side code need different TypeScript configurations.
|
|
23
|
+
|
|
24
|
+
For example, the frontend can use `moduleResolution: "Bundler"`, while the server side uses `moduleResolution: "NodeNext"` for type resolution of conditional exports or subpath exports.
|
|
25
|
+
|
|
26
|
+
## Example
|
|
27
|
+
|
|
28
|
+
The example below uses `tsconfig.server.json` as the file name. You can use another name in your project.
|
|
29
|
+
|
|
30
|
+
Add `<appDirectory>/tsconfig.server.json`:
|
|
31
|
+
|
|
32
|
+
```jsonc title="tsconfig.server.json"
|
|
33
|
+
{
|
|
34
|
+
"extends": "./tsconfig.json",
|
|
35
|
+
"compilerOptions": {
|
|
36
|
+
"module": "NodeNext",
|
|
37
|
+
"moduleResolution": "NodeNext",
|
|
38
|
+
"target": "ES2022",
|
|
39
|
+
"lib": ["ESNext"],
|
|
40
|
+
"types": ["node"],
|
|
41
|
+
"esModuleInterop": true,
|
|
42
|
+
"experimentalDecorators": true,
|
|
43
|
+
"emitDecoratorMetadata": true
|
|
44
|
+
},
|
|
45
|
+
"include": ["api", "shared", "server", "config", "modern.config.ts"]
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Specify this file in `modern.config.ts`:
|
|
50
|
+
|
|
51
|
+
```ts title="modern.config.ts"
|
|
52
|
+
export default defineConfig({
|
|
53
|
+
server: {
|
|
54
|
+
tsconfigPath: './tsconfig.server.json',
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Notes
|
|
60
|
+
|
|
61
|
+
- `tsconfigPath` is resolved relative to `appDirectory`. Absolute paths are also supported.
|
|
62
|
+
- It is recommended to inherit shared options such as `paths` from the root tsconfig through `extends`, instead of maintaining them in multiple files.
|
|
63
|
+
- If the configured file does not exist, TypeScript / ts-node will throw an error at startup.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
["
|
|
1
|
+
["rstest", "playwright"]
|
|
@@ -75,6 +75,12 @@ Modern.js can be used with any React UI component library from the community, su
|
|
|
75
75
|
|
|
76
76
|
Modern.js supports the use of [Storybook](https://storybook.js.org/) for developing UI components. This feature is optional. Please refer to ["Using Storybook"](/guides/basic-features/debug/using-storybook) to enable it.
|
|
77
77
|
|
|
78
|
+
## Testing Framework
|
|
79
|
+
|
|
80
|
+
Modern.js recommends [Rstest](https://rstest.rs/) for unit tests and component tests. Rstest is built on Rspack for fast startup and execution, and it can reuse your Modern.js app configuration through [`@modern-js/adapter-rstest`](/guides/basic-features/testing/rstest).
|
|
81
|
+
|
|
82
|
+
For end-to-end (E2E) tests, you can use [Playwright](/guides/basic-features/testing/playwright).
|
|
83
|
+
|
|
78
84
|
## Node.js Framework
|
|
79
85
|
|
|
80
86
|
import TechStackNodeFramework from '@site-docs-en/components/tech-stack-node-framework';
|
|
@@ -124,7 +124,7 @@ pnpm run reset
|
|
|
124
124
|
|
|
125
125
|
如果你进行了 bugfix,或者添加了需要测试的代码,请添加一些测试代码。
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
Modern.js 仓库的单元测试统一使用 [Rstest](https://rstest.rs/)。你可以在 `<PACKAGE_DIR>/tests` 文件夹中添加测试用例,测试语法基于 Rstest。
|
|
128
128
|
|
|
129
129
|
### 运行单元测试
|
|
130
130
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: tsconfigPath
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# server.tsconfigPath
|
|
6
|
+
|
|
7
|
+
- **类型:** `string`
|
|
8
|
+
- **默认值:** `<appDirectory>/tsconfig.json`
|
|
9
|
+
|
|
10
|
+
指定服务端 TypeScript 相关流程使用的 tsconfig 文件。
|
|
11
|
+
|
|
12
|
+
该配置会影响:
|
|
13
|
+
|
|
14
|
+
- BFF / API 编译(`@modern-js/plugin-bff`)
|
|
15
|
+
- 自定义 Server 编译(`server/` 目录下的 `*.ts` 文件)
|
|
16
|
+
- 运行时 ts-node 注册(如 SSR、`modern.config.ts`、`config/` 目录下的 `.ts` 文件)
|
|
17
|
+
|
|
18
|
+
未配置时,默认使用 `<appDirectory>/tsconfig.json`。
|
|
19
|
+
|
|
20
|
+
## 使用场景
|
|
21
|
+
|
|
22
|
+
当前端和服务端需要不同的 TypeScript 配置时,可以通过该选项为服务端单独指定 tsconfig。
|
|
23
|
+
|
|
24
|
+
例如前端使用 `moduleResolution: "Bundler"`,服务端需要使用 `moduleResolution: "NodeNext"` 来适配 conditional exports 或 subpath exports 的类型解析。
|
|
25
|
+
|
|
26
|
+
## 配置示例
|
|
27
|
+
|
|
28
|
+
下面以 `tsconfig.server.json` 为例,你也可以根据项目情况使用其他文件名。
|
|
29
|
+
|
|
30
|
+
新增 `<appDirectory>/tsconfig.server.json`:
|
|
31
|
+
|
|
32
|
+
```jsonc title="tsconfig.server.json"
|
|
33
|
+
{
|
|
34
|
+
"extends": "./tsconfig.json",
|
|
35
|
+
"compilerOptions": {
|
|
36
|
+
"module": "NodeNext",
|
|
37
|
+
"moduleResolution": "NodeNext",
|
|
38
|
+
"target": "ES2022",
|
|
39
|
+
"lib": ["ESNext"],
|
|
40
|
+
"types": ["node"],
|
|
41
|
+
"esModuleInterop": true,
|
|
42
|
+
"experimentalDecorators": true,
|
|
43
|
+
"emitDecoratorMetadata": true
|
|
44
|
+
},
|
|
45
|
+
"include": ["api", "shared", "server", "config", "modern.config.ts"]
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
在 `modern.config.ts` 中指定该文件:
|
|
50
|
+
|
|
51
|
+
```ts title="modern.config.ts"
|
|
52
|
+
export default defineConfig({
|
|
53
|
+
server: {
|
|
54
|
+
tsconfigPath: './tsconfig.server.json',
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 注意事项
|
|
60
|
+
|
|
61
|
+
- `tsconfigPath` 相对 `appDirectory` 解析,也支持绝对路径。
|
|
62
|
+
- 建议通过 `extends` 继承根 tsconfig 中的 `paths` 等公共配置,避免重复维护。
|
|
63
|
+
- 如果配置的文件不存在,TypeScript / ts-node 会在启动时抛出错误。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
["
|
|
1
|
+
["rstest", "playwright"]
|
|
@@ -75,6 +75,12 @@ Modern.js 可以与社区中任意的 React 组件库搭配使用,比如 [MUI]
|
|
|
75
75
|
|
|
76
76
|
Modern.js 支持使用 [Storybook](https://storybook.js.org/) 来开发 UI 组件。该功能为可选功能,请参考 [使用 Storybook](/guides/basic-features/debug/using-storybook) 启用。
|
|
77
77
|
|
|
78
|
+
## 测试框架
|
|
79
|
+
|
|
80
|
+
Modern.js 推荐使用 [Rstest](https://rstest.rs/) 编写单元测试和组件测试。Rstest 基于 Rspack 构建,启动和执行速度快,并且可以通过 [`@modern-js/adapter-rstest`](/guides/basic-features/testing/rstest) 复用 Modern.js 的应用配置。
|
|
81
|
+
|
|
82
|
+
如果需要编写端到端(E2E)测试,可以使用 [Playwright](/guides/basic-features/testing/playwright)。
|
|
83
|
+
|
|
78
84
|
## Node.js 框架
|
|
79
85
|
|
|
80
86
|
import TechStackNodeFramework from '@site-docs/components/tech-stack-node-framework';
|
package/package.json
CHANGED
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"modern",
|
|
17
17
|
"modern.js"
|
|
18
18
|
],
|
|
19
|
-
"version": "3.2.
|
|
19
|
+
"version": "3.2.1",
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"registry": "https://registry.npmjs.org/",
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"mermaid": "^11.12.3",
|
|
26
|
-
"@modern-js/sandpack-react": "3.2.
|
|
26
|
+
"@modern-js/sandpack-react": "3.2.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"rsbuild-plugin-open-graph": "1.1.2",
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# Cypress
|
|
2
|
-
|
|
3
|
-
Cypress is a framework for E2E testing and component testing.
|
|
4
|
-
|
|
5
|
-
To use Cypress in Modern.js, you need to install the dependencies first. You can run the following commands:
|
|
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
|
-
Next, create a `cypress.config.ts` file and add the following content:
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
import { defineConfig } from 'cypress'
|
|
15
|
-
|
|
16
|
-
export default defineConfig({
|
|
17
|
-
e2e: {
|
|
18
|
-
setupNodeEvents(on, config) {},
|
|
19
|
-
},
|
|
20
|
-
})
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Writing Test Cases
|
|
24
|
-
|
|
25
|
-
Now, use Cypress to write an E2E test case by first creating two Modern.js pages.
|
|
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
|
-
Next, create the test case file:
|
|
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
|
-
The test file may lack type definitions for the API. You can refer to the [Cypress - Typescript](https://docs.cypress.io/guides/tooling/typescript-support#Configure-tsconfigjson) documentation to resolve this.
|
|
74
|
-
|
|
75
|
-
You can add the command to your `package.json`:
|
|
76
|
-
|
|
77
|
-
```json title="package.json"
|
|
78
|
-
{
|
|
79
|
-
"scripts": {
|
|
80
|
-
"test": "cypress open"
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Run Test Cases
|
|
86
|
-
|
|
87
|
-
Execute the above `test` command to run the test cases:
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
DevTools listening on ws://127.0.0.1:55203/devtools/browser/xxxxx
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Cypress will open a headless browser. Following the prompts, you can find the corresponding test files and automatically run the E2E tests:
|
|
94
|
-
|
|
95
|
-

|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
# Jest
|
|
2
|
-
|
|
3
|
-
Jest is a JavaScript testing framework that is primarily used with React Testing Library for unit testing and Snapshot testing.
|
|
4
|
-
|
|
5
|
-
To use Jest in Modern.js, you need to install the dependencies first. You can run the following commands:
|
|
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
|
-
Next, you can run the following commands to automatically initialize Jest in your project and generate a basic `jest.config.ts` configuration:
|
|
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
|
-
## Configuration File
|
|
24
|
-
|
|
25
|
-
:::note
|
|
26
|
-
This section will use `.ts` files for Jest testing.
|
|
27
|
-
:::
|
|
28
|
-
|
|
29
|
-
Compared to other testing frameworks, Jest requires more configuration at the build level, such as handling JSX and ESM syntax. Therefore, you need to install some additional dependencies:
|
|
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
|
-
### Configure Jest
|
|
38
|
-
|
|
39
|
-
You need to further configure the `jest.config.ts` file to allow Jest to correctly compile and run test cases. Here is a basic configuration:
|
|
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
|
-
In the configuration, the `transformIgnorePatterns` is set to an empty array, meaning that all files will be compiled. If you want to speed up the test run, you can configure it as needed.
|
|
58
|
-
|
|
59
|
-
The `setupFilesAfterEnv` will be executed at startup. In `jest.setup.ts`, you can import `@testing-library/jest-dom`, which includes a set of convenient custom matchers, such as `.toBeInTheDocument()`, to make writing tests easier:
|
|
60
|
-
|
|
61
|
-
```ts title="jest.setup.ts"
|
|
62
|
-
import '@testing-library/jest-dom';
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Configure Babel
|
|
66
|
-
|
|
67
|
-
You need to configure Babel to allow Jest to automatically compile JSX and other syntax. Here is a basic configuration:
|
|
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
|
-
## Writing Test Cases
|
|
80
|
-
|
|
81
|
-
Now, you can start writing tests. First, add a `test` command in `package.json`:
|
|
82
|
-
|
|
83
|
-
```json title="package.json"
|
|
84
|
-
{
|
|
85
|
-
"scripts": {
|
|
86
|
-
"test": "jest"
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Create a simple page for testing:
|
|
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
|
-
Add a test case to check if the page has the expected text:
|
|
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
|
-
In the above test case, we imported the `<Router>` component from `@modern-js/runtime/router` because React Router requires the corresponding context when rendering some route-related components.
|
|
130
|
-
|
|
131
|
-
:::note
|
|
132
|
-
When running directly in the Modern.js application, the `<Router>` component will be automatically injected.
|
|
133
|
-
:::
|
|
134
|
-
|
|
135
|
-
## Run Test Cases
|
|
136
|
-
|
|
137
|
-
Execute the above `test` command to run the test cases:
|
|
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
|
-
```
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# Vitest
|
|
2
|
-
|
|
3
|
-
Vitest is a testing framework driven by Vite, which can be used for unit testing in combination with React Testing Library.
|
|
4
|
-
|
|
5
|
-
To use Vitest in Modern.js, you need to install the dependencies first. You can run the following commands:
|
|
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
|
-
Next, you need to create a Vitest configuration file `vitest.config.ts` with the following content:
|
|
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
|
-
For more information about Vitest configuration, you can refer to the [Vitest configuration documentation](https://vitest.dev/config/#configuration).
|
|
31
|
-
|
|
32
|
-
You can optionally add the `vitest` command to `package.json`:
|
|
33
|
-
|
|
34
|
-
```json title="package.json"
|
|
35
|
-
{
|
|
36
|
-
"scripts": {
|
|
37
|
-
"test": "vitest"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
After running this command, Vitest will automatically watch your file changes and rerun the test cases.
|
|
43
|
-
|
|
44
|
-
## Create Unit Tests
|
|
45
|
-
|
|
46
|
-
First, create a simple page for testing:
|
|
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
|
-
Add a test case to check if the page has the expected text:
|
|
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
|
-
In the above test case, we imported the `<Router>` component from `@modern-js/runtime/router` because React Router requires the corresponding context when rendering some route-related components.
|
|
80
|
-
|
|
81
|
-
:::note
|
|
82
|
-
When running directly in the Modern.js application, the `<Router>` component will be automatically injected.
|
|
83
|
-
:::
|
|
84
|
-
|
|
85
|
-
## Run Test Cases
|
|
86
|
-
|
|
87
|
-
Execute the above `test` command to run the test cases:
|
|
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
|
-
```
|
|
@@ -1,95 +0,0 @@
|
|
|
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
|
-

|
|
@@ -1,148 +0,0 @@
|
|
|
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
|
-
随后,你可以运行以下命令,这将自动在项目中初始化 Jest,并生成一个基础的 `jest.config.ts` 配置:
|
|
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
|
-
```
|
|
@@ -1,100 +0,0 @@
|
|
|
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
|
-
```
|