@bleedingdev/modern-js-main-doc 3.2.0-ultramodern.11 → 3.2.0-ultramodern.110

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.
Files changed (79) hide show
  1. package/docs/en/apis/app/commands.mdx +32 -32
  2. package/docs/en/community/blog/2022-0708-updates.md +1 -1
  3. package/docs/en/community/blog/2022-0910-updates.md +2 -2
  4. package/docs/en/community/blog/v2-release-note.mdx +5 -5
  5. package/docs/en/community/blog/v3-release-note.mdx +1 -1
  6. package/docs/en/community/contributing-guide.mdx +2 -3
  7. package/docs/en/community/releases.mdx +2 -2
  8. package/docs/en/components/build-output.mdx +1 -1
  9. package/docs/en/components/debug-app.mdx +1 -1
  10. package/docs/en/components/deploy-command.mdx +3 -3
  11. package/docs/en/components/init-app.mdx +38 -36
  12. package/docs/en/components/init-rspack-app.mdx +1 -1
  13. package/docs/en/components/prerequisites.mdx +1 -2
  14. package/docs/en/components/serve-command.mdx +3 -3
  15. package/docs/en/configure/app/bff/runtime-framework.mdx +1 -1
  16. package/docs/en/configure/app/usage.mdx +6 -6
  17. package/docs/en/guides/advanced-features/international/api.mdx +4 -1
  18. package/docs/en/guides/advanced-features/international/configuration.mdx +1 -0
  19. package/docs/en/guides/advanced-features/international/locale-detection.mdx +1 -1
  20. package/docs/en/guides/advanced-features/international/routing.mdx +43 -2
  21. package/docs/en/guides/basic-features/debug/using-storybook.mdx +1 -1
  22. package/docs/en/guides/basic-features/deploy.mdx +14 -14
  23. package/docs/en/guides/basic-features/env-vars.mdx +2 -2
  24. package/docs/en/guides/basic-features/routes/config-routes.mdx +2 -2
  25. package/docs/en/guides/basic-features/routes/routes.mdx +24 -9
  26. package/docs/en/guides/basic-features/testing/_meta.json +1 -1
  27. package/docs/en/guides/concept/server.mdx +2 -2
  28. package/docs/en/guides/get-started/quick-start.mdx +2 -2
  29. package/docs/en/guides/get-started/tech-stack.mdx +10 -4
  30. package/docs/en/guides/get-started/ultramodern.mdx +93 -16
  31. package/docs/en/guides/topic-detail/module-federation/application.mdx +1 -1
  32. package/docs/en/guides/topic-detail/module-federation/deploy.mdx +2 -2
  33. package/docs/en/guides/topic-detail/module-federation/usage.mdx +5 -5
  34. package/docs/en/guides/troubleshooting/builder.mdx +1 -1
  35. package/docs/en/guides/upgrade/other.mdx +7 -7
  36. package/docs/zh/apis/app/commands.mdx +32 -32
  37. package/docs/zh/community/blog/2022-0708-updates.md +1 -1
  38. package/docs/zh/community/blog/2022-0910-updates.md +2 -2
  39. package/docs/zh/community/blog/v2-release-note.mdx +5 -5
  40. package/docs/zh/community/blog/v3-release-note.mdx +1 -1
  41. package/docs/zh/community/contributing-guide.mdx +2 -3
  42. package/docs/zh/community/releases.mdx +2 -2
  43. package/docs/zh/components/build-output.mdx +1 -1
  44. package/docs/zh/components/debug-app.mdx +1 -1
  45. package/docs/zh/components/deploy-command.mdx +3 -3
  46. package/docs/zh/components/init-app.mdx +36 -34
  47. package/docs/zh/components/init-rspack-app.mdx +1 -1
  48. package/docs/zh/components/prerequisites.mdx +1 -2
  49. package/docs/zh/components/serve-command.mdx +3 -3
  50. package/docs/zh/configure/app/bff/runtime-framework.mdx +1 -1
  51. package/docs/zh/configure/app/usage.mdx +5 -5
  52. package/docs/zh/guides/advanced-features/international/api.mdx +4 -1
  53. package/docs/zh/guides/advanced-features/international/configuration.mdx +1 -0
  54. package/docs/zh/guides/advanced-features/international/locale-detection.mdx +1 -1
  55. package/docs/zh/guides/advanced-features/international/routing.mdx +43 -2
  56. package/docs/zh/guides/basic-features/debug/using-storybook.mdx +1 -1
  57. package/docs/zh/guides/basic-features/deploy.mdx +13 -13
  58. package/docs/zh/guides/basic-features/env-vars.mdx +2 -2
  59. package/docs/zh/guides/basic-features/routes/config-routes.mdx +2 -2
  60. package/docs/zh/guides/basic-features/routes/routes.mdx +24 -9
  61. package/docs/zh/guides/basic-features/testing/_meta.json +1 -1
  62. package/docs/zh/guides/concept/server.mdx +2 -2
  63. package/docs/zh/guides/get-started/quick-start.mdx +2 -2
  64. package/docs/zh/guides/get-started/tech-stack.mdx +10 -4
  65. package/docs/zh/guides/get-started/ultramodern.mdx +90 -1
  66. package/docs/zh/guides/topic-detail/module-federation/application.mdx +1 -1
  67. package/docs/zh/guides/topic-detail/module-federation/deploy.mdx +2 -2
  68. package/docs/zh/guides/topic-detail/module-federation/usage.mdx +5 -5
  69. package/docs/zh/guides/troubleshooting/builder.mdx +1 -1
  70. package/docs/zh/guides/upgrade/other.md +7 -8
  71. package/main-doc/docs/en/guides/get-started/ultramodern.mdx +97 -14
  72. package/main-doc/docs/zh/guides/get-started/ultramodern.mdx +62 -3
  73. package/package.json +12 -12
  74. package/docs/en/guides/basic-features/testing/cypress.mdx +0 -95
  75. package/docs/en/guides/basic-features/testing/jest.mdx +0 -148
  76. package/docs/en/guides/basic-features/testing/vitest.mdx +0 -100
  77. package/docs/zh/guides/basic-features/testing/cypress.mdx +0 -95
  78. package/docs/zh/guides/basic-features/testing/jest.mdx +0 -148
  79. package/docs/zh/guides/basic-features/testing/vitest.mdx +0 -100
