feat: validate continuity config and extract receipt contract
This commit is contained in:
133
plugins/continuity/test/continuity.config.test.mjs
Normal file
133
plugins/continuity/test/continuity.config.test.mjs
Normal file
@@ -0,0 +1,133 @@
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
import defaultConfig from '../src/config/defaults.mjs';
|
||||
import {
|
||||
normalizeContinuityConfig,
|
||||
validateContinuityConfig,
|
||||
} from '../src/config/schema.mjs';
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(`ok - ${name}`);
|
||||
} catch (error) {
|
||||
console.error(`not ok - ${name}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
test('accepts default config', () => {
|
||||
const result = validateContinuityConfig(defaultConfig);
|
||||
assert.equal(result.ok, true);
|
||||
assert.deepEqual(result.errors, []);
|
||||
assert.deepEqual(result.normalizedConfig, defaultConfig);
|
||||
});
|
||||
|
||||
test('accepts custom receipt directory', () => {
|
||||
const result = validateContinuityConfig({
|
||||
receiptDir: 'tmp/continuity-receipts',
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.normalizedConfig.receiptDir, 'tmp/continuity-receipts');
|
||||
assert.deepEqual(result.errors, []);
|
||||
});
|
||||
|
||||
test('accepts custom legal terminal states list', () => {
|
||||
const result = validateContinuityConfig({
|
||||
legalTerminalStates: ['waiting_user', 'blocked', 'done_elsewhere'],
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.deepEqual(result.normalizedConfig.legalTerminalStates, ['waiting_user', 'blocked', 'done_elsewhere']);
|
||||
});
|
||||
|
||||
test('normalizes missing fields from defaults', () => {
|
||||
const normalized = normalizeContinuityConfig({
|
||||
debug: true,
|
||||
});
|
||||
|
||||
assert.equal(normalized.debug, true);
|
||||
assert.equal(normalized.enabled, defaultConfig.enabled);
|
||||
assert.equal(normalized.receiptDir, defaultConfig.receiptDir);
|
||||
assert.deepEqual(normalized.legalTerminalStates, defaultConfig.legalTerminalStates);
|
||||
assert.notEqual(normalized.legalTerminalStates, defaultConfig.legalTerminalStates);
|
||||
});
|
||||
|
||||
test('rejects non-array legalTerminalStates', () => {
|
||||
const result = validateContinuityConfig({
|
||||
legalTerminalStates: 'waiting_user',
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.errors.join('\n'), /legalTerminalStates/);
|
||||
assert.match(result.errors.join('\n'), /array/i);
|
||||
});
|
||||
|
||||
test('rejects invalid legalTerminalStates entry types', () => {
|
||||
const result = validateContinuityConfig({
|
||||
legalTerminalStates: ['waiting_user', 123],
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.errors.join('\n'), /legalTerminalStates\[1\]/);
|
||||
assert.match(result.errors.join('\n'), /string/i);
|
||||
});
|
||||
|
||||
test('rejects empty receiptDir', () => {
|
||||
const result = validateContinuityConfig({
|
||||
receiptDir: ' ',
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.errors.join('\n'), /receiptDir/);
|
||||
});
|
||||
|
||||
test('rejects malformed adapter.forceRecall shape', () => {
|
||||
const result = validateContinuityConfig({
|
||||
adapter: {
|
||||
forceRecall: false,
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.errors.join('\n'), /adapter\.forceRecall/);
|
||||
});
|
||||
|
||||
test('rejects malformed adapter.forceRecall.enabled type', () => {
|
||||
const result = validateContinuityConfig({
|
||||
adapter: {
|
||||
forceRecall: {
|
||||
enabled: 'yes',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.errors.join('\n'), /adapter\.forceRecall\.enabled/);
|
||||
});
|
||||
|
||||
test('rejects malformed adapter.forceRecall.injectBlockLabel type', () => {
|
||||
const result = validateContinuityConfig({
|
||||
adapter: {
|
||||
forceRecall: {
|
||||
injectBlockLabel: 42,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.errors.join('\n'), /injectBlockLabel/);
|
||||
});
|
||||
|
||||
test('rejects unknown top-level key', () => {
|
||||
const result = validateContinuityConfig({
|
||||
unexpected: true,
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.errors.join('\n'), /unknown/i);
|
||||
assert.match(result.errors.join('\n'), /unexpected/);
|
||||
});
|
||||
|
||||
console.log('continuity.config.test.mjs PASS');
|
||||
Reference in New Issue
Block a user