@be-link/smart-test 1.0.1-beta.24 → 1.0.1-beta.25

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 (123) hide show
  1. package/README.md +202 -320
  2. package/dist/bin/smart-test.js +1708 -1942
  3. package/dist/cli/commands/index.d.ts.map +1 -1
  4. package/dist/cli/commands/init.d.ts.map +1 -1
  5. package/dist/cli/commands/preset.d.ts +7 -0
  6. package/dist/cli/commands/preset.d.ts.map +1 -0
  7. package/dist/cli/commands/record.d.ts +1 -1
  8. package/dist/cli/commands/record.d.ts.map +1 -1
  9. package/dist/cli/commands/run.d.ts +7 -0
  10. package/dist/cli/commands/run.d.ts.map +1 -0
  11. package/dist/cli/loaders/config-loader.d.ts +41 -0
  12. package/dist/cli/loaders/config-loader.d.ts.map +1 -0
  13. package/dist/cli/loaders/env-loader.d.ts.map +1 -0
  14. package/dist/cli/loaders/preset-loader.d.ts +33 -0
  15. package/dist/cli/loaders/preset-loader.d.ts.map +1 -0
  16. package/dist/cli/templates/playwright.config.template.ts +12 -1
  17. package/dist/cli/templates/recording-preset.template.ts +53 -0
  18. package/dist/cli/templates/smart-test.config.template.ts +22 -14
  19. package/dist/core/config.d.ts.map +1 -1
  20. package/dist/core/types/ai.types.d.ts +59 -0
  21. package/dist/core/types/ai.types.d.ts.map +1 -0
  22. package/dist/core/types/api.types.d.ts +34 -0
  23. package/dist/core/types/api.types.d.ts.map +1 -0
  24. package/dist/core/types/index.d.ts +7 -0
  25. package/dist/core/types/index.d.ts.map +1 -0
  26. package/dist/core/types/recorder.types.d.ts +204 -0
  27. package/dist/core/types/recorder.types.d.ts.map +1 -0
  28. package/dist/generators/base-generator.d.ts +37 -0
  29. package/dist/generators/base-generator.d.ts.map +1 -0
  30. package/dist/generators/index.d.ts +6 -3
  31. package/dist/generators/index.d.ts.map +1 -1
  32. package/dist/generators/mock-generator.d.ts +27 -3
  33. package/dist/generators/mock-generator.d.ts.map +1 -1
  34. package/dist/generators/test-generator.d.ts +53 -0
  35. package/dist/generators/test-generator.d.ts.map +1 -0
  36. package/dist/index.d.ts +6 -5
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.esm.mjs +1346 -520
  39. package/dist/index.js +1347 -522
  40. package/dist/prompts/fragment-loader.d.ts +28 -0
  41. package/dist/prompts/fragment-loader.d.ts.map +1 -0
  42. package/dist/prompts/fragments/system/mock-generation-base.md +1 -0
  43. package/dist/prompts/fragments/system/mock-generation-example.md +53 -0
  44. package/dist/prompts/fragments/system/mock-generation-specs.md +25 -0
  45. package/dist/prompts/fragments/system/test-generation-api-reference.md +46 -0
  46. package/dist/prompts/fragments/system/test-generation-base.md +8 -0
  47. package/dist/prompts/fragments/system/test-generation-requirements.md +29 -0
  48. package/dist/prompts/fragments/user/test-generation-header.md +19 -0
  49. package/dist/prompts/fragments/user/test-generation-mock-hint.md +9 -0
  50. package/dist/prompts/fragments/user/test-generation-template.md +35 -0
  51. package/dist/prompts/index.d.ts +3 -0
  52. package/dist/prompts/index.d.ts.map +1 -0
  53. package/dist/prompts/mock-generation.prompt.d.ts +23 -0
  54. package/dist/prompts/mock-generation.prompt.d.ts.map +1 -0
  55. package/dist/prompts/test-generation.prompt.d.ts +47 -0
  56. package/dist/prompts/test-generation.prompt.d.ts.map +1 -0
  57. package/dist/recorders/action-tracker.d.ts +42 -0
  58. package/dist/recorders/action-tracker.d.ts.map +1 -0
  59. package/dist/recorders/index.d.ts +8 -0
  60. package/dist/recorders/index.d.ts.map +1 -0
  61. package/dist/recorders/interactive-recorder.d.ts +13 -102
  62. package/dist/recorders/interactive-recorder.d.ts.map +1 -1
  63. package/dist/recorders/screenshot-manager.d.ts +23 -0
  64. package/dist/recorders/screenshot-manager.d.ts.map +1 -0
  65. package/dist/services/ai/ai-service.d.ts +41 -0
  66. package/dist/services/ai/ai-service.d.ts.map +1 -0
  67. package/dist/services/ai/index.d.ts +2 -0
  68. package/dist/services/ai/index.d.ts.map +1 -0
  69. package/dist/services/browser/api-interceptor.d.ts +44 -0
  70. package/dist/services/browser/api-interceptor.d.ts.map +1 -0
  71. package/dist/services/browser/index.d.ts +2 -0
  72. package/dist/services/browser/index.d.ts.map +1 -0
  73. package/dist/utils/data-compressor.d.ts +54 -0
  74. package/dist/utils/data-compressor.d.ts.map +1 -0
  75. package/dist/utils/fs-utils.d.ts +7 -0
  76. package/dist/utils/fs-utils.d.ts.map +1 -0
  77. package/dist/utils/index.d.ts +9 -0
  78. package/dist/utils/index.d.ts.map +1 -0
  79. package/dist/utils/path-utils.d.ts +8 -0
  80. package/dist/utils/path-utils.d.ts.map +1 -0
  81. package/dist/utils/string-utils.d.ts +16 -0
  82. package/dist/utils/string-utils.d.ts.map +1 -0
  83. package/dist/workflows/record-and-generate.d.ts +96 -18
  84. package/dist/workflows/record-and-generate.d.ts.map +1 -1
  85. package/package.json +3 -2
  86. package/dist/analyzers/page-api-analyzer.d.ts +0 -106
  87. package/dist/analyzers/page-api-analyzer.d.ts.map +0 -1
  88. package/dist/cli/commands/gen.d.ts +0 -2
  89. package/dist/cli/commands/gen.d.ts.map +0 -1
  90. package/dist/cli/commands/generate-mock.d.ts +0 -6
  91. package/dist/cli/commands/generate-mock.d.ts.map +0 -1
  92. package/dist/cli/commands/generate-testcase.d.ts +0 -6
  93. package/dist/cli/commands/generate-testcase.d.ts.map +0 -1
  94. package/dist/cli/core/config-loader.d.ts +0 -69
  95. package/dist/cli/core/config-loader.d.ts.map +0 -1
  96. package/dist/cli/core/env-loader.d.ts.map +0 -1
  97. package/dist/cli/core/validators.d.ts +0 -27
  98. package/dist/cli/core/validators.d.ts.map +0 -1
  99. package/dist/cli/ui/interactive.d.ts +0 -32
  100. package/dist/cli/ui/interactive.d.ts.map +0 -1
  101. package/dist/core/ai-assistant.d.ts +0 -25
  102. package/dist/core/ai-assistant.d.ts.map +0 -1
  103. package/dist/core/prompts.d.ts +0 -14
  104. package/dist/core/prompts.d.ts.map +0 -1
  105. package/dist/core/types.d.ts +0 -265
  106. package/dist/core/types.d.ts.map +0 -1
  107. package/dist/generators/batch-mock-generator.d.ts +0 -42
  108. package/dist/generators/batch-mock-generator.d.ts.map +0 -1
  109. package/dist/generators/midscene-test-generator.d.ts +0 -57
  110. package/dist/generators/midscene-test-generator.d.ts.map +0 -1
  111. package/dist/generators/testcase-generator.d.ts +0 -6
  112. package/dist/generators/testcase-generator.d.ts.map +0 -1
  113. package/dist/utils/dom-extractor.d.ts +0 -37
  114. package/dist/utils/dom-extractor.d.ts.map +0 -1
  115. package/dist/utils/playwright-config-loader.d.ts +0 -52
  116. package/dist/utils/playwright-config-loader.d.ts.map +0 -1
  117. package/dist/utils/screenshot.d.ts +0 -8
  118. package/dist/utils/screenshot.d.ts.map +0 -1
  119. package/dist/utils/type-extractor.d.ts +0 -10
  120. package/dist/utils/type-extractor.d.ts.map +0 -1
  121. package/dist/utils/web-server-manager.d.ts +0 -27
  122. package/dist/utils/web-server-manager.d.ts.map +0 -1
  123. /package/dist/cli/{core → loaders}/env-loader.d.ts +0 -0