@@ -38,7 +38,7 @@ UltraModern.js V3 记录的是一套“更强默认值的 Modern.js 参考档案
38
38
  | Metrics 与 Trace 关联 | SSR metrics 不解析 W3C trace 上下文 | 解析 `traceparent` 并注入 `trace_id` / `span_id` 标签 | 已实现 | 提升跨系统观测关联度 |
39
39
  | 应用级 MF SSR 合约开关 | 无专门 app-level MF SSR 稳定性契约开关 | 新增 `server.ssr.moduleFederationAppSSR`,并在检测到 MF SSR 标记时自动启用环境变量握手 | 已实现 | 注入 `process.env.MODERN_MF_APP_SSR` |
40
40
  | 应用级 MF SSR 运行时桥接 | 非稳定默认桥接路径 | V3 在「服务端渲染 + MF 标记」场景下提供稳定桥接默认行为 | 已实现 | 保留显式关闭路径 |
41
- | MF 远程加载可靠性契约 | 远程加载重试/降级策略通常由业务自管 | 新增 timeout/network/contract-error 的确定性降级矩阵与分布式 OTEL 连续性断言 | 已实现 | 对应 `routes-tanstack-mf` 可靠性套件 |
41
+ | MF vertical 加载可靠性契约 | 加载重试/降级策略通常由业务自管 | 新增 timeout/network/contract-error 的确定性降级矩阵与分布式 OTEL 连续性断言 | 已实现 | 对应 `routes-tanstack-mf` 可靠性套件 |
42
42
  | BFF 运行时选型 | Modern.js V3 基线仅提供 Hono 运行时路径(无内建 Effect 运行时) | 将 Effect 设为默认运行时,并采用严格运行时拆分(`effect` -> `api/effect`,`hono` -> `api/lambda`),同时补齐 Effect-Schema-only MF 数据契约与 failure-injection 覆盖 | 已实现(Effect 默认 + 严格拆分) | 该流明确不引入 Zod |
