test: stabilize bun coverage reporting

This commit is contained in:
2026-03-27 23:35:59 -07:00
parent 23b2360ac4
commit 9caf25bedb
26 changed files with 732 additions and 99 deletions

View File

@@ -4,7 +4,7 @@ import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { ConfigService, ConfigStartupParseError } from './service';
import { DEFAULT_CONFIG, RUNTIME_OPTION_REGISTRY } from './definitions';
import { DEFAULT_CONFIG, RUNTIME_OPTION_REGISTRY, deepMergeRawConfig } from './definitions';
import { generateConfigTemplate } from './template';
function makeTempDir(): string {
@@ -1032,6 +1032,61 @@ test('reloadConfigStrict parse failure does not mutate raw config or warnings',
assert.deepEqual(service.getWarnings(), beforeWarnings);
});
test('SM-012 config paths do not use JSON serialize-clone helpers', () => {
const definitionsSource = fs.readFileSync(
path.join(process.cwd(), 'src/config/definitions.ts'),
'utf-8',
);
const serviceSource = fs.readFileSync(path.join(process.cwd(), 'src/config/service.ts'), 'utf-8');
assert.equal(definitionsSource.includes('JSON.parse(JSON.stringify('), false);
assert.equal(serviceSource.includes('JSON.parse(JSON.stringify('), false);
});
test('getRawConfig returns a detached clone', () => {
const dir = makeTempDir();
fs.writeFileSync(
path.join(dir, 'config.jsonc'),
`{
"ankiConnect": {
"tags": ["SubMiner"]
}
}`,
'utf-8',
);
const service = new ConfigService(dir);
const raw = service.getRawConfig();
raw.ankiConnect!.tags!.push('mutated');
assert.deepEqual(service.getRawConfig().ankiConnect?.tags, ['SubMiner']);
});
test('deepMergeRawConfig returns a detached merged clone', () => {
const base = {
ankiConnect: {
tags: ['SubMiner'],
behavior: {
autoUpdateNewCards: true,
},
},
};
const merged = deepMergeRawConfig(base, {
ankiConnect: {
behavior: {
autoUpdateNewCards: false,
},
},
});
merged.ankiConnect!.tags!.push('mutated');
merged.ankiConnect!.behavior!.autoUpdateNewCards = true;
assert.deepEqual(base.ankiConnect?.tags, ['SubMiner']);
assert.equal(base.ankiConnect?.behavior?.autoUpdateNewCards, true);
});
test('warning emission order is deterministic across reloads', () => {
const dir = makeTempDir();
const configPath = path.join(dir, 'config.jsonc');

View File

@@ -84,11 +84,11 @@ export const CONFIG_OPTION_REGISTRY = [
export { CONFIG_TEMPLATE_SECTIONS };
export function deepCloneConfig(config: ResolvedConfig): ResolvedConfig {
return JSON.parse(JSON.stringify(config)) as ResolvedConfig;
return structuredClone(config);
}
export function deepMergeRawConfig(base: RawConfig, patch: RawConfig): RawConfig {
const clone = JSON.parse(JSON.stringify(base)) as Record<string, unknown>;
const clone = structuredClone(base) as Record<string, unknown>;
const patchObject = patch as Record<string, unknown>;
const mergeInto = (target: Record<string, unknown>, source: Record<string, unknown>): void => {

View File

@@ -61,7 +61,7 @@ export class ConfigService {
}
getRawConfig(): RawConfig {
return JSON.parse(JSON.stringify(this.rawConfig)) as RawConfig;
return structuredClone(this.rawConfig);
}
getWarnings(): ConfigValidationWarning[] {