package/README.md CHANGED
@@ -1,420 +1,302 @@
1
1
  # @be-link/smart-test
2
2
 
3
- AI-powered visual testing for Playwright | 基于 AI 视觉模型的 Playwright 测试工具
3
+ AI-powered test recorder for Playwright | 基于 AI Playwright 测试录制工具
4
4
 
5
- ## 特性
5
+ ## 特性
6
6
 
7
- - 🎯 **AI 视觉检查**:使用 AI 视觉模型自动检查页面截图是否符合预期
8
- - 🤖 **AI 代码生成**:使用 AI 自动生成测试用例和 Mock 数据
9
- - 📝 **TypeScript 支持**:完整的 TypeScript 类型定义
10
- - 🔧 **灵活配置**:支持自定义 AI 模型和服务地址
7
+ - **交互式录制**:打开浏览器,手动操作页面,自动记录用户行为和 API 请求
8
+ - **预设模式录制**:通过配置文件定义测试场景,批量执行录制
9
+ - **AI 生成 Mock**:基于录制的 API 请求,AI 自动生成类型安全的 Mock 函数
10
+ - **AI 生成测试**:基于录制的操作步骤,AI 自动生成 Midscene 测试用例
11
+ - **TypeScript 支持**:完整的类型定义,生成的代码开箱即用
11
12
 
