mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-14 05:37:40 +02:00
87 lines
3.7 KiB
TypeScript
87 lines
3.7 KiB
TypeScript
// Run: npx tsx --test frontend/src/toolui/parseLeniently.test.ts
|
|
// Every case here is a payload shape a real agent emitted (Eric's 2026-08-09 console capture):
|
|
// widgets users should see were quietly falling back to classic rendering.
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { parseLeniently } from './parseLeniently.ts';
|
|
import { SerializableStatsDisplaySchema } from './components/stats-display/schema.ts';
|
|
import { SerializableProgressTrackerSchema } from './components/progress-tracker/schema.ts';
|
|
import { SerializableDataTableSchema } from './components/data-table/schema.ts';
|
|
|
|
test('stats-display: missing key and stringy diff.value repair to a valid payload', () => {
|
|
const gate = parseLeniently(SerializableStatsDisplaySchema, {
|
|
id: 'revenue-stats',
|
|
stats: [
|
|
{ label: 'Revenue', value: 1204, diff: { value: '+12%' } },
|
|
{ label: 'Churn', value: '2.1%', diff: '-0.4' },
|
|
],
|
|
});
|
|
assert.equal(gate.state, 'ok');
|
|
const stats = (gate as { parsed: { stats: Array<Record<string, unknown>> } }).parsed.stats;
|
|
assert.equal(stats[0].key, 'revenue');
|
|
assert.deepEqual(stats[0].diff, { value: 12 });
|
|
assert.deepEqual(stats[1].diff, { value: -0.4 });
|
|
});
|
|
|
|
test('progress-tracker: missing step ids, duplicate labels, underscore statuses all repair', () => {
|
|
const gate = parseLeniently(SerializableProgressTrackerSchema, {
|
|
id: 'deploy-progress',
|
|
steps: [
|
|
{ label: 'Build', status: 'completed' },
|
|
{ label: 'Test', status: 'in_progress' },
|
|
{ label: 'Test', status: 'pending' },
|
|
],
|
|
});
|
|
assert.equal(gate.state, 'ok');
|
|
const steps = (gate as { parsed: { steps: Array<Record<string, unknown>> } }).parsed.steps;
|
|
assert.deepEqual(steps.map((s) => s.status), ['completed', 'in-progress', 'pending']);
|
|
assert.equal(new Set(steps.map((s) => s.id)).size, 3);
|
|
});
|
|
|
|
test('extra invented top-level keys AND repairable steps in the same payload still pass', () => {
|
|
const gate = parseLeniently(SerializableProgressTrackerSchema, {
|
|
id: 'combo',
|
|
caption: 'invented key the schema rejects',
|
|
steps: [{ label: 'Only step', status: 'done' }],
|
|
});
|
|
assert.equal(gate.state, 'ok');
|
|
});
|
|
|
|
test('data-table: a non-ISO receipt.at coerces to ISO; an unparseable one costs only the receipt', () => {
|
|
const base = {
|
|
id: 'orders',
|
|
columns: [{ key: 'name', label: 'Name' }],
|
|
data: [{ name: 'Widget' }],
|
|
};
|
|
const coerced = parseLeniently(SerializableDataTableSchema, {
|
|
...base,
|
|
receipt: { outcome: 'confirmed', summary: 'ok', at: '2026-08-08 14:30' },
|
|
});
|
|
assert.equal(coerced.state, 'ok');
|
|
const rec = (coerced as { parsed: { receipt: { at: string; outcome: string } } }).parsed.receipt;
|
|
assert.ok(rec.at.endsWith('Z') && !Number.isNaN(Date.parse(rec.at)));
|
|
assert.equal(rec.outcome, 'success');
|
|
const dropped = parseLeniently(SerializableDataTableSchema, {
|
|
...base,
|
|
receipt: { outcome: 'confirmed', summary: 'ok', at: 'yesterday-ish' },
|
|
});
|
|
assert.equal(dropped.state, 'ok');
|
|
assert.equal((dropped as { parsed: Record<string, unknown> }).parsed.receipt, undefined);
|
|
});
|
|
|
|
test('a valid payload passes through byte-identical, no repair applied', () => {
|
|
const payload = {
|
|
id: 'clean',
|
|
stats: [{ key: 'a', label: 'A', value: 1, diff: { value: 2 } }],
|
|
};
|
|
const gate = parseLeniently(SerializableStatsDisplaySchema, payload);
|
|
assert.equal(gate.state, 'ok');
|
|
assert.deepEqual((gate as { parsed: Record<string, unknown> }).parsed.stats, payload.stats);
|
|
});
|
|
|
|
test('a genuinely wrong shape still fails loudly with a readable problem', () => {
|
|
const gate = parseLeniently(SerializableStatsDisplaySchema, { id: 'nope', stats: [] });
|
|
assert.equal(gate.state, 'bad');
|
|
assert.ok((gate as { problem: string }).problem.length > 0);
|
|
});
|