feat(frontend): add computeNumericSeries helper

This commit is contained in:
Experiments DB Dev
2026-05-01 07:51:22 -04:00
parent 0b83795665
commit b9b8a4ef1d
2 changed files with 86 additions and 0 deletions
+53
View File
@@ -4,6 +4,7 @@ import {
getUniqueNoteValues,
runAnalysis,
extractNumber,
computeNumericSeries,
} from '../src/lib/csvAnalysis';
// ── Fixtures ───────────────────────────────────────────────────────────────────
@@ -306,3 +307,55 @@ describe('extractNumber', () => {
expect(extractNumber(undefined)).toBeNull();
});
});
describe('computeNumericSeries', () => {
const rows = [
{ frame: '1', timestamp: '0.0', note: 'L25' },
{ frame: '3', timestamp: '2.0', note: 'L30.5' },
{ frame: '2', timestamp: '1.0', note: 'L40' },
{ frame: '4', timestamp: '3.0', note: 'F' },
{ frame: '5', timestamp: '4.0', note: 'abc' }, // bucket-member but no number
{ frame: 'x', timestamp: '5.0', note: 'L99' }, // bad x
{ frame: '6', timestamp: '6.0', note: '' }, // not in bucket
];
const bucket = { name: 'Lick latency', type: 'numerical', notes: ['L25', 'L30.5', 'L40', 'abc', 'L99'] };
test('returns sorted points with average and counts', () => {
const out = computeNumericSeries(rows, 'frame', 'note', bucket);
expect(out.points).toEqual([
{ x: 1, value: 25, raw: 'L25' },
{ x: 2, value: 40, raw: 'L40' },
{ x: 3, value: 30.5, raw: 'L30.5' },
]);
expect(out.avg).toBeCloseTo((25 + 40 + 30.5) / 3);
expect(out.skipped).toBe(2); // 'abc' (no number) + bad x
expect(out.total).toBe(5); // bucket-member rows
expect(out.xLabel).toBe('frame');
});
test('falls back to timestamp x-column when frame is empty string', () => {
const out = computeNumericSeries(rows, 'timestamp', 'note', bucket);
expect(out.xLabel).toBe('timestamp');
expect(out.points[0].x).toBe(0);
});
test('returns avg=null and empty points when nothing plottable', () => {
const onlyBad = [
{ frame: '1', note: 'abc' },
];
const b = { name: 'Z', type: 'numerical', notes: ['abc'] };
const out = computeNumericSeries(onlyBad, 'frame', 'note', b);
expect(out.points).toEqual([]);
expect(out.avg).toBeNull();
expect(out.skipped).toBe(1);
expect(out.total).toBe(1);
});
test('returns total=0 when bucket notes match nothing in rows', () => {
const b = { name: 'Empty', type: 'numerical', notes: ['nope'] };
const out = computeNumericSeries(rows, 'frame', 'note', b);
expect(out.total).toBe(0);
expect(out.points).toEqual([]);
expect(out.avg).toBeNull();
});
});