12
- ## 📦 安装
13
+ ## 安装
13
14
 
14
15
  ```bash
16
+ # 安装 smart-test
15
17
  pnpm add -D @be-link/smart-test
18
+
19
+ # 安装必需的依赖
20
+ pnpm add -D @midscene/web playwright @playwright/test dotenv tsx
16
21
  ```
17
22
 
18
- ## 🚀 快速开始
23
+ ## 快速开始
19
24
 
20
25
  ### 1. 初始化配置
21
26
 
22
- 首先在项目中初始化配置文件:
23
-
24
27
  ```bash
25
- # 在项目根目录运行
26
- smart-test init
28
+ npx smart-test init
27
29
  ```
28
30
 
29
- 然后编辑 `tests/smart-test.config.json`,配置 AI API 密钥:
30
-
31
- ```json
32
- {
33
- "ai": {
34
- "apiKey": "${VITE_AI_API_KEY}",
35
- "baseURL": "https://dashscope.aliyuncs.com/compatible-mode/v1",
36
- "visionModel": "qwen3-vl-plus",
37
- "codeModel": "qwen3-coder-plus"
38
- }
39
- }
40
- ```
31
+ 这会在项目中生成:
41
32
 
42
- 配置文件会在使用 AI 功能时自动加载,无需手动调用配置函数。
33
+ - `tests/smart-test.config.ts` - Smart Test 配置
34
+ - `playwright.config.ts` - Playwright 配置
35
+ - `tests/e2e/` - 测试文件目录
36
+ - `tests/mock/` - Mock 文件目录
43
37
 
44
- ### 2. AI 视觉检查
38
+ ### 2. 配置环境变量
45
39
 
46
- Playwright 测试中使用 AI 检查页面截图:
40
+ 在项目根目录创建 `.env` 文件,配置 Midscene AI 相关的环境变量:
47
41
 
48
- ```typescript
49
- import { test } from '@playwright/test';
50
- import { aiReviewScreenshot } from '@be-link/smart-test';
42
+ ```bash
43
+ # AI 模型 API 地址
44
+ MIDSCENE_MODEL_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
51
45
 
