Add browser-based unit tests for xiaozhi test modules

- Add browser-compatible test files (no npm required)

  - recorder.test.browser.js: 8 tests for microphone and HTTP detection

  - tools.test.browser.js: 5 tests for Live2D actions and error handling

- Add test runner (test-runner.html) with built-in test framework

- Add null safety checks in tools.js for DOM element access

- Add documentation (English and Chinese versions)

  - README_TESTS.md / README_TESTS_CN.md: Complete test guide

  - QUICK_START_TEST.md / QUICK_START_TEST_CN.md: Quick start guides

- Total: 13 unit tests covering microphone detection, HTTP detection, Live2D actions, and error handling
This commit is contained in:
spider-yamet
2026-01-26 10:18:40 -08:00
parent 4f4f8ca54e
commit b7e4408a0f
10 changed files with 1597 additions and 102 deletions
+111
View File
@@ -0,0 +1,111 @@
# 单元测试指南
本目录包含 xiaozhi 测试页面模块的单元测试。
## 摘要
- **测试总数:** 13 个单元测试
- **测试文件:** 2 个浏览器兼容的测试文件
- **测试运行器:** 基于浏览器(无需 npm)
- **测试覆盖:** 麦克风检测、HTTP 检测、Live2D 动作、错误处理
## 测试文件
- `js/core/audio/recorder.test.browser.js` - 浏览器兼容的麦克风可用性检测和 HTTP 非本地访问检测测试
- `js/core/mcp/tools.test.browser.js` - 浏览器兼容的 MCP 工具和 Live2D 动作执行测试
**注意:** `.browser.js` 版本无需任何 npm 依赖。它们使用内置在 `test-runner.html` 中的简单测试框架。
## 运行测试
### 基于浏览器的测试运行器(无需 npm!)
1. 启动本地服务器:
```bash
cd main/xiaozhi-server/test
python -m http.server 8007
```
2. 在浏览器中打开 `http://localhost:8007/test-runner.html`
3. 点击 "▶ Run All Tests"(运行所有测试)按钮
就这么简单!无需 npm,无需 package.json,无需任何依赖。
## 测试覆盖
### `recorder.test.browser.js`
-`checkMicrophoneAvailability()` - 当麦克风可用时返回 true
-`checkMicrophoneAvailability()` - 当麦克风不可用时返回 false
-`checkMicrophoneAvailability()` - 当浏览器不支持 getUserMedia 时返回 false
-`isHttpNonLocalhost()` - 对于 HTTP 非本地访问返回 true
-`isHttpNonLocalhost()` - 对于 localhost 返回 false
-`isHttpNonLocalhost()` - 对于 127.0.0.1 返回 false
-`isHttpNonLocalhost()` - 对于私有 IP 地址返回 false
-`isHttpNonLocalhost()` - 对于 HTTPS 协议返回 false
### `tools.test.browser.js`
-`executeMcpTool('live2d.smile')` - 执行 FlickUp 动作
-`executeMcpTool('live2d.wave')` - 执行 Tap 动作
-`executeMcpTool('live2d.action')` - 执行自定义动作
-`executeMcpTool()` - 优雅处理缺失的 Live2D 管理器
-`executeMcpTool()` - 优雅处理未知工具
## 编写新测试
添加新功能时,创建一个遵循以下模式的 `.browser.js` 测试文件:
```javascript
// your-module.test.browser.js
import { yourFunction } from './your-module.js';
describe('您的功能', () => {
beforeEach(() => {
// 设置模拟并重置状态
vi.clearAllMocks();
});
test('应该执行某些操作', () => {
// 准备
const input = 'test';
// 执行
const result = yourFunction(input);
// 断言
expect(result).toBe('expected');
});
});
```
## 模拟指南
- 使用 `vi.fn()` 创建函数模拟
- 使用 `vi.fn().mockResolvedValue(value)` 创建解析的异步模拟
- 使用 `vi.fn().mockRejectedValue(error)` 创建拒绝的异步模拟
-`beforeEach` 中使用 `vi.clearAllMocks()` 重置状态
- 模拟浏览器 API`navigator``window.location``localStorage``fetch`
- 需要时模拟 DOM 元素(`document.getElementById` 等)
## 可用的测试函数
浏览器测试框架提供:
- `describe(name, fn)` - 定义测试套件
- `test(name, fn)` - 定义测试用例
- `beforeEach(fn)` - 在每个测试之前运行
- `afterEach(fn)` - 在每个测试之后运行
- `expect(actual)` - 断言对象,包含:
- `.toBe(expected)` - 严格相等
- `.toHaveBeenCalled()` - 函数已被调用
- `.toHaveBeenCalledWith(...args)` - 函数已使用特定参数调用
- `.toContain(substring)` - 字符串包含子字符串
- `vi.fn(impl?)` - 创建模拟函数
- `vi.clearAllMocks()` - 清除所有模拟
## 注意事项
- 测试使用 ES 模块(`import`/`export`
- 测试直接在浏览器中运行(无需 Node.js)
- 无需 npm 依赖 - 所有内容都是自包含的
- 测试运行器(`test-runner.html`)包含一个简单的测试框架
- 点击 "Run All Tests"(运行所有测试)时自动加载测试