Skip to content

Commit 117796a

Browse files
committed
test(playground): add unit tests for PlaygroundSDK and RemoteExecutionAdapter
1 parent 34b2a7f commit 117796a

File tree

11 files changed

+2378
-2
lines changed

11 files changed

+2378
-2
lines changed

apps/report/src/components/playground.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ export function StandardPlayground({
378378

379379
try {
380380
console.log('destroy agent.page', activeAgent?.page);
381-
await activeAgent?.page?.destroy();
381+
await activeAgent?.page?.destroy?.();
382382
console.log('destroy agent.page done', activeAgent?.page);
383383
} catch (e) {
384384
console.error(e);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"dev": "nx run-many --target=build:watch --exclude=android-playground,chrome-extension,@midscene/report,doc --verbose --parallel=6",
77
"build": "nx run-many --target=build --exclude=doc --verbose",
88
"build:skip-cache": "nx run-many --target=build --exclude=doc --verbose --skip-nx-cache",
9-
"test": "nx run-many --target=test --projects=@midscene/core,@midscene/shared,@midscene/visualizer,@midscene/web,@midscene/cli,@midscene/android --verbose",
9+
"test": "nx run-many --target=test --projects=@midscene/core,@midscene/shared,@midscene/visualizer,@midscene/web,@midscene/cli,@midscene/android,@midscene/playground --verbose",
1010
"test:ai": "nx run-many --target=test:ai --projects=@midscene/core,@midscene/web,@midscene/cli --verbose",
1111
"e2e": "nx run @midscene/web:e2e --verbose --exclude-task-dependencies",
1212
"e2e:cache": "nx run @midscene/web:e2e:cache --verbose --exclude-task-dependencies",

packages/playground/tests/README.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# @midscene/playground Tests
2+
3+
This directory contains the test suite for the `@midscene/playground` package.
4+
5+
## Test Structure
6+
7+
```
8+
tests/
9+
├── unit/ # Unit tests for individual components
10+
│ ├── common.test.ts # Tests for common utilities
11+
│ ├── playground-sdk.test.ts # Tests for PlaygroundSDK
12+
│ ├── base-adapter.test.ts # Tests for BasePlaygroundAdapter
13+
│ ├── local-execution-adapter.test.ts # Tests for LocalExecutionAdapter
14+
│ ├── remote-execution-adapter.test.ts # Tests for RemoteExecutionAdapter
15+
│ └── types.test.ts # Type definition tests
16+
├── integration/ # Integration tests
17+
│ └── playground-integration.test.ts # End-to-end workflow tests
18+
├── setup.ts # Test setup and global mocks
19+
└── README.md # This file
20+
```
21+
22+
## Running Tests
23+
24+
### All Tests
25+
```bash
26+
pnpm test
27+
```
28+
29+
### Watch Mode
30+
```bash
31+
pnpm test:watch
32+
```
33+
34+
### Coverage Report
35+
```bash
36+
pnpm test -- --coverage
37+
```
38+
39+
### Specific Test Files
40+
```bash
41+
# Run only unit tests
42+
pnpm test tests/unit
43+
44+
# Run only integration tests
45+
pnpm test tests/integration
46+
47+
# Run specific test file
48+
pnpm test tests/unit/common.test.ts
49+
```
50+
51+
## Test Categories
52+
53+
### Unit Tests
54+
55+
**common.test.ts**
56+
- Tests core utility functions like `formatErrorMessage`, `validateStructuredParams`, and `executeAction`
57+
- Validates API constants and their relationships
58+
- Tests error handling and parameter validation
59+
60+
**playground-sdk.test.ts**
61+
- Tests the main PlaygroundSDK class
62+
- Validates adapter selection logic
63+
- Tests delegation to appropriate adapters
64+
- Mocks underlying adapters for isolation
65+
66+
**base-adapter.test.ts**
67+
- Tests the abstract BasePlaygroundAdapter class
68+
- Validates common validation logic
69+
- Tests parameter filtering and display content creation
70+
- Tests helper methods and error handling
71+
72+
**local-execution-adapter.test.ts**
73+
- Tests LocalExecutionAdapter specific functionality
74+
- Validates local agent interaction
75+
- Tests progress tracking and task cancellation
76+
- Tests parameter parsing for local execution
77+
78+
**remote-execution-adapter.test.ts**
79+
- Tests RemoteExecutionAdapter specific functionality
80+
- Validates server communication methods
81+
- Tests Android-specific error formatting
82+
- Mocks fetch calls for server interactions
83+
84+
**types.test.ts**
85+
- Validates TypeScript type definitions
86+
- Ensures interfaces accept valid objects
87+
- Tests type compatibility and extensibility
88+
89+
### Integration Tests
90+
91+
**playground-integration.test.ts**
92+
- End-to-end workflow testing
93+
- Tests complete scenarios from SDK creation to action execution
94+
- Validates cross-adapter compatibility
95+
- Tests real-world usage patterns
96+
97+
## Test Setup
98+
99+
The `setup.ts` file provides:
100+
- Global mock configuration
101+
- Console method mocking to reduce test noise
102+
- Browser global mocking for server-side tests
103+
- Automatic cleanup between tests
104+
105+
## Mocking Strategy
106+
107+
- **External Dependencies**: Mocked using Vitest's `vi.mock()`
108+
- **Network Calls**: Mocked using global `fetch` mock
109+
- **Console Output**: Suppressed during tests to reduce noise
110+
- **Browser APIs**: Mocked for Node.js environment compatibility
111+
112+
## Coverage
113+
114+
The test suite aims for high coverage of:
115+
- All exported functions and classes
116+
- Error handling paths
117+
- Edge cases and boundary conditions
118+
- Type safety and interface compliance
119+
120+
Coverage reports are generated in `coverage/` directory when running with `--coverage` flag.
121+
122+
## Writing New Tests
123+
124+
When adding new functionality:
125+
126+
1. **Unit Tests**: Add tests in the appropriate `tests/unit/*.test.ts` file
127+
2. **Integration Tests**: Add end-to-end scenarios to `playground-integration.test.ts`
128+
3. **Type Tests**: Add type validation to `types.test.ts` for new interfaces
129+
4. **Mocking**: Use existing mock patterns and add new mocks as needed
130+
131+
### Test Naming Convention
132+
133+
- Describe blocks: Use present tense describing the component
134+
- Test cases: Use "should" statements describing expected behavior
135+
- Mock functions: Prefix with "mock" for clarity
136+
137+
### Example Test Structure
138+
139+
```typescript
140+
describe('ComponentName', () => {
141+
let component: ComponentType;
142+
143+
beforeEach(() => {
144+
component = new ComponentType();
145+
});
146+
147+
describe('methodName', () => {
148+
it('should handle normal case', () => {
149+
// Test implementation
150+
});
151+
152+
it('should handle error case', () => {
153+
// Error test implementation
154+
});
155+
});
156+
});
157+
```

packages/playground/tests/setup.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { afterEach, beforeEach, vi } from 'vitest';
2+
3+
// Mock console methods to avoid noise in tests
4+
vi.spyOn(console, 'warn').mockImplementation(() => {});
5+
vi.spyOn(console, 'error').mockImplementation(() => {});
6+
7+
// Mock problematic dependencies early
8+
vi.mock('@midscene/shared', () => ({
9+
generateId: vi.fn(() => 'mock-id'),
10+
sleep: vi.fn(() => Promise.resolve()),
11+
}));
12+
13+
vi.mock('@midscene/shared/img/get-photon', () => ({
14+
default: vi.fn(),
15+
}));
16+
17+
vi.mock('@midscene/shared/env', () => ({
18+
overrideAIConfig: vi.fn(),
19+
resetAIConfig: vi.fn(),
20+
}));
21+
22+
vi.mock('@midscene/core/ai-model', () => ({
23+
findAllMidsceneLocatorField: vi.fn(() => ['locateField']),
24+
}));
25+
26+
vi.mock('@midscene/core', () => ({
27+
Puppeteer: vi.fn(),
28+
Playwright: vi.fn(),
29+
createPage: vi.fn(),
30+
}));
31+
32+
vi.mock('express', () => {
33+
const mockExpress = () => ({
34+
use: vi.fn(),
35+
get: vi.fn(),
36+
post: vi.fn(),
37+
listen: vi.fn(),
38+
});
39+
mockExpress.static = vi.fn();
40+
return { default: mockExpress };
41+
});
42+
43+
vi.mock('cors', () => ({
44+
default: vi.fn(() => (req: any, res: any, next: any) => next()),
45+
}));
46+
47+
vi.mock('fs', () => ({
48+
existsSync: vi.fn(() => true),
49+
readFileSync: vi.fn(() => '{}'),
50+
writeFileSync: vi.fn(),
51+
mkdirSync: vi.fn(),
52+
}));
53+
54+
// Global test setup
55+
beforeEach(() => {
56+
// Reset all mocks before each test
57+
vi.clearAllMocks();
58+
});
59+
60+
// Clean up after tests
61+
afterEach(() => {
62+
// Restore console methods
63+
vi.clearAllMocks();
64+
});
65+
66+
// Mock browser globals for tests that need them
67+
Object.defineProperty(global, 'window', {
68+
value: {
69+
location: {
70+
href: 'http://localhost:3000',
71+
},
72+
},
73+
writable: true,
74+
});
75+
76+
Object.defineProperty(global, 'fetch', {
77+
value: vi.fn(),
78+
writable: true,
79+
});

0 commit comments

Comments
 (0)