@be-link/smart-test 1.0.1-beta.7 → 1.0.1-beta.8

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 (41) hide show
  1. package/README.md +32 -271
  2. package/dist/core/ai-assistant.d.ts.map +1 -1
  3. package/dist/core/config.d.ts +1 -0
  4. package/dist/core/config.d.ts.map +1 -1
  5. package/dist/core/types.d.ts +10 -0
  6. package/dist/core/types.d.ts.map +1 -1
  7. package/dist/index.esm.js +36 -3
  8. package/dist/index.js +56 -3
  9. package/dist/utils/screenshot.d.ts +9 -0
  10. package/dist/utils/screenshot.d.ts.map +1 -1
  11. package/package.json +3 -20
  12. package/bin/smart-test.js +0 -15
  13. package/dist/analyzer/code-analyzer.d.ts +0 -32
  14. package/dist/analyzer/code-analyzer.d.ts.map +0 -1
  15. package/dist/analyzer/index.d.ts +0 -7
  16. package/dist/analyzer/index.d.ts.map +0 -1
  17. package/dist/analyzer/mock-generator.d.ts +0 -53
  18. package/dist/analyzer/mock-generator.d.ts.map +0 -1
  19. package/dist/analyzer/react-analyzer.d.ts +0 -62
  20. package/dist/analyzer/react-analyzer.d.ts.map +0 -1
  21. package/dist/analyzer/test-generator.d.ts +0 -38
  22. package/dist/analyzer/test-generator.d.ts.map +0 -1
  23. package/dist/analyzer/type-analyzer.d.ts +0 -50
  24. package/dist/analyzer/type-analyzer.d.ts.map +0 -1
  25. package/dist/analyzer/types.d.ts +0 -170
  26. package/dist/analyzer/types.d.ts.map +0 -1
  27. package/dist/cli/commands/generate.d.ts +0 -22
  28. package/dist/cli/commands/generate.d.ts.map +0 -1
  29. package/dist/cli/commands/init.d.ts +0 -5
  30. package/dist/cli/commands/init.d.ts.map +0 -1
  31. package/dist/cli/index.d.ts +0 -10
  32. package/dist/cli/index.d.ts.map +0 -1
  33. package/dist/cli/index.js +0 -2117
  34. package/dist/config/config-loader.d.ts +0 -35
  35. package/dist/config/config-loader.d.ts.map +0 -1
  36. package/dist/config/config-schema.d.ts +0 -85
  37. package/dist/config/config-schema.d.ts.map +0 -1
  38. package/dist/utils/error-handler.d.ts +0 -41
  39. package/dist/utils/error-handler.d.ts.map +0 -1
  40. package/dist/utils/logger.d.ts +0 -88
  41. package/dist/utils/logger.d.ts.map +0 -1
package/README.md CHANGED
@@ -6,36 +6,17 @@
6
6
 
7
7
  ## ✨ 特性
8
8
 
9
- ### 🤖 AI 视觉检查
10
-
11
- - 基于通义千问等视觉模型,智能检查页面是否符合预期
12
- - 支持自然语言描述测试预期
13
- - 自动识别页面问题并给出详细反馈
14
-
15
- ### 🎯 零代码测试生成(开发中)
16
-
17
- - **CLI 工具**:一条命令自动生成测试代码
18
- - **录制模式**:访问页面自动录制接口和交互
19
- - **代码分析**:扫描项目代码自动生成 Mock 数据
20
- - **AI 生成**:基于自然语言描述生成完整测试
21
-
22
- ### 🔧 灵活易用
23
-
24
- - 与 Playwright 无缝集成,零侵入设计
25
- - 支持全局配置和单次调用配置
26
- - 优雅降级:无 API Key 时自动跳过
27
- - 完整的 TypeScript 类型支持
28
-
29
- ### 📸 自动化
30
-
31
- - 自动截图并保存
32
- - 自动生成 Mock 数据
33
- - 自动生成测试用例
9
+ - 🤖 **AI 视觉检查**:基于通义千问等视觉模型,智能检查页面是否符合预期
10
+ - 🎯 **零侵入设计**:与 Playwright 无缝集成,无需修改现有测试代码
11
+ - 🔧 **灵活配置**:支持全局配置和单次调用配置
12
+ - 📸 **自动截图**:自动保存测试截图,方便排查问题
13
+ - 🚫 **优雅降级**:无 API Key 时自动跳过,不影响其他测试
14
+ - 📦 **TypeScript**:完整的类型定义支持
34
15
 
