@michelabboud/visual-forge-mcp 0.5.6 → 0.6.0
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.
- package/CHANGELOG.md +814 -0
- package/dist/types/generation.d.ts +7 -1
- package/dist/types/generation.d.ts.map +1 -1
- package/dist/utils/image-optimizer.d.ts +91 -0
- package/dist/utils/image-optimizer.d.ts.map +1 -0
- package/dist/utils/image-optimizer.js +241 -0
- package/dist/utils/image-optimizer.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/workflow/workflow-orchestrator.d.ts.map +1 -1
- package/dist/workflow/workflow-orchestrator.js +34 -1
- package/dist/workflow/workflow-orchestrator.js.map +1 -1
- package/docs/guides/README.md +24 -0
- package/docs/guides/backup-system-flow.md +511 -0
- package/docs/guides/backup-system.md +688 -0
- package/docs/guides/development-testing.md +338 -0
- package/docs/guides/html-support.md +548 -0
- package/docs/guides/image-optimization.md +370 -0
- package/docs/guides/testing.md +279 -0
- package/docs/guides/usage-examples.md +101 -0
- package/docs/guides/vf-workflow.md +112 -0
- package/docs/guides/workflow-with-backups.md +471 -0
- package/package.json +15 -3
- package/dist/.gitkeep +0 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Visual Forge MCP - Testing Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide explains how to write and run tests for Visual Forge MCP.
|
|
6
|
+
|
|
7
|
+
## Test Infrastructure
|
|
8
|
+
|
|
9
|
+
The project uses:
|
|
10
|
+
- **Jest** - Testing framework
|
|
11
|
+
- **ts-jest** - TypeScript support for Jest
|
|
12
|
+
- **ES Modules** - Full ES module support
|
|
13
|
+
|
|
14
|
+
## Running Tests
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Run all tests
|
|
18
|
+
npm test
|
|
19
|
+
|
|
20
|
+
# Run tests in watch mode
|
|
21
|
+
npm run test:watch
|
|
22
|
+
|
|
23
|
+
# Run tests with coverage
|
|
24
|
+
npm test -- --coverage
|
|
25
|
+
|
|
26
|
+
# Run specific test file
|
|
27
|
+
npm test -- provider-factory.test.ts
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Writing Tests
|
|
31
|
+
|
|
32
|
+
### Test Structure
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
|
|
36
|
+
import { YourModule } from '../src/your-module.js';
|
|
37
|
+
|
|
38
|
+
describe('YourModule', () => {
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
// Setup before each test
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
// Cleanup after each test
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('yourMethod()', () => {
|
|
48
|
+
it('should do something specific', () => {
|
|
49
|
+
// Arrange
|
|
50
|
+
const input = 'test';
|
|
51
|
+
|
|
52
|
+
// Act
|
|
53
|
+
const result = yourMethod(input);
|
|
54
|
+
|
|
55
|
+
// Assert
|
|
56
|
+
expect(result).toBe('expected');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Using Test Helpers
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import {
|
|
66
|
+
createMockImageSpec,
|
|
67
|
+
createMockProviderConfig,
|
|
68
|
+
setTestEnv,
|
|
69
|
+
clearTestEnv,
|
|
70
|
+
} from './test/helpers/test-utils.js';
|
|
71
|
+
|
|
72
|
+
// Create test data
|
|
73
|
+
const spec = createMockImageSpec({
|
|
74
|
+
prompt: 'Custom prompt',
|
|
75
|
+
aspectRatio: '16:9',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Set environment variables
|
|
79
|
+
setTestEnv({
|
|
80
|
+
GOOGLE_API_KEY: 'AIza-test-key-1234567890',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Clean up
|
|
84
|
+
clearTestEnv(['GOOGLE_API_KEY']);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Mocking
|
|
88
|
+
|
|
89
|
+
#### Mocking Modules
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
jest.mock('axios');
|
|
93
|
+
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
|
94
|
+
|
|
95
|
+
mockedAxios.post = jest.fn().mockResolvedValue({
|
|
96
|
+
data: { success: true },
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Mock Providers
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { createMockProvider } from './test/helpers/mock-providers.js';
|
|
104
|
+
|
|
105
|
+
const successProvider = createMockProvider('success');
|
|
106
|
+
const failureProvider = createMockProvider('failure');
|
|
107
|
+
const rateLimitedProvider = createMockProvider('rate-limited');
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Best Practices
|
|
111
|
+
|
|
112
|
+
### 1. Test Isolation
|
|
113
|
+
|
|
114
|
+
Each test should be independent:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
beforeEach(() => {
|
|
118
|
+
// Reset state before each test
|
|
119
|
+
jest.clearAllMocks();
|
|
120
|
+
clearTestEnv(['API_KEY']);
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 2. Descriptive Test Names
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// Good
|
|
128
|
+
it('should throw ConfigurationError when API key is missing', () => {});
|
|
129
|
+
|
|
130
|
+
// Bad
|
|
131
|
+
it('should fail', () => {});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 3. AAA Pattern
|
|
135
|
+
|
|
136
|
+
Use Arrange-Act-Assert:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
it('should calculate cost correctly', () => {
|
|
140
|
+
// Arrange
|
|
141
|
+
const spec = createMockImageSpec();
|
|
142
|
+
const provider = createMockProvider();
|
|
143
|
+
|
|
144
|
+
// Act
|
|
145
|
+
const cost = provider.estimateCost(spec);
|
|
146
|
+
|
|
147
|
+
// Assert
|
|
148
|
+
expect(cost).toBe(0.04);
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 4. Test Both Success and Failure Paths
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
describe('generate()', () => {
|
|
156
|
+
it('should successfully generate image', async () => {
|
|
157
|
+
// Test success path
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should handle API errors gracefully', async () => {
|
|
161
|
+
// Test error path
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 5. Mock External Dependencies
|
|
167
|
+
|
|
168
|
+
Always mock:
|
|
169
|
+
- HTTP clients (axios)
|
|
170
|
+
- File system operations (fs/promises)
|
|
171
|
+
- Image processing (sharp)
|
|
172
|
+
- Environment variables
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
jest.mock('fs/promises', () => ({
|
|
176
|
+
writeFile: jest.fn().mockResolvedValue(undefined),
|
|
177
|
+
mkdir: jest.fn().mockResolvedValue(undefined),
|
|
178
|
+
}));
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Common Test Patterns
|
|
182
|
+
|
|
183
|
+
### Testing Async Functions
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
it('should generate image asynchronously', async () => {
|
|
187
|
+
const spec = createMockImageSpec();
|
|
188
|
+
const result = await provider.generate(spec);
|
|
189
|
+
|
|
190
|
+
expect(result).toBeDefined();
|
|
191
|
+
expect(result.filepath).toContain(spec.id);
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Testing Error Handling
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
it('should throw error when provider unavailable', () => {
|
|
199
|
+
const config = createMockProviderConfig({ apiKey: '' });
|
|
200
|
+
const provider = new Provider(config);
|
|
201
|
+
|
|
202
|
+
expect(() => provider.generate(spec)).rejects.toThrow();
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Testing Environment Variables
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
it('should use environment variable for API key', () => {
|
|
210
|
+
setTestEnv({ GOOGLE_API_KEY: 'test-key' });
|
|
211
|
+
|
|
212
|
+
const factory = new ProviderFactory();
|
|
213
|
+
factory.initialize();
|
|
214
|
+
|
|
215
|
+
expect(factory.isProviderAvailable('gemini')).toBe(true);
|
|
216
|
+
|
|
217
|
+
clearTestEnv(['GOOGLE_API_KEY']);
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Coverage Goals
|
|
222
|
+
|
|
223
|
+
Aim for:
|
|
224
|
+
- **Branches**: 60%
|
|
225
|
+
- **Functions**: 60%
|
|
226
|
+
- **Lines**: 60%
|
|
227
|
+
- **Statements**: 60%
|
|
228
|
+
|
|
229
|
+
Critical paths should have higher coverage (80%+):
|
|
230
|
+
- Provider initialization
|
|
231
|
+
- Image generation
|
|
232
|
+
- Error handling
|
|
233
|
+
- State persistence
|
|
234
|
+
|
|
235
|
+
## Debugging Tests
|
|
236
|
+
|
|
237
|
+
### Run Single Test
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npm test -- --testNamePattern="should initialize OpenAI"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Enable Verbose Output
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
npm test -- --verbose
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Debug in VS Code
|
|
250
|
+
|
|
251
|
+
Add to `.vscode/launch.json`:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"type": "node",
|
|
256
|
+
"request": "launch",
|
|
257
|
+
"name": "Jest Debug",
|
|
258
|
+
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
|
259
|
+
"args": ["--runInBand", "--no-cache"],
|
|
260
|
+
"console": "integratedTerminal",
|
|
261
|
+
"internalConsoleOptions": "neverOpen"
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Common Issues
|
|
266
|
+
|
|
267
|
+
### ES Module Issues
|
|
268
|
+
|
|
269
|
+
If you see "Cannot use import statement outside a module":
|
|
270
|
+
|
|
271
|
+
1. Ensure `package.json` has `"type": "module"`
|
|
272
|
+
2. Use `.js` extensions in imports (even for `.ts` files)
|
|
273
|
+
3. Check `jest.config.js` has correct ES module configuration
|
|
274
|
+
|
|
275
|
+
### Type Errors in Tests
|
|
276
|
+
|
|
277
|
+
If TypeScript complains about test types:
|
|
278
|
+
|
|
279
|
+
1. Ensure `@types/jest` is installed
|
|
280
|
+
2. Add `"jest"` to `types` in `tsconfig.json`
|
|
281
|
+
3. Use proper Jest matchers
|
|
282
|
+
|
|
283
|
+
### Mock Not Working
|
|
284
|
+
|
|
285
|
+
If mocks aren't being applied:
|
|
286
|
+
|
|
287
|
+
1. Call `jest.clearAllMocks()` in `beforeEach`
|
|
288
|
+
2. Ensure mock is defined before importing module
|
|
289
|
+
3. Use `jest.resetModules()` if needed
|
|
290
|
+
|
|
291
|
+
## Test Organization
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
test/
|
|
295
|
+
├── helpers/ # Shared test utilities
|
|
296
|
+
│ ├── test-utils.ts
|
|
297
|
+
│ └── mock-providers.ts
|
|
298
|
+
├── providers/ # Provider tests
|
|
299
|
+
│ └── provider-factory.test.ts
|
|
300
|
+
├── state/ # State management tests (planned)
|
|
301
|
+
├── workflow/ # Workflow tests (planned)
|
|
302
|
+
└── README.md # Test documentation
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## CI/CD Integration
|
|
306
|
+
|
|
307
|
+
Tests are designed to run in CI:
|
|
308
|
+
- No external API calls (all mocked)
|
|
309
|
+
- Fast execution (< 10 seconds)
|
|
310
|
+
- Deterministic results
|
|
311
|
+
- No file system dependencies
|
|
312
|
+
|
|
313
|
+
Example GitHub Actions:
|
|
314
|
+
|
|
315
|
+
```yaml
|
|
316
|
+
name: Tests
|
|
317
|
+
on: [push, pull_request]
|
|
318
|
+
jobs:
|
|
319
|
+
test:
|
|
320
|
+
runs-on: ubuntu-latest
|
|
321
|
+
steps:
|
|
322
|
+
- uses: actions/checkout@v3
|
|
323
|
+
- uses: actions/setup-node@v3
|
|
324
|
+
with:
|
|
325
|
+
node-version: '24'
|
|
326
|
+
- run: npm install
|
|
327
|
+
- run: npm test
|
|
328
|
+
- run: npm test -- --coverage
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Next Steps
|
|
332
|
+
|
|
333
|
+
1. Add more provider tests
|
|
334
|
+
2. Add StateManager tests
|
|
335
|
+
3. Add WorkflowOrchestrator tests
|
|
336
|
+
4. Add MarkdownParser tests
|
|
337
|
+
5. Add QualityInspector tests
|
|
338
|
+
6. Increase code coverage to 80%+
|