Files
pig/apps/api/test/facts.test.ts
2026-08-13 01:39:01 -07:00

148 lines
4.2 KiB
TypeScript

import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';
import type { Database } from '@pig/db';
import { facts } from '@pig/db';
import type { Principal } from '../src/lib/auth';
import { executeMutation, MutationError } from '../src/lib/mutation';
import { factDecisionDefinition } from '../src/routes/facts';
const reviewer: Principal = {
userId: '00000000-0000-0000-0000-000000000001',
email: 'research@example.com',
name: 'Research reviewer',
isPlatformAdmin: false,
teams: [{ team: 'research', role: 'admin' }],
via: 'jwt',
scopes: ['read', 'write'],
};
const proposedFact = {
id: '10000000-0000-0000-0000-000000000001',
accountId: '20000000-0000-0000-0000-000000000001',
contactId: null,
field: 'supplierType',
value: 'neocloud',
score: '0.780',
band: 'probable',
status: 'proposed',
evidence: { excerpt: 'Operates dedicated GPU cloud regions.' },
sourceUrl: 'https://example.com/infrastructure',
method: 'web_search',
agentRunId: null,
decidedByUserId: null,
decidedAt: null,
observedAt: new Date('2026-08-12T10:00:00Z'),
supersededAt: null,
createdAt: new Date('2026-08-12T10:00:00Z'),
} as const;
function fakeDatabase(initial: Record<string, unknown>) {
let stored = { ...initial };
const updates: { table: unknown; values: Record<string, unknown> }[] = [];
const activities: Record<string, unknown>[] = [];
const tx = {
select: () => ({
from: () => ({
where: () => ({ limit: async () => [stored] }),
}),
}),
update: (table: unknown) => ({
set: (values: Record<string, unknown>) => ({
where: () => ({
returning: async () => {
updates.push({ table, values });
stored = { ...stored, ...values };
return [stored];
},
}),
}),
}),
insert: () => ({
values: async (row: Record<string, unknown>) => {
activities.push(row);
},
}),
};
const db = {
transaction: async (work: (transaction: unknown) => Promise<unknown>) => work(tx),
} as unknown as Database;
return { db, updates, activities };
}
describe('fact review decisions', () => {
it('approves evidence without applying an arbitrary field to the CRM record', async () => {
const state = fakeDatabase(proposedFact);
const result = await executeMutation(
state.db,
reviewer,
async () => ({ status: 'approved' }),
factDecisionDefinition,
{ id: proposedFact.id },
);
assert.equal(result.fact.status, 'approved');
assert.equal(result.recordUpdated, false);
assert.equal(state.updates.length, 1);
assert.equal(state.updates[0]?.table, facts);
assert.deepEqual(state.updates[0]?.values, {
status: 'approved',
decidedByUserId: reviewer.userId,
decidedAt: state.updates[0]?.values.decidedAt,
});
assert.ok(state.updates[0]?.values.decidedAt instanceof Date);
assert.deepEqual(state.activities[0]?.meta, {
factId: proposedFact.id,
decision: 'approved',
field: proposedFact.field,
recordUpdated: false,
});
});
it('refuses to approve an unsupported claim', async () => {
const state = fakeDatabase({
...proposedFact,
evidence: null,
sourceUrl: null,
});
await assert.rejects(
executeMutation(
state.db,
reviewer,
async () => ({ status: 'approved' }),
factDecisionDefinition,
{ id: proposedFact.id },
),
(error: unknown) =>
error instanceof MutationError && error.code === 'missing_evidence',
);
assert.deepEqual(state.updates, []);
assert.deepEqual(state.activities, []);
});
it('allows an unsupported proposal to be dismissed without manufacturing evidence', async () => {
const state = fakeDatabase({
...proposedFact,
evidence: null,
sourceUrl: null,
});
const result = await executeMutation(
state.db,
reviewer,
async () => ({ status: 'dismissed' }),
factDecisionDefinition,
{ id: proposedFact.id },
);
assert.equal(result.fact.status, 'dismissed');
assert.equal(result.recordUpdated, false);
assert.equal(state.updates.length, 1);
assert.equal(state.updates[0]?.table, facts);
});
});