35
16
  ## 📦 安装
36
17
 
37
18
  ```bash
38
- # 使用 pnpm(推荐)
19
+ # 使用 pnpm
39
20
  pnpm add -D @be-link/smart-test
40
21
 
41
22
  # 使用 npm
@@ -47,56 +28,7 @@ yarn add -D @be-link/smart-test
47
28
 
48
29
  ## 🚀 快速开始
49
30
 
50
- ### 方式一:使用 CLI 工具(推荐)⭐
51
-
52
- #### 1. 初始化配置
53
-
54
- ```bash
55
- npx smart-test init
56
- ```
57
-
58
- 交互式配置向导会引导你完成设置:
59
-
60
- ```
61
- ━━━ 初始化 Smart Test 配置 ━━━
62
-
63
- ? 请输入 AI API Key: sk-xxxxx
64
- ? 选择 AI 模型: 通义千问 (qwen3-vl-plus)
65
- ? 测试文件目录: ./tests/e2e
66
- ? Helpers 目录: ./tests/helpers
67
- ? Playwright Base URL: http://localhost:8080
68
- ? 文件命名风格: kebab-case
69
-
70
- ✓ 配置文件已创建: .smarttestrc.json
71
- ```
72
-
73
- #### 2. 生成测试代码(开发中)
74
-
75
- ```bash
76
- # 录制模式 - 访问页面自动录制
77
- npx smart-test record --url http://localhost:8080/coupon
78
-
79
- # 代码分析模式 - 扫描页面代码
80
- npx smart-test generate --page src/pages/coupon/index.tsx
81
-
82
- # 描述生成模式 - 基于自然语言
83
- npx smart-test generate --desc "优惠券列表页,有可用券和已用券两个 tab"
84
-
85
- # 交互式模式 - 引导式生成
86
- npx smart-test generate --interactive
87
- ```
88
-
89
- #### 3. 运行测试
90
-
91
- ```bash
92
- npx playwright test
93
- ```
94
-
95
- ---
96
-
97
- ### 方式二:手动编程
98
-
99
- #### 1. 配置 API Key
31
+ ### 1. 配置 API Key
100
32
 
101
33
  在项目根目录创建 `.env` 文件:
102
34
 
@@ -104,7 +36,7 @@ npx playwright test
104
36
  AI_API_KEY=sk-your-api-key-here
105
37
  ```
106
38
 
107
- #### 2. 初始化配置
39
+ ### 2. 初始化配置
108
40
 
109
41
  在 `playwright.config.ts` 中配置:
110
42
 
@@ -123,7 +55,7 @@ export default defineConfig({
123
55
  });
124
56
  ```
125
57
 
126
- #### 3. 在测试中使用
58
+ ### 3. 在测试中使用
127
59
 
128
60
  ```typescript
129
61
  import { test, expect } from '@playwright/test';
@@ -146,95 +78,7 @@ test.describe('优惠券页面', () => {
146
78
  });
