test-scaffolding-fixes.js
1 /** 2 * Quick unit tests for scaffolding fixes 3 * Tests the new methods without database dependencies 4 */ 5 6 import { test, describe } from 'node:test'; 7 import assert from 'node:assert'; 8 import { TriageAgent } from '../src/agents/triage.js'; 9 import { QAAgent } from '../src/agents/qa.js'; 10 11 describe('Scaffolding Fixes - Triage Agent', () => { 12 const agent = new TriageAgent(); 13 14 describe('calculatePriority', () => { 15 test('assigns highest priority to critical errors', () => { 16 const task = { 17 id: 1, 18 created_at: new Date(Date.now() - 48 * 60 * 60 * 1000).toISOString(), 19 }; 20 21 const context = { 22 frequency: 150, 23 severity: 'critical', 24 stage: 'scoring', 25 error_type: 'database_connection', 26 }; 27 28 const priority = agent.calculatePriority(task, context); 29 assert.strictEqual(priority, 1); 30 }); 31 32 test('assigns medium priority to low-frequency errors', () => { 33 const task = { 34 id: 1, 35 created_at: new Date().toISOString(), 36 }; 37 38 const context = { 39 frequency: 1, 40 severity: 'low', 41 stage: 'outreach', 42 }; 43 44 const priority = agent.calculatePriority(task, context); 45 assert.strictEqual(priority, 5); 46 }); 47 48 test('clamps priority to 1-10 range', () => { 49 const task = { 50 id: 1, 51 created_at: new Date().toISOString(), 52 }; 53 54 const maxContext = { 55 frequency: 200, 56 severity: 'critical', 57 stage: 'scoring', 58 error_type: 'security_breach', 59 }; 60 61 const minContext = {}; 62 63 const maxPriority = agent.calculatePriority(task, maxContext); 64 const minPriority = agent.calculatePriority(task, minContext); 65 66 assert.ok(maxPriority >= 1 && maxPriority <= 10); 67 assert.ok(minPriority >= 1 && minPriority <= 10); 68 }); 69 }); 70 71 describe('calculateSimilarity', () => { 72 test('returns 1.0 for identical strings', () => { 73 const error = 'TypeError: Cannot read property length'; 74 const similarity = agent.calculateSimilarity(error, error); 75 assert.strictEqual(similarity, 1.0); 76 }); 77 78 test('returns 0 for empty strings', () => { 79 assert.strictEqual(agent.calculateSimilarity('', 'error'), 0); 80 assert.strictEqual(agent.calculateSimilarity('error', ''), 0); 81 }); 82 83 test('returns 1 for two empty strings', () => { 84 assert.strictEqual(agent.calculateSimilarity('', ''), 1); 85 }); 86 87 test('returns high similarity for similar errors', () => { 88 const error1 = 'database connection timeout'; 89 const error2 = 'database connection failed'; 90 91 const similarity = agent.calculateSimilarity(error1, error2); 92 assert.ok(similarity > 0.6); 93 }); 94 95 test('returns low similarity for different errors', () => { 96 const error1 = 'TypeError: Cannot read property'; 97 const error2 = 'ReferenceError: fetch is not defined'; 98 99 const similarity = agent.calculateSimilarity(error1, error2); 100 assert.ok(similarity < 0.5); 101 }); 102 }); 103 }); 104 105 describe('Scaffolding Fixes - QA Agent', () => { 106 const agent = new QAAgent(); 107 108 describe('addMissingImport', () => { 109 test('adds node:test import for test identifier', () => { 110 const code = `test('my test', async (t) => {\n // test code\n});`; 111 const result = agent.addMissingImport(code, 'test'); 112 113 assert.ok(result.includes("import { test } from 'node:test';")); 114 assert.ok(result.includes("test('my test'")); 115 }); 116 117 test('adds node:assert default import', () => { 118 const code = `test('my test', () => {\n // use assert\n});`; 119 const result = agent.addMissingImport(code, 'assert'); 120 121 assert.ok(result.includes("import assert from 'node:assert';")); 122 assert.ok(!result.includes('{ assert }')); // Default import, not named 123 }); 124 125 test('adds to existing import', () => { 126 const code = `import { test } from 'node:test';\n\ntest('my test', () => {});`; 127 const result = agent.addMissingImport(code, 'describe'); 128 129 assert.ok(result.includes('test, describe')); 130 assert.strictEqual(result.match(/import.*from 'node:test'/g).length, 1); 131 }); 132 133 test('returns unchanged if already imported', () => { 134 const code = `import { test } from 'node:test';\n\ntest('my test', () => {});`; 135 const result = agent.addMissingImport(code, 'test'); 136 137 assert.strictEqual(result, code); 138 }); 139 140 test('detects CommonJS style', () => { 141 const code = `const test = require('node:test');\ntest('my test', () => {});`; 142 const result = agent.addMissingImport(code, 'assert'); 143 144 assert.ok(result.includes('require')); 145 assert.ok(!result.includes('import')); 146 }); 147 148 test('adds comment for unknown identifiers', () => { 149 const code = `test('my test', () => {});`; 150 const result = agent.addMissingImport(code, 'unknownIdentifier'); 151 152 assert.ok(result.includes('// TODO: Add import for unknownIdentifier (unknown module)')); 153 }); 154 155 test('handles fs/promises imports', () => { 156 const code = `test('my test', async () => {});`; 157 const result = agent.addMissingImport(code, 'readFile'); 158 159 assert.ok(result.includes("import { readFile } from 'fs/promises';")); 160 }); 161 162 test('handles path imports', () => { 163 const code = `test('my test', () => {});`; 164 const result = agent.addMissingImport(code, 'join'); 165 166 assert.ok(result.includes("import { join } from 'path';")); 167 }); 168 169 test('handles better-sqlite3 default import', () => { 170 const code = `test('my test', () => {});`; 171 const result = agent.addMissingImport(code, 'Database'); 172 173 assert.ok(result.includes("import Database from 'better-sqlite3';")); 174 assert.ok(!result.includes('{ Database }')); 175 }); 176 }); 177 });