Files
范智鹏 e469554691 test: 新增 8 个测试文件 63 用例 + 覆盖率设施,行覆盖 42.58%→48.24%
- 新增 jsp-extractor/report/method-extractor/fix-prompt/registry/provider-chat/import-service/yaml-parser 测试
- .vscode-test.mjs 加 srcDir+coverage,package.json 加 test:coverage,产出 tests/coverage/(html)
- 修复 method-extractor java fallback 取错捕获组、mockDocument.getText 忽略 range
- 更新 tests/test-cases.md(24 文件 179 条)与 test-execution-log.md(覆盖率记录)
2026-08-27 22:54:00 +08:00

107 lines
4.3 KiB
TypeScript

import * as assert from 'assert';
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { buildFinalYaml, ImportService, parseImportableYaml } from '../src/rules/import-service';
import type { PreviewDecision, ImportableRule } from '../src/rules/import-types';
function rule(overrides: Partial<ImportableRule>): ImportableRule {
return { id: 'r', severity: 'warning', description: 'd', message: 'm', ...overrides };
}
suite('ImportService Tests', () => {
test('parseImportableYaml handles arrays and quoted ids', () => {
const yaml = [
'- id: no-console',
' severity: warning',
' description: forbid console',
' message: use logger',
' languages: [javascript, typescript]',
'- id: "quoted-id"',
' severity: info',
' description: d',
' message: m',
].join('\n');
const rules = parseImportableYaml(yaml);
assert.strictEqual(rules.length, 2);
assert.deepStrictEqual(rules[0].languages, ['javascript', 'typescript']);
assert.strictEqual(rules[1].id, 'quoted-id');
});
test('parseImportableYaml fills message from description and vice versa', () => {
const rules = parseImportableYaml('- id: a\n severity: error\n description: only-desc\n');
assert.strictEqual(rules[0].message, 'only-desc');
const rules2 = parseImportableYaml('- id: b\n severity: error\n message: only-msg\n');
assert.strictEqual(rules2[0].description, 'only-msg');
});
test('buildFinalYaml uses edited rules when present', () => {
const rules = [rule({ id: 'r1' })];
const edited = [rule({ id: 'r1', severity: 'error', description: 'edited' })];
const decision: PreviewDecision = { keepRule: { r1: true }, confirmed: true, editedRules: edited };
const out = buildFinalYaml('- id: r1\n severity: warning\n description: d\n message: m\n', rules, decision);
assert.match(out, /severity: error/);
assert.match(out, /edited/);
});
test('buildFinalYaml comments exact duplicates and strips duplicate metadata', () => {
const yaml = [
'- id: a',
' severity: warning',
' description: desc a',
' message: msg a',
'- id: b',
' severity: error',
' description: desc b',
' message: msg b',
' duplicateOf: custom/x',
' duplicateLevel: exact',
' duplicateReason: same',
].join('\n');
const rules = parseImportableYaml(yaml);
const decision: PreviewDecision = { keepRule: { a: true, b: false }, confirmed: true };
const out = buildFinalYaml(yaml, rules, decision);
assert.match(out, /- id: a/);
assert.match(out, /# - id: b/);
const dupLines = out.split('\n').filter(l => /duplicateOf:/.test(l));
assert.ok(dupLines.length > 0);
assert.ok(dupLines.every(l => l.trimStart().startsWith('#')), 'duplicate metadata only appears in comments');
});
test('buildFinalYaml keeps all when no overrides', () => {
const yaml = '- id: x\n severity: warning\n description: dx\n message: mx\n';
const rules = parseImportableYaml(yaml);
const decision: PreviewDecision = { keepRule: {}, confirmed: true };
const out = buildFinalYaml(yaml, rules, decision);
assert.match(out, /- id: x/);
assert.ok(!/# - id: x/.test(out));
});
test('applyConversion writes final yaml to nested target path', () => {
const yaml = '- id: k\n severity: warning\n description: dk\n message: mk\n';
const rules = parseImportableYaml(yaml);
const decision: PreviewDecision = { keepRule: { k: true }, confirmed: true };
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'import-svc-'));
const target = path.join(tmp, 'nested', 'custom-rules.yaml');
try {
new ImportService().applyConversion(
{ rules, yamlContent: yaml, sourceFileName: 'a.yaml', exactCount: 0, overlapCount: 0 },
decision,
target,
);
assert.ok(fs.existsSync(target));
assert.match(fs.readFileSync(target, 'utf-8'), /- id: k/);
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
}
});
test('convert throws for unsupported extension', async () => {
const svc = new ImportService();
await assert.rejects(
() => svc.convert('/tmp/foo.xyz', {} as vscode.ExtensionContext),
);
});
});