52
- test('页面显示正确', async ({ page }) => {
53
- await page.goto('/home');
46
+ # AI 模型 API 密钥
47
+ MIDSCENE_MODEL_API_KEY=your_api_key
54
48
 
55
- const result = await aiReviewScreenshot(page, '顶部显示logo和导航栏,主内容区域显示3个产品卡片');
49
+ # AI 模型名称
50
+ MIDSCENE_MODEL_NAME=qwen-vl-max-latest
56
51
 
57
- if (!result.skipped && result.issues?.length) {
58
- console.log('AI 发现的问题:', result.issues);
59
- }
60
- });
52
+ # AI 模型家族(可选,根据模型提供商设置)
53
+ MIDSCENE_MODEL_FAMILY=qwen-vl
61
54
  ```
62
55
 
63
- ### 3. AI 生成测试用例
56
+ > 💡 Smart Test 和 Midscene 共用相同的环境变量,无需重复配置
64
57
 
65
- 自动生成完整的 Playwright 测试用例:
58
+ ### 3. 开始录制
66
59
 
67
- ```typescript
68
- import { aiGenerateTestCase } from '@be-link/smart-test';
60
+ #### 方式一:预设模式录制(推荐)
69
61
 
70
- const result = await aiGenerateTestCase({
71
- pageUrl: '/coupon?userId=e2e-user&isPopup=true',
72
- scenario: '优惠券页面展示和 Tab 切换功能',
73
- apiMocks: [
74
- {
75
- path: '**/api/user/info/get-user-detail',
76
- description: '返回用户信息,包含 id、nickname、memberLevel 等字段',
77
- },
78
- {
79
- path: '**/api/user/coupon/get-available-coupons-grouped',
80
- description: '返回可用优惠券列表,按券 ID 分组',
81
- },
82
- ],
83
- aiCheckExpected: '顶部展示门店名称和用户昵称,列表中应显示3张优惠券卡片',
84
- testSteps: ['验证页面显示"优惠券"标题', '验证显示"夏日满减券"', '点击"核销券"按钮', '验证显示"到店核销券"文本'],
85
- });
62
+ 先创建预设配置:
86
63
 
87
- if (result.ok) {
88
- console.log('生成的测试代码:\n', result.code);
89
- }
64
+ ```bash
65
+ npx smart-test preset
90
66
  ```
91
67
 
92
- ### 4. AI 生成 Mock 数据
93
-
94
- 通过传入实际的 TypeScript 类型定义,AI 会生成完全符合接口规范的 Mock 数据:
68
+ 编辑生成的 `*.preset.ts` 文件:
95
69
 
96
70
  ```typescript
97
- import { aiGenerateMock } from '@be-link/smart-test';
98
- import fs from 'fs';
99
-
100
- // 读取类型定义文件
101
- const addressTypes = fs.readFileSync('./src/api/address/types.ts', 'utf-8');
102
-
103
- // 提取需要的类型定义
104
- const result = await aiGenerateMock({
105
- apiPath: '**/api/user/address/get-default-address',
106
- description: '返回用户默认地址信息',
107
- responseType: 'IDefaultAddressResp',
108
- typeDefinitions: [
109
- {
110
- typeName: 'IDefaultAddressResp',
111
- content: `export interface IDefaultAddressResp {
112
- /** 默认地址 */
113
- defaultAddress: IUserAddress | null;
114
- /** 自提地址 */
115
- pickupAddress: IPickUpStoreUserInfo | null;
116
- }`,
117
- },
118
- {
119
- typeName: 'IUserAddress',
120
- content: `export interface IUserAddress {
121
- /** 地址ID */
122
- id: string;
123
- /** 用户ID */
124
- userId: string;
125
- /** 收件人姓名 */
126
- receiverName: string;
127
- /** 收件人手机号 */
128
- receiverMobile: string;
129
- /** 省份名称 */
130
- provinceName: string;
131
- /** 城市名称 */
132
- cityName: string;
133
- /** 区县名称 */
134
- districtName: string;
135
- /** 详细地址 */
136
- detailAddress: string;
137
- /** 是否默认地址:1-是,0-否 */
138
- isDefault: number;
139
- /** 创建时间(毫秒时间戳) */
140
- createdAt: number;
141
- }`,
142
- },
71
+ import type { RecordingPreset } from '@be-link/smart-test';
72
+
73
+ const preset: RecordingPreset = {
74
+ pageUrl: 'http://localhost:8080/login',
75
+ caseName: 'user-login',
76
+ testCases: [
143
77
  {
144
- typeName: 'IPickUpStoreUserInfo',
145
- content: `export interface IPickUpStoreUserInfo {
146
- id?: string;
147
- /** 用户ID */
148
- userId: string;
149
- /** 提货人手机号 */
150
- receiverMobile: string;
151
- /** 提货人名称 */
152
- receiverName: string;
153
- }`,
78
+ name: '用户登录成功',
79
+ steps: ['输入用户名 testuser', '输入密码 123456', '点击登录按钮'],
80
+ expected: '跳转到首页,显示欢迎信息',
154
81
  },
155
82
  ],
156
- });
83
+ viewport: 'mobile-ios',
84
+ headless: false,
85
+ };
157
86
 
158
- if (result.ok) {
159
- console.log('生成的 Mock 代码:\n', result.code);
160
- // AI 会严格按照类型定义生成符合规范的 mock 数据
161
- }
87
+ export default preset;
162
88
  ```
