Repository navigation
Expand file tree
/
Copy pathrun-tests.js
More file actions
executable file
·304 lines (268 loc) · 10.6 KB
/
Copy pathrun-tests.js
File metadata and controls
executable file
·304 lines (268 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#!/usr/bin/env node
/**
* Automated Test Suite for AI Visual Code Review
* Runs critical tests before npm deployment
*/
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
// Test results
const results = {
passed: [],
failed: [],
skipped: []
};
// Helper function to run command and capture output
function runCommand(cmd, expectSuccess = true) {
try {
const output = execSync(cmd, {
encoding: 'utf-8',
cwd: process.cwd()
});
return { success: true, output, error: null };
} catch (error) {
if (!expectSuccess) {
return { success: true, output: error.stdout, error: error.stderr };
}
return { success: false, output: error.stdout, error: error.stderr };
}
}
// Test Categories
console.log('🧪 AI Visual Code Review - Automated Test Suite\n');
console.log('='.repeat(60));
// A1. Basic Commands
console.log('\n📋 A1. Basic Commands');
console.log('-'.repeat(60));
// Test: Help command
console.log('Test: ./bin/ai-review.js quick --help');
let result = runCommand('./bin/ai-review.js quick --help');
if (result.success && result.output.includes('AI Review Export Script')) {
console.log('✅ PASS: Help command works');
results.passed.push('A1-1: Help command');
} else {
console.log('❌ FAIL: Help command');
results.failed.push('A1-1: Help command');
}
// Test: Quick review (if there are staged files)
console.log('\nTest: ./bin/ai-review.js quick');
result = runCommand('git diff --cached --name-only', false);
if (result.output.trim().length > 0) {
result = runCommand('./bin/ai-review.js quick');
if (result.success && fs.existsSync('AI_REVIEW.md')) {
console.log('✅ PASS: Quick review generates AI_REVIEW.md');
results.passed.push('A1-2: Quick review');
} else {
console.log('❌ FAIL: Quick review');
results.failed.push('A1-2: Quick review');
}
} else {
console.log('⏭️ SKIP: Quick review (no staged files)');
results.skipped.push('A1-2: Quick review (no staged files)');
}
// A2. Include Patterns
console.log('\n📋 A2. Include Patterns');
console.log('-'.repeat(60));
// Test: Include *.js files
console.log('Test: ./bin/ai-review.js quick --include "*.js"');
result = runCommand('git diff --cached --name-only', false);
if (result.output.trim().length > 0) {
result = runCommand('./bin/ai-review.js quick --include "*.js"', false);
if (result.success || (result.error && result.error.includes('No files to process'))) {
console.log('✅ PASS: Include *.js pattern works');
results.passed.push('A2-1: Include *.js');
} else {
console.log('❌ FAIL: Include *.js pattern');
results.failed.push('A2-1: Include *.js');
}
} else {
console.log('⏭️ SKIP: Include pattern test (no staged files)');
results.skipped.push('A2-1: Include *.js (no staged files)');
}
// Test: Include scripts/**/*.js
console.log('\nTest: ./bin/ai-review.js quick --include "scripts/**/*.js"');
result = runCommand('git diff --cached --name-only', false);
const hasScriptsJs = result.output.includes('scripts/') && result.output.includes('.js');
if (hasScriptsJs) {
result = runCommand('./bin/ai-review.js quick --include "scripts/**/*.js"');
if (result.success && result.output.includes('Included: 1')) {
console.log('✅ PASS: Include scripts/**/*.js matches correctly');
results.passed.push('A2-2: Include scripts/**/*.js');
} else {
console.log('❌ FAIL: Include scripts/**/*.js');
results.failed.push('A2-2: Include scripts/**/*.js');
}
} else {
console.log('⏭️ SKIP: Include scripts/**/*.js (no matching files)');
results.skipped.push('A2-2: Include scripts/**/*.js (no matching files)');
}
// B1. Pattern Matching
console.log('\n📋 B1. Glob Patterns');
console.log('-'.repeat(60));
// Test pattern matching logic directly
console.log('Test: Pattern matching function');
const exportScript = require('./scripts/export-ai-review.js');
// This test requires examining the matchPattern function
console.log('⏭️ SKIP: Direct pattern matching (requires module exports)');
results.skipped.push('B1: Pattern matching unit test');
// D1. Error Scenarios
console.log('\n📋 D1. Git Repository Errors');
console.log('-'.repeat(60));
// Test: No staged changes error
console.log('Test: Error handling for no staged changes');
const hasStaged = execSync('git diff --cached --name-only', { encoding: 'utf-8' }).trim().length > 0;
if (!hasStaged) {
result = runCommand('./bin/ai-review.js quick', false);
if (result.error && result.error.includes('No staged changes')) {
console.log('✅ PASS: Correct error for no staged changes');
results.passed.push('D1-1: No staged changes error');
} else {
console.log('❌ FAIL: No staged changes error');
results.failed.push('D1-1: No staged changes error');
}
} else {
console.log('⏭️ SKIP: No staged changes test (files are staged)');
results.skipped.push('D1-1: No staged changes test');
}
// H1. Output Validation
console.log('\n📋 H1. AI_REVIEW.md Content Validation');
console.log('-'.repeat(60));
if (fs.existsSync('AI_REVIEW.md')) {
const content = fs.readFileSync('AI_REVIEW.md', 'utf8');
// Test: Header includes timestamp
if (content.includes('# 🔍 Code Review -')) {
console.log('✅ PASS: Header includes timestamp');
results.passed.push('H1-1: Header timestamp');
} else {
console.log('❌ FAIL: Header timestamp missing');
results.failed.push('H1-1: Header timestamp');
}
// Test: Project name present
if (content.includes('**Project:**')) {
console.log('✅ PASS: Project name present');
results.passed.push('H1-2: Project name');
} else {
console.log('❌ FAIL: Project name missing');
results.failed.push('H1-2: Project name');
}
// Test: Change summary present
if (content.includes('## 📊 Change Summary')) {
console.log('✅ PASS: Change summary present');
results.passed.push('H1-3: Change summary');
} else {
console.log('❌ FAIL: Change summary missing');
results.failed.push('H1-3: Change summary');
}
// Test: Diff blocks present (if files were processed)
if (content.includes('```diff') || content.includes('No files to process')) {
console.log('✅ PASS: Diff blocks formatted');
results.passed.push('H1-4: Diff blocks');
} else {
console.log('❌ FAIL: Diff blocks missing');
results.failed.push('H1-4: Diff blocks');
}
// Test: Line numbers present in diff
const hasDiff = content.includes('```diff');
if (hasDiff) {
const diffMatch = content.match(/```diff[\s\S]*?```/);
if (diffMatch && /\d+\s+[+-]/.test(diffMatch[0])) {
console.log('✅ PASS: Line numbers with +/- signs present');
results.passed.push('H1-5: Line numbers format');
} else {
console.log('❌ FAIL: Line numbers format incorrect');
results.failed.push('H1-5: Line numbers format');
}
} else {
console.log('⏭️ SKIP: Line numbers test (no diff blocks)');
results.skipped.push('H1-5: Line numbers test');
}
// Test: Review checklist present
if (content.includes('## 🤖 AI Review Checklist')) {
console.log('✅ PASS: Review checklist present');
results.passed.push('H1-6: Review checklist');
} else {
console.log('❌ FAIL: Review checklist missing');
results.failed.push('H1-6: Review checklist');
}
// Test: Footer with metadata
if (content.includes('*Generated by AI Visual Code Review')) {
console.log('✅ PASS: Footer with metadata present');
results.passed.push('H1-7: Footer metadata');
} else {
console.log('❌ FAIL: Footer metadata missing');
results.failed.push('H1-7: Footer metadata');
}
} else {
console.log('⏭️ SKIP: Output validation (AI_REVIEW.md not found)');
results.skipped.push('H1: Output validation tests');
}
// E1. Integration Testing
console.log('\n📋 E1. CLI to Script Integration');
console.log('-'.repeat(60));
// Test: bin/ai-review.js calls export-ai-review.js
console.log('Test: CLI script integration');
const binContent = fs.readFileSync('./bin/ai-review.js', 'utf8');
if (binContent.includes('export-ai-review.js') && binContent.includes('execSync')) {
console.log('✅ PASS: CLI calls export script correctly');
results.passed.push('E1-1: CLI integration');
} else {
console.log('❌ FAIL: CLI integration issue');
results.failed.push('E1-1: CLI integration');
}
// Test: DiffService integration
console.log('\nTest: DiffService integration');
const exportContent = fs.readFileSync('./scripts/export-ai-review.js', 'utf8');
if (exportContent.includes('DiffService') && exportContent.includes('generateEnhancedDiffMarkdown')) {
console.log('✅ PASS: DiffService integrated correctly');
results.passed.push('E1-2: DiffService integration');
} else {
console.log('❌ FAIL: DiffService integration issue');
results.failed.push('E1-2: DiffService integration');
}
// F1. Performance Testing
console.log('\n📋 F1. Performance Test');
console.log('-'.repeat(60));
console.log('Test: Quick review performance (<5 seconds for current files)');
result = runCommand('git diff --cached --name-only', false);
if (result.output.trim().length > 0) {
const startTime = Date.now();
result = runCommand('./bin/ai-review.js quick', false);
const duration = Date.now() - startTime;
if (duration < 5000) {
console.log(`✅ PASS: Completed in ${duration}ms (<5s)`);
results.passed.push(`F1-1: Performance (${duration}ms)`);
} else {
console.log(`⚠️ WARN: Completed in ${duration}ms (>5s but acceptable)`);
results.passed.push(`F1-1: Performance (${duration}ms - acceptable)`);
}
} else {
console.log('⏭️ SKIP: Performance test (no staged files)');
results.skipped.push('F1-1: Performance test');
}
// Summary
console.log(`\n${ '='.repeat(60)}`);
console.log('📊 TEST RESULTS SUMMARY');
console.log('='.repeat(60));
console.log(`✅ Passed: ${results.passed.length}`);
console.log(`❌ Failed: ${results.failed.length}`);
console.log(`⏭️ Skipped: ${results.skipped.length}`);
console.log(`📈 Total: ${results.passed.length + results.failed.length + results.skipped.length}`);
if (results.passed.length > 0) {
console.log('\n✅ Passed Tests:');
results.passed.forEach(test => console.log(` - ${test}`));
}
if (results.failed.length > 0) {
console.log('\n❌ Failed Tests:');
results.failed.forEach(test => console.log(` - ${test}`));
}
if (results.skipped.length > 0) {
console.log('\n⏭️ Skipped Tests:');
results.skipped.forEach(test => console.log(` - ${test}`));
}
console.log(`\n${ '='.repeat(60)}`);
if (results.failed.length === 0) {
console.log('✅ ALL TESTS PASSED! Ready for deployment.');
process.exit(0);
} else {
console.log('❌ SOME TESTS FAILED! Review failures before deployment.');
process.exit(1);
}