147
79
  ```
148
80
 
149
- ## 📖 CLI 命令参考
150
-
151
- ### `smart-test init`
152
-
153
- 初始化配置文件,交互式设置 AI API Key、模型、输出目录等。
154
-
155
- ```bash
156
- smart-test init
157
- ```
158
-
159
- ### `smart-test generate` (开发中)
160
-
161
- 生成测试代码。
162
-
163
- ```bash
164
- # 基础用法
165
- smart-test generate
166
-
167
- # 指定页面(代码分析模式)
168
- smart-test generate --page <path>
169
-
170
- # 指定 URL(录制模式)
171
- smart-test generate --url <url>
172
-
173
- # 基于描述(自然语言模式)
174
- smart-test generate --desc <description>
175
-
176
- # 交互式模式
177
- smart-test generate --interactive
178
-
179
- # 指定输出目录
180
- smart-test generate --page <path> --output tests/custom
181
-
182
- # 预览模式(不写入文件)
183
- smart-test generate --page <path> --dry-run
184
- ```
185
-
186
- **选项:**
187
-
188
- | 选项 | 简写 | 说明 |
189
- | ---------------------- | ---- | ---------------------------- |
190
- | `--page <path>` | `-p` | 页面文件路径(代码分析模式) |
191
- | `--url <url>` | `-u` | 页面 URL(录制模式) |
192
- | `--desc <description>` | `-d` | 页面描述(自然语言模式) |
193
- | `--output <dir>` | `-o` | 输出目录 |
194
- | `--interactive` | `-i` | 交互式模式 |
195
- | `--dry-run` | | 预览模式,不写入文件 |
196
-
197
- ### `smart-test record` (开发中)
198
-
199
- 录制模式的快捷命令(`generate --url` 的别名)。
200
-
201
- ```bash
202
- # 基础录制
203
- smart-test record --url http://localhost:8080/coupon
204
-
205
- # 手动操作模式
206
- smart-test record --url http://localhost:8080/coupon --manual
207
-
208
- # 交互式引导
209
- smart-test record --url http://localhost:8080/coupon --interactive
210
- ```
211
-
212
- **选项:**
213
-
214
- | 选项 | 简写 | 说明 |
215
- | ---------------- | ---- | ------------------------ |
216
- | `--url <url>` | `-u` | 要录制的页面 URL(必需) |
217
- | `--output <dir>` | `-o` | 输出目录 |
218
- | `--manual` | | 手动操作模式 |
219
- | `--interactive` | | 交互式引导 |
220
-
221
- ### `smart-test config`
222
-
223
- 查看当前配置。
224
-
225
- ```bash
226
- smart-test config
227
- ```
228
-
229
- ### 全局选项
230
-
231
- | 选项 | 简写 | 说明 |
232
- | ----------- | ---- | -------------------- |
233
- | `--version` | `-V` | 显示版本号 |
234
- | `--verbose` | `-v` | 详细输出(调试模式) |
235
- | `--help` | `-h` | 显示帮助信息 |
236
-
237
- ## 📖 编程 API 文档
81
+ ## 📖 API 文档
238
82
 
239
83
  ### `configure(config)`
240
84
 
@@ -247,6 +91,8 @@ configure({
247
91
  apiKey: 'sk-xxx', // AI API 密钥
248
92
  baseURL: 'https://...', // AI 服务地址(可选)
249
93
  model: 'qwen3-vl-plus', // AI 模型(可选)
94
+ screenshotDir: './screenshots', // 截图保存目录(可选)
95
+ saveScreenshots: true, // 是否保存截图(可选)
250
96
  timeout: 30000, // 超时时间(可选)
251
97
  });
252
98
  ```
@@ -335,48 +181,26 @@ test.describe('商品页面测试', () => {
335
181
  });