163
89
 
164
- ### 5. 通用代码生成
165
-
166
- 使用 AI 生成任意 TypeScript 代码:
167
-
168
- ```typescript
169
- import { aiGenerateCode } from '@be-link/smart-test';
170
-
171
- const result = await aiGenerateCode({
172
- prompt: '生成一个函数,用于计算两个日期之间的天数差',
173
- context: `// 项目中的日期工具示例
174
- function formatDate(date: Date): string {
175
- return date.toISOString().split('T')[0];
176
- }`,
177
- });
90
+ 然后执行录制:
178
91
 
179
- if (result.ok) {
180
- console.log('生成的代码:\n', result.code);
181
- }
92
+ ```bash
93
+ npx smart-test run login.preset.ts
182
94
  ```
183
95
 
184
- ## 📖 API 文档
185
-
186
- ### aiReviewScreenshot
96
+ #### 方式二:交互式录制
187
97
 
188
- 使用 AI 视觉模型检查页面截图是否符合预期。
189
-
190
- ```typescript
191
- function aiReviewScreenshot(page: Page, options: string | AiCheckOptions): Promise<AiCheckResult>;
98
+ ```bash
99
+ npx smart-test record
192
100
  ```
193
101
 
194
- **参数:**
102
+ 按照提示输入:
195
103
 
196
- - `page`: Playwright Page 对象
197
- - `options`: 检查选项
198
- - 字符串:直接传入预期描述
199
- - 对象:包含 `expected`(预期描述)、`fullPage`(是否全页截图)等配置
104
+ 1. 页面 URL
105
+ 2. 测试用例名称
106
+ 3. 测试场景描述
107
+ 4. 视口尺寸
200
108
 
201
- **返回值:**
109
+ ### 4. 运行测试
202
110
 
203
- ```typescript
204
- interface AiCheckResult {
205
- ok: boolean; // 检查是否通过
206
- issues?: string[]; // 发现的问题列表
207
- suggestion?: string[]; // 改进建议列表
208
- skipped?: boolean; // 是否跳过检查
209
- reason?: string; // 跳过原因
210
- rawResponse?: string; // AI 原始响应
211
- }
111
+ ```bash
112
+ npx playwright test
212
113
  ```
213
114
 
214
- ### aiGenerateTestCase
115
+ ## 生成的文件
215
116
 
216
- 使用 AI 生成完整的 Playwright 测试用例。
117
+ 录制完成后,会在 `tests/` 目录生成:
217
118
 
218
- ```typescript
219
- function aiGenerateTestCase(options: AiTestCaseGenerationOptions): Promise<AiCodeGenerationResult>;
220
119
  ```
221
-
222
- **参数:**
223
-
224
- ```typescript
225
- interface AiTestCaseGenerationOptions {
226
- pageUrl: string; // 页面 URL
227
- scenario: string; // 测试场景描述
228
- apiMocks?: ApiMockConfig[]; // API Mock 配置列表
229
- aiCheckExpected?: string; // AI 视觉检查预期
230
- testSteps?: string[]; // 测试步骤列表
231
- referenceCode?: string; // 参考代码
232
- // ... 以及 AiBaseConfig 的所有配置项
233
- }
234
-
235
- interface ApiMockConfig {
236
- path: string; // API 路径(支持通配符)
237
- description: string; // Mock 数据描述
238
- }
120
+ tests/
121
+ ├── e2e/
122
+ │ └── {caseName}.spec.ts # Midscene 测试用例
123
+ ├── mock/
124
+ │ └── {caseName}.mock.ts # Mock 函数
125
+ └── smart-test.config.ts # 配置文件
239
126
  ```
240
127
 
241
- ### aiGenerateMock
242
-
243
- 使用 AI 生成 API Mock 函数。
128
+ ### Mock 文件示例
244
129
 
245
130
  ```typescript