43
43
  | 模块 SDK 合约产物 | 无框架级模块契约产物 | 新增机器可读模块家族契约与类型化模块 SDK 接口 | 已实现 | `module-sdk-contracts.json` + `moduleSdk.d.ts` |
44
44
  | 边界反模式 CI 守卫 | 无专门边界反模式工作流 | 新增基于 profile 的边界检查(导入边界/必需钩子/模块禁用模式) | 已实现 | `.github/workflows/boundary-anti-patterns.yml` |
@@ -239,7 +239,7 @@ UltraModern.js V3 对应 Beads Stream D 落地了额外可靠性能力:
239
239
 
240
240
  - `@modern-js/plugin-bff` 运行时路径迁移到 Effect v4。
241
241
  - MF 数据拉取契约采用 Effect-only 指导(该流明确不引入 Zod)。
242
- - 远程加载可靠性矩阵覆盖 timeout/network/contract error 的确定性注入场景。
242
+ - MF vertical 加载可靠性矩阵覆盖 timeout/network/contract error 的确定性注入场景。
243
243
  - build 与 serve 路径重新启用分布式 trace 连续性断言。
244
244
  - 数据平台架构补齐 operation identity、请求/水合 envelope 完整性、scope key 与失效路由契约。
245
245
 
@@ -247,7 +247,7 @@ UltraModern.js V3 对应 Beads Stream D 落地了额外可靠性能力:
247
247
 
248
248
  - `docs/super-app-rfc-adr/ADR-0003-effect-only-mf-data-fetch-reliability.md`
249
249
  - `packages/cli/plugin-bff/docs/data-platform-architecture.md`
250
- - `tests/integration/routes-tanstack-mf/test/remote-loader-reliability.test.ts`
250
+ - `routes-tanstack-mf` 可靠性覆盖
251
251
 
252
252
  ### 11) 发布与模块认证 Gate 模型
253
253
 
@@ -280,6 +280,65 @@ UltraModern.js V3 对应 Beads Stream D 落地了额外可靠性能力:
280
280
  - 将应用级 MF SSR 强制为所有应用的默认路径。
281
281
  - 将 Effect-only 数据获取运行时强制为所有应用的默认路径。
282
282
 
283
+ ## 人类工作流
284
+
285
+ 公开的 BleedingDev create 包默认从简单路径开始。默认命令会创建一个
286
+ 可上线的 UltraModern 单应用,包含 `presetUltramodern(...)`、SSR、
287
+ TanStack Router、Tailwind CSS v4、i18n、Effect BFF、生成质量 gate,以及
288
+ Cloudflare 部署基础:
289
+
290
+ ```bash
291
+ pnpm dlx @bleedingdev/modern-js-create myapp
292
+ cd myapp
293
+ mise install
294
+ mise exec -- pnpm install
295
+ mise exec -- pnpm ultramodern:check
296
+ ```
297
+
298
+ 只有当独立归属边界有实际价值时,才创建 SuperApp workspace:
299
+
300
+ ```bash
301
+ pnpm dlx @bleedingdev/modern-js-create my-super-app --ultramodern-workspace
302
+ cd my-super-app
303
+ mise install
304
+ mise exec -- pnpm install
305
+ mise exec -- pnpm ultramodern:check
306
+ ```
307
+
308
+ 真实业务边界出现后,再添加对应 MicroVertical:
309
+
310
+ ```bash
311
+ pnpm dlx @bleedingdev/modern-js-create transportation --vertical
312
+ pnpm dlx @bleedingdev/modern-js-create food-delivery --vertical
313
+ pnpm dlx @bleedingdev/modern-js-create payments --vertical
314
+ pnpm dlx @bleedingdev/modern-js-create maps --vertical
315
+ mise exec -- pnpm ultramodern:check
316
+ ```
317
+
318
+ `--vertical` 会修改当前 workspace:创建 vertical 包,并更新 topology 元数据、
319
+ ownership 记录、shell Module Federation、开发 overlays、包依赖、生成契约、
320
+ 端口、路由归属 i18n、CSS 隔离,以及 vertical 自己拥有的 Effect BFF/client surface。
321
+
322
+ 生成应用和 vertical 沿用正常的 Modern.js SSR 路径。SuperApp workspace 在需要
323
+ Module Federation SSR 时会加入 `server.ssr.moduleFederationAppSSR`,但这个开关是
324
+ 显式契约,不是所有应用的强制要求。
325
+
326
+ 每个应用都会产出 `src/routes/ultramodern-route-metadata` 和
327
+ `ultramodernLocalisedUrls`。i18n 插件在 `localeDetection.localisedUrls` 中读取它,
328
+ 并从 `/locales/{{lng}}/{{ns}}.json` 提供动态后端 JSON。
329
+
330
+ 生成契约会在 `.modernjs/ultramodern-generated-contract.json` 中写入
331
+ `cssFederation`:共享 design tokens 保留在 `packages/shared-design-tokens`,
332
+ shell CSS 拥有 shell layer,每个 vertical 拥有自己的 CSS layer 与应用本地前缀,
333
+ SSR 首屏使用 Modern/Rspack 产物和 manifest 归属的 vertical CSS。
334
+
335
+ 生成 workspace 包含 `scripts/proof-cloudflare-version.mjs`,用于 live Cloudflare 和
336
+ Zephyr 证据。Live 证明需要公开 Worker URL 和 Zephyr 凭据;本地检查仍可校验
337
+ 生成契约、构建、Cloudflare 输出、dry-run Zephyr 证据计划和本地证据 schema。
338
+
339
+ BleedingDev 包通过 GitHub Actions trusted publishing 发布。公开发布 workflow 不使用
340
+ 长期 npm token;不要从开发机器手动发布包。
341
+
283
342
  ## 基线开关(可按需关闭)
