Files
multi-simadmin/packages/operation-registry/test/runtime-registry.test.ts
T

106 lines
3.8 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {
OperationRegistry,
RuntimeRegistryError,
listOperations,
operationRegistry,
requireExecutableOperation,
requireOperation,
} from '../src/index.ts';
import { upstream58e2204Operations } from '../src/upstream-58e2204.ts';
import { operationAcceptanceOverrides58e2204 } from '../src/acceptance-58e2204.ts';
test('runtime registry projects exactly 117 descriptors in stable operationId order', () => {
const listed = listOperations();
assert.equal(listed.length, 117);
assert.equal(new Set(listed.map((row) => row.operationId)).size, 117);
assert.deepEqual(
listed.map((row) => row.operationId),
listed.map((row) => row.operationId).toSorted(),
);
assert.ok(Object.isFrozen(listed));
assert.ok(listed.every((row) => Object.isFrozen(row)));
const device = requireOperation('getDevice');
assert.equal(device.module, device.upstreamDomain);
assert.equal(device.uiStrategy, operationAcceptanceOverrides58e2204.getDevice.uiStrategy);
assert.equal(device.method, 'GET');
assert.ok(Object.isFrozen(device.sourceEvidence));
assert.strictEqual(requireOperation('getDevice'), device);
assert.strictEqual(operationRegistry.requireOperation('getDevice'), device);
});
test('runtime construction rejects duplicate rows and missing acceptance overrides', () => {
const rows = upstream58e2204Operations as readonly (typeof upstream58e2204Operations)[number][];
assert.throws(
() => new OperationRegistry([...rows, rows[0]], operationAcceptanceOverrides58e2204),
/duplicate operationId: getDevice/,
);
const missing = { ...operationAcceptanceOverrides58e2204 };
delete (missing as Record<string, unknown>).getDevice;
assert.throws(
() => new OperationRegistry(rows, missing),
/missing acceptance override: getDevice/,
);
});
test('requireOperation validates only operationId and fails closed with a stable typed error', () => {
for (const id of [
'',
' ',
'GET /api/device',
'/api/device',
'__proto__',
'constructor',
'get-device',
undefined,
null,
]) {
assert.throws(
() => requireOperation(id as string),
(error: unknown) =>
error instanceof RuntimeRegistryError && error.code === 'UNKNOWN_OPERATION',
String(id),
);
}
assert.throws(
() => requireOperation('getDefinitelyUnknown'),
(error: unknown) => error instanceof RuntimeRegistryError && error.code === 'UNKNOWN_OPERATION',
);
});
test('dedicated auth flows are catalogued but cannot cross executable boundary', () => {
for (const id of [
'postAuthSetup',
'postAuthPassword',
'postAuthSettings',
'postAuthLogin',
'postAuthLogout',
]) {
assert.equal(requireOperation(id).executionPolicy, 'dedicatedFlow');
assert.throws(
() => requireExecutableOperation(id),
(error: unknown) =>
error instanceof RuntimeRegistryError && error.code === 'DEDICATED_FLOW_REQUIRED',
id,
);
}
assert.strictEqual(requireExecutableOperation('getDevice'), requireOperation('getDevice'));
});
test('descriptors are deeply immutable and mutation cannot affect later lookups or frozen source', () => {
const source = upstream58e2204Operations.find((row) => row.operationId === 'getDevice')!;
const originalSourceEvidence = structuredClone(source.sourceEvidence);
const descriptor = requireOperation('getDevice');
assert.ok(Object.isFrozen(descriptor));
assert.ok(Object.isFrozen(descriptor.sourceEvidence));
assert.ok(Object.isFrozen(descriptor.sensitiveFields));
assert.throws(() => ((descriptor as { method: string }).method = 'DELETE'), TypeError);
assert.throws(() => (descriptor.sourceEvidence as string[]).push('mutation'), TypeError);
assert.equal(requireOperation('getDevice').method, 'GET');
assert.deepEqual(source.sourceEvidence, originalSourceEvidence);
});