Files
2026Technology-Competition/tests/customFixEngine.test.ts
T
范智鹏 e9762bfbe1 test: 目录对齐赛道二成果物规范(tests/ 迁移+实验报告+提效测量脚本)
- src/test 迁移至根目录 tests/(16 测试 + fixtures/manual),导入改为 ../src/
- 新增 tsconfig.test.json 独立编译测试;.vscode-test.mjs / package.json / .gitignore 同步
- 新增 tests/test-execution-log.md、tests/test-cases.md(116 用例清单)
- 新增 tests/measure/measure-review-time.mjs + performance-comparison.md(提效测量)
- 重命名 3 个中文报告文件为 demo-*-coverage-report.md
- git rm --cached 解除 vsix 跟踪;README 标注演示视频进行中
2026-08-26 19:17:44 +08:00

101 lines
3.8 KiB
TypeScript

import * as assert from 'assert';
import * as vscode from 'vscode';
import { AIProvider, ChatOptions } from '../src/ai/providers/base';
import { aiFixReviewIssue } from '../src/fix/customFixEngine';
import type { ReviewIssueInput } from '../src/fix/fixPrompt';
class MockReviewFixProvider extends AIProvider {
id = 'mock';
name = 'mock';
constructor(private responses: string[]) { super('key', 'url'); }
async chat(_system: string, _user: string, _options: ChatOptions): Promise<string> {
const next = this.responses.shift();
return next ?? '{}';
}
}
const options: ChatOptions = { model: 'mock', temperature: 0, maxTokens: 100, timeoutMs: 1000 };
function reviewDiag(message = 'bad code', line = 0): ReviewIssueInput {
return { ruleId: 'custom:test-rule', line, message, suggestion: 'use GOOD instead' };
}
suite('Custom FixEngine Tests', () => {
test('aiFixReviewIssue applies AI fix and converges after verify', async () => {
const doc = await vscode.workspace.openTextDocument({
content: 'const x = BAD;\n',
language: 'javascript',
});
const provider = new MockReviewFixProvider([
'{"originalText":"BAD","newText":"GOOD"}',
'{"fixed":true}',
]);
const result = await aiFixReviewIssue(doc, reviewDiag(), 3, provider, options, true);
assert.strictEqual(result.success, true);
assert.strictEqual(result.newText, 'const x = GOOD;\n');
assert.strictEqual(result.appliedFixes.length, 1);
});
test('aiFixReviewIssue returns ai-match-failed when originalText not found', async () => {
const doc = await vscode.workspace.openTextDocument({
content: 'const x = BAD;\n',
language: 'javascript',
});
const provider = new MockReviewFixProvider(['{"originalText":"NOPE","newText":"GOOD"}']);
const result = await aiFixReviewIssue(doc, reviewDiag(), 3, provider, options, true);
assert.strictEqual(result.success, false);
assert.strictEqual(result.message, 'ai-match-failed');
});
test('aiFixReviewIssue retries until verify passes within maxIterations', async () => {
const doc = await vscode.workspace.openTextDocument({
content: 'const x = BAD;\n',
language: 'javascript',
});
const provider = new MockReviewFixProvider([
'{"originalText":"BAD","newText":"BAD2"}',
'{"fixed":false,"reason":"still bad"}',
'{"originalText":"BAD2","newText":"GOOD"}',
'{"fixed":true}',
]);
const result = await aiFixReviewIssue(doc, reviewDiag(), 3, provider, options, true);
assert.strictEqual(result.success, true);
assert.strictEqual(result.appliedFixes.length, 2);
assert.strictEqual(result.newText, 'const x = GOOD;\n');
});
test('aiFixReviewIssue accepts last fix when verify never passes', async () => {
const doc = await vscode.workspace.openTextDocument({
content: 'const x = BAD;\n',
language: 'javascript',
});
const provider = new MockReviewFixProvider([
'{"originalText":"BAD","newText":"GOOD"}',
'{"fixed":false,"reason":"still bad"}',
]);
const result = await aiFixReviewIssue(doc, reviewDiag(), 1, provider, options, true);
assert.strictEqual(result.success, true);
assert.strictEqual(result.newText, 'const x = GOOD;\n');
assert.strictEqual(result.appliedFixes.length, 1);
});
test('aiFixReviewIssue retries empty fix once then fails with ai-no-fix', async () => {
const doc = await vscode.workspace.openTextDocument({
content: 'const x = BAD;\n',
language: 'javascript',
});
const provider = new MockReviewFixProvider([
'{"originalText":"","newText":""}',
'{"originalText":"","newText":""}',
]);
const result = await aiFixReviewIssue(doc, reviewDiag(), 3, provider, options, true);
assert.strictEqual(result.success, false);
assert.strictEqual(result.message, 'ai-no-fix');
});
});