mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-28 01:53:53 +08:00
112 lines
3.9 KiB
Markdown
112 lines
3.9 KiB
Markdown
# Unit Tests Guide
|
|||
|
|
|
||
|
|
This directory contains unit tests for the xiaozhi test page modules.
|
||
|
|
|
||
|
|
## Summary
|
||
|
|
|
||
|
|
- **Total Tests:** 13 unit tests
|
||
|
|
- **Test Files:** 2 browser-compatible test files
|
||
|
|
- **Test Runner:** Browser-based (no npm required)
|
||
|
|
- **Coverage:** Microphone detection, HTTP detection, Live2D actions, error handling
|
||
|
|
|
||
|
|
## Test Files
|
||
|
|
|
||
|
|
- `js/core/audio/recorder.test.browser.js` - Browser-compatible tests for microphone availability detection and HTTP non-localhost detection
|
||
|
|
- `js/core/mcp/tools.test.browser.js` - Browser-compatible tests for MCP tools and Live2D action execution
|
||
|
|
|
||
|
|
**Note:** The `.browser.js` versions work without any npm dependencies. They use a simple test framework built into `test-runner.html`.
|
||
|
|
|
||
|
|
## Running Tests
|
||
|
|
|
||
|
|
### Browser-based Test Runner (No npm required!)
|
||
|
|
|
||
|
|
1. Start a local server:
|
||
|
|
```bash
|
||
|
|
cd main/xiaozhi-server/test
|
||
|
|
python -m http.server 8007
|
||
|
|
```
|
||
|
|
|
||
|
|
2. Open `http://localhost:8007/test-runner.html` in your browser
|
||
|
|
|
||
|
|
3. Click "▶ Run All Tests" button
|
||
|
|
|
||
|
|
That's it! No npm, no package.json, no dependencies needed.
|
||
|
|
|
||
|
|
## Test Coverage
|
||
|
|
|
||
|
|
### `recorder.test.browser.js`
|
||
|
|
- ✅ `checkMicrophoneAvailability()` - Returns true when microphone is available
|
||
|
|
- ✅ `checkMicrophoneAvailability()` - Returns false when microphone is not available
|
||
|
|
- ✅ `checkMicrophoneAvailability()` - Returns false when browser doesn't support getUserMedia
|
||
|
|
- ✅ `isHttpNonLocalhost()` - Returns true for HTTP non-localhost access
|
||
|
|
- ✅ `isHttpNonLocalhost()` - Returns false for localhost
|
||
|
|
- ✅ `isHttpNonLocalhost()` - Returns false for 127.0.0.1
|
||
|
|
- ✅ `isHttpNonLocalhost()` - Returns false for private IP addresses
|
||
|
|
- ✅ `isHttpNonLocalhost()` - Returns false for HTTPS protocol
|
||
|
|
|
||
|
|
### `tools.test.browser.js`
|
||
|
|
- ✅ `executeMcpTool('live2d.smile')` - Executes FlickUp action
|
||
|
|
- ✅ `executeMcpTool('live2d.wave')` - Executes Tap action
|
||
|
|
- ✅ `executeMcpTool('live2d.action')` - Executes custom action
|
||
|
|
- ✅ `executeMcpTool()` - Handles missing Live2D manager gracefully
|
||
|
|
- ✅ `executeMcpTool()` - Handles unknown tools gracefully
|
||
|
|
|
||
|
|
## Writing New Tests
|
||
|
|
|
||
|
|
When adding new functionality, create a `.browser.js` test file that follows these patterns:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// your-module.test.browser.js
|
||
|
|
import { yourFunction } from './your-module.js';
|
||
|
|
|
||
|
|
describe('Your Feature', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
// Setup mocks and reset state
|
||
|
|
vi.clearAllMocks();
|
||
|
|
});
|
||
|
|
|
||
|
|
test('should do something', () => {
|
||
|
|
// Arrange
|
||
|
|
const input = 'test';
|
||
|
|
|
||
|
|
// Act
|
||
|
|
const result = yourFunction(input);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
expect(result).toBe('expected');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
## Mocking Guidelines
|
||
|
|
|
||
|
|
- Use `vi.fn()` for function mocks
|
||
|
|
- Use `vi.fn().mockResolvedValue(value)` for async mocks that resolve
|
||
|
|
- Use `vi.fn().mockRejectedValue(error)` for async mocks that reject
|
||
|
|
- Use `vi.clearAllMocks()` in `beforeEach` to reset state
|
||
|
|
- Mock browser APIs (`navigator`, `window.location`, `localStorage`, `fetch`)
|
||
|
|
- Mock DOM elements when needed (`document.getElementById`, etc.)
|
||
|
|
|
||
|
|
## Available Test Functions
|
||
|
|
|
||
|
|
The browser test framework provides:
|
||
|
|
- `describe(name, fn)` - Define a test suite
|
||
|
|
- `test(name, fn)` - Define a test case
|
||
|
|
- `beforeEach(fn)` - Run before each test
|
||
|
|
- `afterEach(fn)` - Run after each test
|
||
|
|
- `expect(actual)` - Assertion object with:
|
||
|
|
- `.toBe(expected)` - Strict equality
|
||
|
|
- `.toHaveBeenCalled()` - Function was called
|
||
|
|
- `.toHaveBeenCalledWith(...args)` - Function was called with specific args
|
||
|
|
- `.toContain(substring)` - String contains substring
|
||
|
|
- `vi.fn(impl?)` - Create a mock function
|
||
|
|
- `vi.clearAllMocks()` - Clear all mocks
|
||
|
|
|
||
|
|
## Notes
|
||
|
|
|
||
|
|
- Tests use ES modules (`import`/`export`)
|
||
|
|
- Tests run directly in the browser (no Node.js needed)
|
||
|
|
- No npm dependencies required - everything is self-contained
|
||
|
|
- The test runner (`test-runner.html`) includes a simple test framework
|
||
|
|
- Tests are automatically loaded when you click "Run All Tests"
|