UNPKG

symref

Version:

Static code checker for AI code agents (Windsurf, Cline, etc.)

118 lines (115 loc) 4.5 kB
export class TestPromptGenerator { static generate(context) { return ` 検証対象の呼び出し経路: ${this.formatCallPath(context.callGraph.paths)} シンボル情報: ${this.formatSymbolInfo(context.symbolRefs)} テスト構造: \`\`\`typescript ${this.generateTestStructure(context)} \`\`\` `; } static formatCallPath(paths) { return paths.map(path => { return path.nodes .map((node, index) => { const indent = ' '.repeat(index); const prefix = index === 0 ? '- ' : '└─ '; return `${indent}${prefix}${node.symbol} (${node.location.filePath}:${node.location.line})`; }) .join('\n'); }).join('\n\n'); } static formatSymbolInfo(refs) { const lines = []; if (refs.definition) { lines.push(`- 定義: ${refs.definition.filePath}:${refs.definition.line}`); lines.push(`- 宣言: ${refs.definition.filePath}:${refs.definition.line}`); } else { lines.push('- 定義: 未定義'); lines.push('- 宣言: 未定義'); } lines.push(`- 参照数: ${refs.references.length}`); lines.push(`- 依存: ${refs.dependencies.map(dep => dep.symbol).join(', ') || 'なし'}`); return lines.join('\n'); } static generateTestStructure(context) { const { callGraph, symbolRefs, framework } = context; const firstNode = callGraph.paths[0]?.nodes[0]; const lastNode = callGraph.paths[0]?.nodes.slice(-1)[0]; if (!firstNode || !lastNode) { return '// 呼び出し経路が見つかりませんでした。'; } const testSuiteName = `${firstNode.symbol} から ${lastNode.symbol} への呼び出し経路のテスト`; const beforeEachSetup = this.generateBeforeEachSetup(callGraph.paths[0].nodes, framework); const testCases = this.generateTestCases(callGraph.paths[0].nodes, framework); return `describe('${testSuiteName}', () => { ${beforeEachSetup} ${testCases} });`; } static generateBeforeEachSetup(nodes, framework) { const spySetup = nodes.map(node => { const [className, methodName] = node.symbol.split('.'); if (methodName) { if (framework === 'jest') { return `jest.spyOn(${className}.prototype, '${methodName}');`; } else { return `sinon.spy(${className}.prototype, '${methodName}');`; } } return ''; }).filter(Boolean); return `beforeEach(() => { ${spySetup.join('\n ')} });`; } static generateTestCases(nodes, framework) { const testCases = []; // 呼び出し順序のテスト testCases.push(this.generateCallOrderTest(nodes, framework)); // エラーケースのテスト testCases.push(this.generateErrorTest(nodes, framework)); return testCases.join('\n\n '); } static generateCallOrderTest(nodes, framework) { const assertions = nodes.map((node, index) => { const [className, methodName] = node.symbol.split('.'); if (!methodName) return ''; if (framework === 'jest') { return `expect(${className}.prototype.${methodName}).toHaveBeenCalledTimes(1);`; } else { return `expect(${className}.prototype.${methodName}).to.have.been.calledOnce;`; } }).filter(Boolean); return `test('should call methods in correct order', async () => { // テストの実装 ${assertions.join('\n ')} });`; } static generateErrorTest(nodes, framework) { const lastNode = nodes[nodes.length - 1]; const [className, methodName] = lastNode.symbol.split('.'); if (!methodName) return ''; if (framework === 'jest') { return `test('should handle errors', async () => { ${className}.prototype.${methodName}.mockRejectedValueOnce(new Error('Test error')); // エラーケースのテスト実装 });`; } else { return `test('should handle errors', async () => { ${className}.prototype.${methodName}.rejects(new Error('Test error')); // エラーケースのテスト実装 });`; } } } //# sourceMappingURL=test-prompt-generator.js.map