246
- function aiGenerateMock(options: AiMockGenerationOptions): Promise<AiCodeGenerationResult>;
131
+ /**
132
+ * 自动生成的 Mock 文件
133
+ * @generated by @be-link/smart-test
134
+ */
135
+ import type { Page } from '@playwright/test';
136
+
137
+ export async function mockUserLoginApis(page: Page): Promise<void> {
138
+ await page.route('**/api/user/login', async (route) => {
139
+ await route.fulfill({
140
+ status: 200,
141
+ contentType: 'application/json',
142
+ body: JSON.stringify({
143
+ code: 0,
144
+ data: { token: 'xxx', userId: '123' },
145
+ }),
146
+ });
147
+ });
148
+ }
247
149
  ```
248
150
 
249
- **参数:**
151
+ ### 测试文件示例
250
152
 
251
153
  ```typescript
252
- interface AiMockGenerationOptions {
253
- apiPath: string; // API 路径
254
- description: string; // Mock 数据描述
255
- responseType?: string; // 响应数据类型名称(可选)
256
- typeDefinitions?: TypeDefinition[]; // TypeScript 类型定义列表(可选)
257
- referenceCode?: string; // 参考代码
258
- // ... 以及 AiBaseConfig 的所有配置项
259
- }
154
+ /**
155
+ * 自动生成的测试文件
156
+ * @generated by @be-link/smart-test
157
+ */
158
+ import { expect, test } from '@playwright/test';
159
+ import { PlaywrightAgent } from '@midscene/web/playwright';
160
+
161
+ import { mockUserLoginApis } from '../mock/user-login.mock';
162
+
163
+ test.describe('user-login', () => {
164
+ let agent: PlaywrightAgent;
165
+
166
+ test.beforeEach(async ({ page }) => {
167
+ await mockUserLoginApis(page);
168
+ await page.goto('/login');
169
+ await page.waitForLoadState('networkidle');
170
+ agent = new PlaywrightAgent(page);
171
+ });
260
172
 
261
- interface TypeDefinition {
262
- typeName: string; // 类型名称
263
- content: string; // 类型定义内容
264
- }
173
+ test('用户登录成功', async () => {
174
+ await agent.aiAction('输入用户名 testuser');
175
+ await agent.aiAction('输入密码 123456');
176
+ await agent.aiAction('点击登录按钮');
177
+ await agent.aiAssert('跳转到首页,显示欢迎信息');
178
+ });
179
+ });
265
180
  ```
266
181
 
267
- **使用说明:**
268
- 传入 `typeDefinitions` 和 `responseType`,AI 会严格按照 TypeScript 类型定义生成 mock 数据,确保类型安全和数据准确性
182
+ ## CLI 命令
269
183
 
270
- ### aiGenerateCode
184
+ ### smart-test init
271
185
 
272
- 通用的 AI 代码生成函数。
186
+ 初始化配置文件和目录结构。
273
187
 
274
- ```typescript
275
- function aiGenerateCode(options: AiCodeGenerationOptions): Promise<AiCodeGenerationResult>;
188
+ ```bash
189
+ npx smart-test init
276
190
  ```
277
191
 
278
- **参数:**
192
+ ### smart-test preset
279
193
 
280
- ```typescript
281
- interface AiCodeGenerationOptions {
282
- prompt: string; // 代码生成描述
283
- context?: string; // 上下文代码
284
- // ... 以及 AiBaseConfig 的所有配置项
285
- }
286
- ```
287
-
288
- **返回值:**
194
+ 创建录制预设配置文件。
289
195
 
