symref
Version:
Static code checker for AI code agents (Windsurf, Cline, etc.)
118 lines (115 loc) • 4.5 kB
JavaScript
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