- 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 标注演示视频进行中
116 lines
4.1 KiB
TypeScript
116 lines
4.1 KiB
TypeScript
import * as assert from 'assert';
|
|
import * as vscode from 'vscode';
|
|
import { AIProvider, ChatOptions } from '../src/ai/providers/base';
|
|
import { LinterAdapter, LinterDiagnostic } from '../src/types';
|
|
import { aiFixDiagnostic } from '../src/fix/aiFixEngine';
|
|
|
|
class MockFixProvider 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 ?? '{}';
|
|
}
|
|
}
|
|
|
|
class MockAdapter implements LinterAdapter {
|
|
id = 'mock';
|
|
supportedLanguages = ['javascript'];
|
|
isAvailable(): boolean { return true; }
|
|
async check(document: vscode.TextDocument, _workingDir: string) {
|
|
const text = document.getText();
|
|
const diagnostics: LinterDiagnostic[] = [];
|
|
if (text.includes('BAD')) {
|
|
diagnostics.push({
|
|
severity: 'error',
|
|
ruleId: 'eslint:mock-rule',
|
|
message: 'bad code',
|
|
range: new vscode.Range(0, 0, 0, 3),
|
|
});
|
|
}
|
|
return { diagnostics, status: 'ok' as const };
|
|
}
|
|
}
|
|
|
|
const options: ChatOptions = { model: 'mock', temperature: 0, maxTokens: 100, timeoutMs: 1000 };
|
|
|
|
suite('AI FixEngine Tests', () => {
|
|
test('aiFixDiagnostic applies AI fix and converges', async () => {
|
|
const doc = await vscode.workspace.openTextDocument({
|
|
content: 'const x = BAD;\n',
|
|
language: 'javascript',
|
|
});
|
|
const diag: LinterDiagnostic = {
|
|
severity: 'error',
|
|
ruleId: 'eslint:mock-rule',
|
|
message: 'bad code',
|
|
range: new vscode.Range(0, 8, 0, 11),
|
|
};
|
|
const provider = new MockFixProvider(['{"originalText":"BAD","newText":"GOOD"}']);
|
|
const result = await aiFixDiagnostic(doc, __dirname, new MockAdapter(), diag, 3, provider, options);
|
|
|
|
assert.strictEqual(result.success, true);
|
|
assert.strictEqual(result.appliedFixes.length, 1);
|
|
assert.strictEqual(result.appliedFixes[0].originalText, 'BAD');
|
|
assert.strictEqual(result.appliedFixes[0].newText, 'GOOD');
|
|
});
|
|
|
|
test('aiFixDiagnostic returns ai-match-failed when originalText not found', async () => {
|
|
const doc = await vscode.workspace.openTextDocument({
|
|
content: 'const x = BAD;\n',
|
|
language: 'javascript',
|
|
});
|
|
const diag: LinterDiagnostic = {
|
|
severity: 'error',
|
|
ruleId: 'eslint:mock-rule',
|
|
message: 'bad code',
|
|
range: new vscode.Range(0, 8, 0, 11),
|
|
};
|
|
const provider = new MockFixProvider(['{"originalText":"NOPE","newText":"GOOD"}']);
|
|
const result = await aiFixDiagnostic(doc, __dirname, new MockAdapter(), diag, 3, provider, options);
|
|
|
|
assert.strictEqual(result.success, false);
|
|
assert.strictEqual(result.message, 'ai-match-failed');
|
|
});
|
|
|
|
test('aiFixDiagnostic returns ai-no-fix when AI provides empty fix', async () => {
|
|
const doc = await vscode.workspace.openTextDocument({
|
|
content: 'const x = BAD;\n',
|
|
language: 'javascript',
|
|
});
|
|
const diag: LinterDiagnostic = {
|
|
severity: 'error',
|
|
ruleId: 'eslint:mock-rule',
|
|
message: 'bad code',
|
|
range: new vscode.Range(0, 8, 0, 11),
|
|
};
|
|
const provider = new MockFixProvider(['{"originalText":"","newText":""}']);
|
|
const result = await aiFixDiagnostic(doc, __dirname, new MockAdapter(), diag, 3, provider, options);
|
|
|
|
assert.strictEqual(result.success, false);
|
|
assert.strictEqual(result.message, 'ai-no-fix');
|
|
});
|
|
|
|
test('aiFixDiagnostic retries until issue resolved within maxIterations', async () => {
|
|
const doc = await vscode.workspace.openTextDocument({
|
|
content: 'BAD BAD\n',
|
|
language: 'javascript',
|
|
});
|
|
const diag: LinterDiagnostic = {
|
|
severity: 'error',
|
|
ruleId: 'eslint:mock-rule',
|
|
message: 'bad code',
|
|
range: new vscode.Range(0, 0, 0, 3),
|
|
};
|
|
const provider = new MockFixProvider([
|
|
'{"originalText":"BAD BAD","newText":"BAD GOOD"}',
|
|
'{"originalText":"BAD","newText":"GOOD"}',
|
|
]);
|
|
const result = await aiFixDiagnostic(doc, __dirname, new MockAdapter(), diag, 3, provider, options);
|
|
|
|
assert.strictEqual(result.success, true);
|
|
assert.strictEqual(result.appliedFixes.length, 2);
|
|
});
|
|
});
|