Skip to content

Commit 20a628e

Browse files
committed
test: Add tests for container types, reordering, and grouping
14 new tests: tab/group schema validation, activeTabId, invalid types, section reorder (both directions), tile grouping with preservation of existing sections.
1 parent c874820 commit 20a628e

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

packages/app/src/__tests__/dashboardSections.test.tsx

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,56 @@ describe('DashboardContainer schema', () => {
5151
}).success,
5252
).toBe(false);
5353
});
54+
55+
it('validates a tab container', () => {
56+
const result = DashboardContainerSchema.safeParse({
57+
id: 'tab-1',
58+
type: 'tab',
59+
title: 'Overview Tabs',
60+
collapsed: false,
61+
});
62+
expect(result.success).toBe(true);
63+
if (result.success) {
64+
expect(result.data.type).toBe('tab');
65+
}
66+
});
67+
68+
it('validates a group container', () => {
69+
const result = DashboardContainerSchema.safeParse({
70+
id: 'group-1',
71+
type: 'group',
72+
title: 'Key Metrics',
73+
collapsed: false,
74+
});
75+
expect(result.success).toBe(true);
76+
if (result.success) {
77+
expect(result.data.type).toBe('group');
78+
}
79+
});
80+
81+
it('validates a tab container with activeTabId', () => {
82+
const result = DashboardContainerSchema.safeParse({
83+
id: 'tab-1',
84+
type: 'tab',
85+
title: 'Tabs',
86+
collapsed: false,
87+
activeTabId: 'sub-tab-1',
88+
});
89+
expect(result.success).toBe(true);
90+
if (result.success) {
91+
expect(result.data.activeTabId).toBe('sub-tab-1');
92+
}
93+
});
94+
95+
it('rejects an invalid container type', () => {
96+
const result = DashboardContainerSchema.safeParse({
97+
id: 'c-1',
98+
type: 'invalid',
99+
title: 'Bad Type',
100+
collapsed: false,
101+
});
102+
expect(result.success).toBe(false);
103+
});
54104
});
55105

56106
describe('Tile schema with containerId', () => {
@@ -525,4 +575,105 @@ describe('section authoring operations', () => {
525575
expect(result.tiles[0].containerId).toBeUndefined();
526576
});
527577
});
578+
579+
describe('reorder sections', () => {
580+
function reorderSections(
581+
dashboard: SimpleDashboard,
582+
fromIndex: number,
583+
toIndex: number,
584+
) {
585+
if (!dashboard.containers) return dashboard;
586+
const containers = [...dashboard.containers];
587+
const [removed] = containers.splice(fromIndex, 1);
588+
containers.splice(toIndex, 0, removed);
589+
return { ...dashboard, containers };
590+
}
591+
592+
it('moves a section from first to last', () => {
593+
const dashboard: SimpleDashboard = {
594+
tiles: [],
595+
containers: [
596+
{ id: 's1', title: 'First', collapsed: false },
597+
{ id: 's2', title: 'Second', collapsed: false },
598+
{ id: 's3', title: 'Third', collapsed: false },
599+
],
600+
};
601+
const result = reorderSections(dashboard, 0, 2);
602+
expect(result.containers!.map(c => c.id)).toEqual(['s2', 's3', 's1']);
603+
});
604+
605+
it('moves a section from last to first', () => {
606+
const dashboard: SimpleDashboard = {
607+
tiles: [],
608+
containers: [
609+
{ id: 's1', title: 'First', collapsed: false },
610+
{ id: 's2', title: 'Second', collapsed: false },
611+
{ id: 's3', title: 'Third', collapsed: false },
612+
],
613+
};
614+
const result = reorderSections(dashboard, 2, 0);
615+
expect(result.containers!.map(c => c.id)).toEqual(['s3', 's1', 's2']);
616+
});
617+
618+
it('does not affect tiles when sections are reordered', () => {
619+
const dashboard: SimpleDashboard = {
620+
tiles: [
621+
{ id: 'a', containerId: 's1' },
622+
{ id: 'b', containerId: 's2' },
623+
],
624+
containers: [
625+
{ id: 's1', title: 'First', collapsed: false },
626+
{ id: 's2', title: 'Second', collapsed: false },
627+
],
628+
};
629+
const result = reorderSections(dashboard, 0, 1);
630+
expect(result.tiles).toEqual(dashboard.tiles);
631+
expect(result.containers!.map(c => c.id)).toEqual(['s2', 's1']);
632+
});
633+
});
634+
635+
describe('group selected tiles', () => {
636+
function groupTilesIntoSection(
637+
dashboard: SimpleDashboard,
638+
tileIds: string[],
639+
newSection: SimpleSection,
640+
) {
641+
const containers = [...(dashboard.containers ?? []), newSection];
642+
const tiles = dashboard.tiles.map(t =>
643+
tileIds.includes(t.id) ? { ...t, containerId: newSection.id } : t,
644+
);
645+
return { ...dashboard, containers, tiles };
646+
}
647+
648+
it('groups selected tiles into a new section', () => {
649+
const dashboard: SimpleDashboard = {
650+
tiles: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
651+
};
652+
const result = groupTilesIntoSection(dashboard, ['a', 'c'], {
653+
id: 'new-s',
654+
title: 'New Section',
655+
collapsed: false,
656+
});
657+
expect(result.containers).toHaveLength(1);
658+
expect(result.tiles.find(t => t.id === 'a')?.containerId).toBe('new-s');
659+
expect(result.tiles.find(t => t.id === 'b')?.containerId).toBeUndefined();
660+
expect(result.tiles.find(t => t.id === 'c')?.containerId).toBe('new-s');
661+
});
662+
663+
it('preserves existing sections when grouping', () => {
664+
const dashboard: SimpleDashboard = {
665+
tiles: [{ id: 'a', containerId: 's1' }, { id: 'b' }, { id: 'c' }],
666+
containers: [{ id: 's1', title: 'Existing', collapsed: false }],
667+
};
668+
const result = groupTilesIntoSection(dashboard, ['b', 'c'], {
669+
id: 'new-s',
670+
title: 'Grouped',
671+
collapsed: false,
672+
});
673+
expect(result.containers).toHaveLength(2);
674+
expect(result.tiles.find(t => t.id === 'a')?.containerId).toBe('s1');
675+
expect(result.tiles.find(t => t.id === 'b')?.containerId).toBe('new-s');
676+
expect(result.tiles.find(t => t.id === 'c')?.containerId).toBe('new-s');
677+
});
678+
});
528679
});

0 commit comments

Comments
 (0)