336
182
  ```
337
183
 
338
- ## 🔧 配置文件
339
-
340
- ### `.smarttestrc.json`
341
-
342
- 使用 `smart-test init` 命令生成的配置文件:
343
-
344
- ```json
345
- {
346
- "version": "1.0.0",
347
- "ai": {
348
- "model": "qwen3-vl-plus",
349
- "apiKey": "${AI_API_KEY}",
350
- "baseURL": "https://dashscope.aliyuncs.com/compatible-mode/v1",
351
- "timeout": 30000
352
- },
353
- "output": {
354
- "testsDir": "./tests/e2e",
355
- "helpersDir": "./tests/helpers",
356
- "naming": "kebab-case"
357
- },
358
- "templates": {
359
- "mock": "default",
360
- "test": "default"
361
- },
362
- "playwright": {
363
- "baseURL": "http://localhost:8080",
364
- "viewport": {
365
- "width": 375,
366
- "height": 667
367
- },
368
- "browser": "chromium"
184
+ ### 批量检查多个元素
185
+
186
+ ```typescript
187
+ test('检查多个区域', async ({ page }) => {
188
+ const checks = [
189
+ { selector: '.header', expected: '顶部导航栏应显示 logo 和菜单' },
190
+ { selector: '.main-content', expected: '主内容区应显示文章列表' },
191
+ { selector: '.sidebar', expected: '侧边栏应显示热门标签' },
192
+ ];
193
+
194
+ for (const check of checks) {
195
+ const element = await page.locator(check.selector);
196
+ const screenshot = await element.screenshot();
197
+
198
+ // 这里可以扩展为单独检查某个元素的功能
199
+ // 当前版本检查整页,后续可以增强
369
200
  }
370
- }
201
+ });
371
202
  ```
372
203
 
373
- ### 支持的配置格式
374
-
375
- - `.smarttestrc.json`
376
- - `.smarttestrc.js`
377
- - `smarttest.config.js`
378
- - `package.json` 中的 `smarttest` 字段
379
-
380
204
  ## 🔧 高级配置
381
205
 
382
206
  ### 支持多种 AI 模型
@@ -408,8 +232,6 @@ configure({
408
232
  // 单次调用自定义
409
233
  const result = await aiReviewScreenshot(page, {
410
234
  expected: '...',
411
- screenshotPrefix: 'my-feature',
412
- screenshotDir: './feature-screenshots',
413
235
  });
414
236
  ```
415
237
 
@@ -437,17 +259,9 @@ A: 理论上支持所有兼容 OpenAI Chat Completions API 的视觉模型,包
437
259
  - OpenAI GPT-4 Vision
438
260
  - 其他兼容的模型服务
439
261
 
440
- ### Q: CLI 生成的测试代码需要手动修改吗?
441
-
442
- A: 生成的代码是可以直接运行的,但建议根据实际需求进行调整。AI 会尽量生成合理的测试用例,但可能无法覆盖所有业务场景。
443
-
444
- ### Q: 录制模式如何处理需要点击才能触发的接口?
445
-
446
- A: 录制模式支持三种方式:
262
+ ### Q: 截图保存在哪里?
447
263
 
448
- 1. **手动操作**:`--manual` 参数,用户手动操作浏览器
449
- 2. **交互式引导**:`--interactive` 参数,AI 引导用户操作
450
- 3. **脚本引导**:`--actions` 参数,提供操作脚本自动执行
264
+ A: 默认保存在 `./test-results/ai-screenshots/` 目录,可以通过 `screenshotDir` 配置修改。
451
265
 
452
266
  ### Q: 如何查看 AI 的原始响应?
453
267
 
@@ -458,55 +272,6 @@ const result = await aiReviewScreenshot(page, '...');
458
272
  console.log('AI 原始响应:', result.rawResponse);
459
273
  ```
460
274
 
461
- ### Q: 生成的代码文件如何组织?
462
-
463
- A: 默认按页面分组:
464
-
465
- - `tests/helpers/mock-{页面名}.ts` - Mock 数据
466
- - `tests/e2e/{页面名}.spec.ts` - 测试用例
467
-
468
- 可以通过 `--output` 参数自定义输出目录。
469
-
470
- ## 🗺️ 开发路线图
471
-
472
- ### ✅ 已完成
473
-
474
- - [x] AI 视觉检查核心功能
475
- - [x] CLI 基础架构
476
- - [x] 配置系统
477
- - [x] 交互式初始化
478
-
479
- ### 🚧 开发中
480
-
481
- - [ ] 录制模式(Phase 2)
482
- - [ ] 网络请求录制
483
- - [ ] HAR 文件解析
484
- - [ ] AI 生成 Mock 代码
485
- - [ ] 交互操作录制
486
-
487
- ### 📅 计划中
488
-
489
- - [ ] 代码分析模式(Phase 3)
490
- - [ ] TypeScript AST 解析
491
- - [ ] API 调用提取
492
- - [ ] 类型定义分析
493
-
494
- - [ ] 描述生成模式(Phase 4)
495
- - [ ] 自然语言理解
496
- - [ ] 交互式问答
497
- - [ ] 代码生成
498
-
499
- - [ ] 增强功能(Phase 5+)
500
- - [ ] 增量更新
501
- - [ ] 自定义模板
502
- - [ ] 测试覆盖率分析
503
- - [ ] VS Code 插件
504
-
505
- ## 📄 文档
506
-
507
- - [CLI 设计文档](./docs/CLI_DESIGN.md) - 完整的 CLI 工具设计方案
508
- - [使用示例](./examples/) - 更多使用示例
509
-
510
275
  ## 📝 License
511
276
 
512
277
  MIT
@@ -518,7 +283,3 @@ MIT
518
283
  ## 📮 联系方式
519
284
 
520
285
  如有问题,请在 [GitHub Issues](https://github.com/snowmountain-top/be-link/issues) 中提出。
521
-
522
- ---
523
-
524
- **版本**:v1.0.0 | **最后更新**:2025-12-30
@@ -1 +1 @@
1
- {"version":3,"file":"ai-assistant.d.ts","sourceRoot":"","sources":["../../src/core/ai-assistant.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAkB,MAAM,SAAS,CAAC;AAI7E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAgE7G"}
1
+ {"version":3,"file":"ai-assistant.d.ts","sourceRoot":"","sources":["../../src/core/ai-assistant.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAkB,MAAM,SAAS,CAAC;AAI7E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA2E7G"}
@@ -11,6 +11,7 @@ import type { AiVisionConfig } from './types';
11
11
  * configure({
12
12
  * apiKey: process.env.AI_API_KEY,
13
13
  * model: 'qwen3-vl-plus',
14
+ * screenshotDir: './screenshots',
14
15
  * });
15
16
  * ```
16
17
  */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAiB9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,QAAQ,CAAC,cAAc,CAAC,CAEpD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,WAAW,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,CAK/F"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAmB9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,QAAQ,CAAC,cAAc,CAAC,CAEpD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,WAAW,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,CAK/F"}
@@ -16,6 +16,16 @@ export interface AiVisionConfig {
16
16
  * @default 'qwen3-vl-plus'
17
17
  */
18
18
  model?: string;
19
+ /**
20
+ * 截图保存目录
21
+ * @default './test-results/ai-screenshots'
22
+ */
23
+ screenshotDir?: string;
24
+ /**
25
+ * 是否保存截图到文件
26
+ * @default true
27
+ */
28
+ saveScreenshots?: boolean;
19
29
  /**
20
30
  * AI 请求超时时间(毫秒)
21
31
  * @default 30000
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,EAAE,EAAE,OAAO,CAAC;IAEZ;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,cAAc,CAAC;IAC7D;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,EAAE,EAAE,OAAO,CAAC;IAEZ;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,cAAc,CAAC;IAC7D;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}
package/dist/index.esm.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { OpenAI } from 'openai';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
2
4
 
3
5
  /**
4
6
  * 默认配置
@@ -7,6 +9,8 @@ const DEFAULT_CONFIG = {
7
9
  apiKey: '',
8
10
  baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
9
11
  model: 'qwen3-vl-plus',
12
+ screenshotDir: './test-results/ai-screenshots',
13
+ saveScreenshots: true,
10
14
  timeout: 30000,
11
15
  };
12
16
  /**
@@ -25,6 +29,7 @@ let globalConfig = { ...DEFAULT_CONFIG };
25
29
  * configure({
26
30
  * apiKey: process.env.AI_API_KEY,
27
31
  * model: 'qwen3-vl-plus',
32
+ * screenshotDir: './screenshots',
28
33
  * });
29
34
  * ```
30
35
  */
@@ -61,6 +66,25 @@ function mergeConfig(localConfig = {}) {
61
66
  };
62
67
  }
63
68
 
69
+ /**
70
+ * 保存截图到文件
71
+ *
72
+ * @param screenshot - 截图 Buffer
73
+ * @param dir - 保存目录
74
+ * @param prefix - 文件名前缀
75
+ * @returns 截图文件的绝对路径
76
+ */
77
+ async function saveScreenshot(screenshot, dir, prefix = 'ai-review') {
78
+ // 确保目录存在
79
+ await fs.promises.mkdir(dir, { recursive: true });
80
+ // 生成文件名(使用时间戳避免冲突)
81
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
82
+ const filename = `${prefix}-${timestamp}.png`;
83
+ const screenshotPath = path.resolve(dir, filename);
84
+ // 写入文件
85
+ await fs.promises.writeFile(screenshotPath, screenshot);
86
+ return screenshotPath;
87
+ }
64
88
  /**
65
89
  * 将截图转换为 base64 编码
66
90
  *
@@ -114,6 +138,12 @@ async function aiReviewScreenshot(page, options) {
114
138
  const screenshot = await page.screenshot({
115
139
  fullPage: opts.fullPage !== false,
116
140
  });
141
+ // 保存截图(如果启用)
142
+ let screenshotPath;
143
+ if (config.saveScreenshots) {
144
+ screenshotPath = await saveScreenshot(screenshot, config.screenshotDir);
145
+ console.log(`[smart-test] 截图已保存: ${screenshotPath}`);
146
+ }
117
147
  // 构建 AI 请求
118
148
  const prompt = buildPrompt(opts.expected);
119
149
  const openai = new OpenAI({
@@ -144,15 +174,18 @@ async function aiReviewScreenshot(page, options) {
144
174
  // 解析 AI 响应
145
175
  const content = completion?.choices[0]?.message?.content || '';
146
176
  const result = parseAiResponse(content);
147
- console.log('[smart-test] AI 检查结果:', result);
148
- return { ...result, rawResponse: content };
177
+ return {
178
+ ...result,
179
+ screenshotPath,
180
+ rawResponse: content,
181
+ };
149
182
  }
150
183
  catch (error) {
151
184
  console.error('[smart-test] AI 检查失败:', error);
152
185
  return {
153
186
  ok: true,
154
187
  skipped: true,
155
- reason: `[smart-test] AI 检查失败: ${error instanceof Error ? error.message : String(error)}`,
188
+ reason: `AI 检查失败: ${error instanceof Error ? error.message : String(error)}`,
156
189
  };
157
190
  }
158
191
  }
package/dist/index.js CHANGED
@@ -1,6 +1,28 @@
1
1
  'use strict';
2
2
 
3
3
  var openai = require('openai');
4
+ var fs = require('fs');
5
+ var path = require('path');
6
+
7
+ function _interopNamespaceDefault(e) {
8
+ var n = Object.create(null);
9
+ if (e) {
10
+ Object.keys(e).forEach(function (k) {
11
+ if (k !== 'default') {
12
+ var d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: function () { return e[k]; }
16
+ });
17
+ }
18
+ });
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+
24
+ var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
25
+ var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
4
26
 
5
27
  /**
6
28
  * 默认配置
@@ -9,6 +31,8 @@ const DEFAULT_CONFIG = {
9
31
  apiKey: '',
10
32
  baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
11
33
  model: 'qwen3-vl-plus',
34
+ screenshotDir: './test-results/ai-screenshots',
35
+ saveScreenshots: true,
12
36
  timeout: 30000,
13
37
  };
14
38
  /**
@@ -27,6 +51,7 @@ let globalConfig = { ...DEFAULT_CONFIG };
27
51
  * configure({
28
52
  * apiKey: process.env.AI_API_KEY,
29
53
  * model: 'qwen3-vl-plus',
54
+ * screenshotDir: './screenshots',
30
55
  * });
31
56
  * ```
32
57
  */
@@ -63,6 +88,25 @@ function mergeConfig(localConfig = {}) {
63
88
  };
64
89
  }
65
90
 
91
+ /**
92
+ * 保存截图到文件
93
+ *
94
+ * @param screenshot - 截图 Buffer
95
+ * @param dir - 保存目录
96
+ * @param prefix - 文件名前缀
97
+ * @returns 截图文件的绝对路径
98
+ */
99
+ async function saveScreenshot(screenshot, dir, prefix = 'ai-review') {
100
+ // 确保目录存在
101
+ await fs__namespace.promises.mkdir(dir, { recursive: true });
102
+ // 生成文件名(使用时间戳避免冲突)
103
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
104
+ const filename = `${prefix}-${timestamp}.png`;
105
+ const screenshotPath = path__namespace.resolve(dir, filename);
106
+ // 写入文件
107
+ await fs__namespace.promises.writeFile(screenshotPath, screenshot);
108
+ return screenshotPath;
109
+ }
66
110
  /**
67
111
  * 将截图转换为 base64 编码
68
112
  *
@@ -116,6 +160,12 @@ async function aiReviewScreenshot(page, options) {
116
160
  const screenshot = await page.screenshot({
117
161
  fullPage: opts.fullPage !== false,
118
162
  });
163
+ // 保存截图(如果启用)
164
+ let screenshotPath;
165
+ if (config.saveScreenshots) {
166
+ screenshotPath = await saveScreenshot(screenshot, config.screenshotDir);
167
+ console.log(`[smart-test] 截图已保存: ${screenshotPath}`);
168
+ }
119
169
  // 构建 AI 请求
120
170
  const prompt = buildPrompt(opts.expected);
121
171
  const openai$1 = new openai.OpenAI({
@@ -146,15 +196,18 @@ async function aiReviewScreenshot(page, options) {
146
196
  // 解析 AI 响应
147
197
  const content = completion?.choices[0]?.message?.content || '';
148
198
  const result = parseAiResponse(content);
149
- console.log('[smart-test] AI 检查结果:', result);
150
- return { ...result, rawResponse: content };
199
+ return {
200
+ ...result,
201
+ screenshotPath,
202
+ rawResponse: content,
203
+ };
151
204
  }
152
205
  catch (error) {
153
206
  console.error('[smart-test] AI 检查失败:', error);
154
207
  return {
155
208
  ok: true,
156
209
  skipped: true,
157
- reason: `[smart-test] AI 检查失败: ${error instanceof Error ? error.message : String(error)}`,
210
+ reason: `AI 检查失败: ${error instanceof Error ? error.message : String(error)}`,
158
211
  };
159
212
  }
160
213
  }
@@ -1,3 +1,12 @@
1
+ /**
2
+ * 保存截图到文件
3
+ *
4
+ * @param screenshot - 截图 Buffer
5
+ * @param dir - 保存目录
6
+ * @param prefix - 文件名前缀
7
+ * @returns 截图文件的绝对路径
8
+ */
9
+ export declare function saveScreenshot(screenshot: Buffer, dir: string, prefix?: string): Promise<string>;
1
10
  /**
2
11
  * 将截图转换为 base64 编码
3
12
  *
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/utils/screenshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D"}
1
+ {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/utils/screenshot.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAanH;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D"}
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "@be-link/smart-test",
3
- "version": "1.0.1-beta.7",
4
- "type": "module",
3
+ "version": "1.0.1-beta.8",
5
4
  "description": "AI-powered visual testing for Playwright - 基于 AI 视觉模型的 Playwright 测试工具",
6
5
  "homepage": "https://github.com/snowmountain-top/be-link",
7
6
  "author": "shian",
@@ -9,9 +8,6 @@
9
8
  "main": "dist/index.js",
10
9
  "module": "dist/index.esm.js",
11
10
  "types": "dist/index.d.ts",
12
- "bin": {
13
- "smart-test": "./bin/smart-test.js"
14
- },
15
11
  "exports": {
16
12
  ".": {
17
13
  "types": "./dist/index.d.ts",
@@ -23,29 +19,16 @@
23
19
  },
24
20
  "files": [
25
21
  "dist",
26
- "bin",
27
- "templates",
28
22
  "README.md"
29
23
  ],
30
24
  "dependencies": {
31
- "@faker-js/faker": "^10.1.0",
32
- "chalk": "^5.3.0",
33
- "commander": "^12.0.0",
34
- "cosmiconfig": "^9.0.0",
35
- "handlebars": "^4.7.8",
36
- "inquirer": "^9.2.0",
37
- "openai": "^6.15.0",
38
- "ora": "^7.0.0",
39
- "prettier": "^3.0.0",
40
- "typescript": "^5.9.3"
25
+ "openai": "^6.15.0"
41
26
  },
42
27
  "peerDependencies": {
43
28
  "@playwright/test": "^1.40.0"
44
29
  },
45
30
  "devDependencies": {
46
- "@playwright/test": "^1.50.0",
47
- "@types/inquirer": "^9.0.0",
48
- "@types/node": "^20.0.0"
31
+ "@playwright/test": "^1.50.0"
49
32
  },
50
33
  "publishConfig": {
51
34
  "access": "public"