290
- ```typescript
291
- interface AiCodeGenerationResult {
292
- ok: boolean; // 是否成功生成
293
- code?: string; // 生成的代码
294
- skipped?: boolean; // 是否跳过
295
- reason?: string; // 跳过或失败原因
296
- rawResponse?: string; // AI 原始响应
297
- }
196
+ ```bash
197
+ npx smart-test preset [filename]
298
198
  ```
299
199
 
300
- ## 🎯 使用场景
200
+ ### smart-test run
301
201
 
302
- ### 场景 1:视觉回归测试
202
+ 使用预设配置执行录制。
303
203
 
304
- 使用 AI 自动检测页面的视觉变化,无需手动维护大量的断言代码:
204
+ ```bash
205
+ npx smart-test run <preset-file>
206
+ ```
305
207
 
306
- ```typescript
307
- test('首页显示正常', async ({ page }) => {
308
- await page.goto('/');
208
+ ### smart-test record
309
209
 
310
- const result = await aiReviewScreenshot(page, {
311
- expected: '页面顶部显示网站logo和主导航,中间显示轮播图,下方显示4个产品分类卡片',
312
- fullPage: true,
313
- });
210
+ 启动交互式录制模式。
314
211
 
315
- expect(result.ok).toBeTruthy();
316
- });
212
+ ```bash
213
+ npx smart-test record
317
214
  ```
318
215
 
319
- ### 场景 2:快速生成测试代码
216
+ ## 配置文件
320
217
 
321
- 为新功能快速生成测试用例骨架,节省编写测试代码的时间:
218
+ ### smart-test.config.ts
322
219
 
323
220
  ```typescript
324
- // 生成测试用例
325
- const result = await aiGenerateTestCase({
326
- pageUrl: '/product/123',
327
- scenario: '产品详情页展示和加入购物车功能',
328
- apiMocks: [
329
- { path: '**/api/product/detail', description: '返回产品详情' },
330
- { path: '**/api/cart/add', description: '加入购物车成功' },
331
- ],
332
- testSteps: ['验证显示产品名称和价格', '点击"加入购物车"按钮', '验证显示成功提示'],
333
- });
334
-
335
- // 将生成的代码保存到文件,然后根据实际需要调整
221
+ import type { SmartTestConfig } from '@be-link/smart-test';
222
+
223
+ const config: SmartTestConfig = {
224
+ ai: {
225
+ // AI 模型配置(API Key 和 Base URL 从环境变量读取)
226
+ visionModel: 'qwen3-vl-plus',
227
+ codeModel: 'qwen3-coder-plus',
228
+ },
229
+ recording: {
230
+ // 测试文件输出目录
231
+ testDir: 'tests/e2e',
232
+ // Mock 文件输出目录
233
+ mockDir: 'tests/mock',
234
+ // API 路径匹配模式
235
+ apiPathPattern: '**/c-bff/**',
236
+ // 排除的 API 路径
237
+ excludeApiPatterns: [],
238
+ },
239
+ };
240
+
241
+ export default config;
336
242
  ```
337
243
 
338
- ### 场景 3:Mock 数据管理
339
-
340
- 通过传入实际的类型定义,确保生成的 Mock 数据完全符合接口规范:
244
+ ### 预设配置 (\*.preset.ts)
341
245
 