284
343
 
285
344
  生成的 `presetUltramodern(...)` create 模板会开启更严格的平台契约。以下环境变量会在生成的 `modern.config.ts` 中读取,可按应用或按环境关闭/覆盖:
package/package.json CHANGED
@@ -18,30 +18,30 @@
18
18
  "modern",
19
19
  "modern.js"
20
20
  ],
21
- "version": "3.2.0-ultramodern.11",
21
+ "version": "3.2.0-ultramodern.110",
22
22
  "publishConfig": {
23
23
  "registry": "https://registry.npmjs.org/",
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
27
  "mermaid": "^11.15.0",
28
- "@modern-js/sandpack-react": "npm:@bleedingdev/modern-js-sandpack-react@3.2.0-ultramodern.11"
28
+ "@modern-js/sandpack-react": "npm:@bleedingdev/modern-js-sandpack-react@3.2.0-ultramodern.110"
29
29
  },
30
30
  "devDependencies": {
31
- "@rsbuild/plugin-sass": "1.5.2",
32
- "@rspress/core": "2.0.11",
33
- "@rspress/plugin-llms": "2.0.11",
34
- "@rspress/shared": "2.0.11",
35
- "@shikijs/transformers": "^4.0.2",
31
+ "@rsbuild/plugin-sass": "1.5.3",
32
+ "@rspress/core": "2.0.13",
33
+ "@rspress/plugin-llms": "2.0.13",
34
+ "@rspress/shared": "2.0.13",
35
+ "@shikijs/transformers": "^4.1.0",
36
36
  "@types/fs-extra": "11.0.4",
37
- "@types/node": "^25.8.0",
38
- "@typescript/native-preview": "7.0.0-dev.20260516.1",
37
+ "@types/node": "^25.9.1",
38
+ "@typescript/native-preview": "7.0.0-dev.20260606.1",
39
39
  "classnames": "^2.5.1",
40
40
  "clsx": "^2.1.1",
41
41
  "fs-extra": "^11.3.5",
42
- "react": "^19.2.6",
43
- "react-dom": "^19.2.6",
44
- "rsbuild-plugin-open-graph": "1.1.2"
42
+ "react": "^19.2.7",
43
+ "react-dom": "^19.2.7",
44
+ "rsbuild-plugin-open-graph": "1.1.3"
45
45
  },
46
46
  "scripts": {
47
47
  "dev": "rspress dev",
@@ -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
- ![cypress](https://lf3-static.bytednsdoc.com/obj/eden-cn/nuvjhpqnuvr/cypress.jpg)
@@ -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
- ![cypress](https://lf3-static.bytednsdoc.com/obj/eden-cn/nuvjhpqnuvr/cypress.jpg)