feat(export): buildSubjectSeriesMatrix — subjects as columns over an X field
This commit is contained in:
@@ -387,3 +387,61 @@ describe('buildSampleIndex', () => {
|
||||
expect(idx.get('a1').get(260).date).toContain('2026-07-03');
|
||||
});
|
||||
});
|
||||
|
||||
import { buildSubjectSeriesMatrix } from '../src/lib/dataExport';
|
||||
|
||||
const ssAnimals = [
|
||||
{ id: 'a1', animal_name: 'Alpha', animal_id_string: 'R-001', subject_info: { grp: 'Control' } },
|
||||
{ id: 'a2', animal_name: 'Beta', animal_id_string: 'R-002', subject_info: { grp: 'Drug' } },
|
||||
];
|
||||
const ssStatuses = [
|
||||
{ animal_id: 'a1', date: '2026-07-01T00:00:00Z', analysis_summary: { total: 5 } },
|
||||
{ animal_id: 'a1', date: '2026-07-02T00:00:00Z', analysis_summary: { total: 7 } },
|
||||
{ animal_id: 'a2', date: '2026-07-01T00:00:00Z', analysis_summary: { total: 9 } },
|
||||
];
|
||||
const totalParam = { id: '__total__', label: 'Total attempts', kind: 'total', group: 'metrics' };
|
||||
|
||||
describe('buildSubjectSeriesMatrix', () => {
|
||||
it('date X: subjects as columns, date rows, blank where missing, context names the metric', () => {
|
||||
const m = buildSubjectSeriesMatrix(
|
||||
{ xField: '__date__', dataParam: totalParam, groupField: '__none__' },
|
||||
{ statuses: ssStatuses, animals: ssAnimals, dailyTemplate: [] },
|
||||
);
|
||||
expect(m.corner).toBe('Date');
|
||||
expect(m.context).toEqual({ label: 'Data', value: 'Total attempts' });
|
||||
expect(m.groupAxis).toBeNull();
|
||||
expect(m.columns.map((c) => c.label)).toEqual(['Alpha', 'Beta']);
|
||||
expect(m.rows.map((r) => r.member.label)).toEqual(['2026-07-01', '2026-07-02']);
|
||||
expect(m.rows[0].values).toEqual([5, 9]);
|
||||
expect(m.rows[1].values).toEqual([7, '']);
|
||||
});
|
||||
it('# days reach X: rows align each subject by day ordinal', () => {
|
||||
const m = buildSubjectSeriesMatrix(
|
||||
{ xField: '__days__', dataParam: totalParam, groupField: '__none__' },
|
||||
{ statuses: ssStatuses, animals: ssAnimals, dailyTemplate: [] },
|
||||
);
|
||||
expect(m.corner).toBe('# Days Reach');
|
||||
expect(m.rows.map((r) => r.member.label)).toEqual(['1', '2']);
|
||||
expect(m.rows[0].values).toEqual([5, 9]);
|
||||
expect(m.rows[1].values).toEqual([7, '']);
|
||||
});
|
||||
it('grouping sets groupAxis col and clusters subjects', () => {
|
||||
const m = buildSubjectSeriesMatrix(
|
||||
{ xField: '__date__', dataParam: totalParam, groupField: 'grp' },
|
||||
{ statuses: ssStatuses, animals: ssAnimals, dailyTemplate: [] },
|
||||
);
|
||||
expect(m.groupAxis).toBe('col');
|
||||
expect(m.columns.map((c) => [c.group, c.label])).toEqual([['Control', 'Alpha'], ['Drug', 'Beta']]);
|
||||
});
|
||||
it('drops entirely-blank rows', () => {
|
||||
const statuses = [
|
||||
{ animal_id: 'a1', date: '2026-07-01T00:00:00Z', analysis_summary: { total: 5 } },
|
||||
{ animal_id: 'a1', date: '2026-07-05T00:00:00Z', analysis_summary: null },
|
||||
];
|
||||
const m = buildSubjectSeriesMatrix(
|
||||
{ xField: '__date__', dataParam: totalParam, groupField: '__none__' },
|
||||
{ statuses, animals: ssAnimals, dailyTemplate: [] },
|
||||
);
|
||||
expect(m.rows.map((r) => r.member.label)).toEqual(['2026-07-01']);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user