342
246
  ```typescript
343
- // 读取或定义类型
344
- import { readFileSync } from 'fs';
345
-
346
- const addressTypeContent = readFileSync('./src/api/address/types.ts', 'utf-8');
347
- // 或者直接定义类型字符串
348
-
349
- const result = await aiGenerateMock({
350
- apiPath: '**/api/user/address/get-default-address',
351
- description: '返回用户默认地址',
352
- responseType: 'IDefaultAddressResp',
353
- typeDefinitions: [
247
+ import type { RecordingPreset } from '@be-link/smart-test';
248
+
249
+ const preset: RecordingPreset = {
250
+ // 要测试的页面 URL
251
+ pageUrl: 'http://localhost:8080/page',
252
+ // 测试用例名称(用于文件命名)
253
+ caseName: 'test-case',
254
+ // 测试场景列表
255
+ testCases: [
354
256
  {
355
- typeName: 'IDefaultAddressResp',
356
- content: extractTypeFromFile(addressTypeContent, 'IDefaultAddressResp'),
357
- },
358
- {
359
- typeName: 'IUserAddress',
360
- content: extractTypeFromFile(addressTypeContent, 'IUserAddress'),
257
+ name: '场景名称',
258
+ steps: ['步骤1', '步骤2'],
259
+ expected: '预期结果',
361
260
  },
362
261
  ],
363
- });
364
-
365
- // 生成的 mock 数据会严格符合类型定义,包括:
366
- // - 字段类型匹配(string、number、boolean、null 等)
367
- // - 必填/可选字段正确
368
- // - 嵌套对象结构准确
369
- // - 根据注释生成合理的测试数据
370
- ```
371
-
372
- ## ⚙️ 配置说明
373
-
374
- ### 默认配置
375
-
376
- ```typescript
377
- {
378
- baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
379
- visionModel: 'qwen3-vl-plus',
380
- codeModel: 'qwen3-coder-plus',
381
- timeout: 30000
382
- }
262
+ // 子目录(可选)
263
+ subDir: '',
264
+ // 视口尺寸:'mobile-ios' | 'mobile-android' | 'tablet' | 'desktop' | 'desktop-wide'
265
+ viewport: 'mobile-ios',
266
+ // 是否使用无头模式
267
+ headless: false,
268
+ };
269
+
270
+ export default preset;
383
271
  ```
384
272
 
385
- ## 🔍 最佳实践
273
+ ## 环境变量
386
274
 
387
- ### 1. 合理使用 AI 检查
275
+ | 变量名 | 说明 | 必填 |
276
+ | ------------------------- | ---------------- | ---- |
277
+ | `MIDSCENE_MODEL_BASE_URL` | AI 模型 API 地址 | 是 |
278
+ | `MIDSCENE_MODEL_API_KEY` | AI 模型 API 密钥 | 是 |
279
+ | `MIDSCENE_MODEL_NAME` | AI 模型名称 | 是 |
280
+ | `MIDSCENE_MODEL_FAMILY` | AI 模型家族 | 否 |
388
281
 
389
- AI 视觉检查适合用于:
282
+ ## 依赖说明
390
283
 
391
- - 整体布局和结构验证
392
- - 内容完整性检查
393
- - 视觉回归测试
284
+ | 依赖 | 说明 |
285
+ | ------------------ | ----------------------------- |
286
+ | `@midscene/web` | Midscene AI 驱动的 Web 测试库 |
287
+ | `playwright` | 浏览器自动化核心库 |
288
+ | `@playwright/test` | Playwright 测试框架 |
289
+ | `dotenv` | 环境变量加载 |
290
+ | `tsx` | TypeScript 执行器 |
394
291
 
395
- 不适合用于:
292
+ ## 与 Midscene 配合
396
293
 
397
- - 精确的像素级对比
398
- - ❌ 颜色值精确匹配
399
- - ❌ 性能敏感的场景
294
+ 生成的测试用例基于 [Midscene](https://midscenejs.com/) 的 AI 驱动 API:
400
295
 
401
- ### 2. 组合使用
296
+ - `agent.aiAction()` - AI 驱动的页面操作
297
+ - `agent.aiQuery()` - AI 驱动的数据查询
298
+ - `agent.aiAssert()` - AI 驱动的断言
402
299
 
403
- AI 检查与传统断言结合使用,获得最佳效果:
300
+ ## License
404
301
 
405
- ```typescript
406
- test('优惠券页面', async ({ page }) => {
407
- await page.goto('/coupon');
408
-
409
- // 传统断言:精确的功能验证
410
- await expect(page.getByText('优惠券')).toBeVisible();
411
- await expect(page.getByRole('button', { name: '核销券' })).toBeVisible();
412
-
413
- // AI 检查:整体视觉验证
414
- const aiResult = await aiReviewScreenshot(page, '页面整体布局合理,优惠券卡片排列整齐,信息展示清晰');
415
-
416
- if (!aiResult.skipped && aiResult.issues?.length) {
417
- console.warn('AI 发现的潜在问题:', aiResult.issues);
418
- }
419
- });
420
- ```
302
+ MIT