mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-30 18:12:08 -07:00
test: stabilize bun coverage reporting
This commit is contained in:
@@ -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');
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -61,7 +61,7 @@ export class ConfigService {
|
||||
}
|
||||
|
||||
getRawConfig(): RawConfig {
|
||||
return JSON.parse(JSON.stringify(this.rawConfig)) as RawConfig;
|
||||
return structuredClone(this.rawConfig);
|
||||
}
|
||||
|
||||
getWarnings(): ConfigValidationWarning[] {
|
||||
|
||||
Reference in New Issue
Block a user