Skip to content

Commit c242406

Browse files
Copilothotlong
andcommitted
Add mobile layout tests for DashboardRenderer
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 6670d8e commit c242406

1 file changed

Lines changed: 214 additions & 0 deletions

File tree

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
/**
2+
* ObjectUI
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10+
import { render } from '@testing-library/react';
11+
import { DashboardRenderer } from '../DashboardRenderer';
12+
import type { DashboardSchema } from '@object-ui/types';
13+
14+
describe('DashboardRenderer mobile layout', () => {
15+
let originalInnerWidth: number;
16+
17+
beforeEach(() => {
18+
originalInnerWidth = window.innerWidth;
19+
});
20+
21+
afterEach(() => {
22+
// Restore original window size
23+
Object.defineProperty(window, 'innerWidth', {
24+
writable: true,
25+
configurable: true,
26+
value: originalInnerWidth,
27+
});
28+
});
29+
30+
const setWindowWidth = (width: number) => {
31+
Object.defineProperty(window, 'innerWidth', {
32+
writable: true,
33+
configurable: true,
34+
value: width,
35+
});
36+
window.dispatchEvent(new Event('resize'));
37+
};
38+
39+
it('should use mobile layout when window width is less than 768px', () => {
40+
const schema: DashboardSchema = {
41+
type: 'dashboard',
42+
name: 'test',
43+
title: 'Test Dashboard',
44+
widgets: [
45+
{
46+
type: 'metric',
47+
title: 'Revenue',
48+
options: { value: '$100k', label: 'Total Revenue' },
49+
},
50+
{
51+
type: 'metric',
52+
title: 'Users',
53+
options: { value: '1,234', label: 'Active Users' },
54+
},
55+
],
56+
};
57+
58+
// Set mobile viewport width
59+
setWindowWidth(375);
60+
61+
const { container } = render(<DashboardRenderer schema={schema} />);
62+
63+
// Mobile layout should have px-4 class and grid grid-cols-2 for metrics
64+
const mobileContainer = container.querySelector('.px-4');
65+
expect(mobileContainer).toBeTruthy();
66+
67+
const metricGrid = container.querySelector('.grid.grid-cols-2');
68+
expect(metricGrid).toBeTruthy();
69+
});
70+
71+
it('should use desktop layout when window width is 768px or more', () => {
72+
const schema: DashboardSchema = {
73+
type: 'dashboard',
74+
name: 'test',
75+
title: 'Test Dashboard',
76+
widgets: [
77+
{
78+
type: 'metric',
79+
title: 'Revenue',
80+
options: { value: '$100k', label: 'Total Revenue' },
81+
},
82+
],
83+
};
84+
85+
// Set desktop viewport width
86+
setWindowWidth(1024);
87+
88+
const { container } = render(<DashboardRenderer schema={schema} />);
89+
90+
// Desktop layout should have grid class but not px-4 or grid-cols-2
91+
const desktopGrid = container.querySelector('.grid.auto-rows-min');
92+
expect(desktopGrid).toBeTruthy();
93+
94+
const mobileContainer = container.querySelector('.px-4');
95+
expect(mobileContainer).toBeFalsy();
96+
});
97+
98+
it('should separate metric and non-metric widgets in mobile layout', () => {
99+
const schema: DashboardSchema = {
100+
type: 'dashboard',
101+
name: 'test',
102+
title: 'Test Dashboard',
103+
widgets: [
104+
{
105+
type: 'metric',
106+
title: 'Metric 1',
107+
options: { value: '100', label: 'Count' },
108+
},
109+
{
110+
type: 'metric',
111+
title: 'Metric 2',
112+
options: { value: '200', label: 'Total' },
113+
},
114+
{
115+
type: 'bar',
116+
title: 'Chart',
117+
options: {
118+
data: { items: [{ name: 'A', value: 10 }] },
119+
xField: 'name',
120+
yField: 'value',
121+
},
122+
},
123+
],
124+
};
125+
126+
// Set mobile viewport width
127+
setWindowWidth(375);
128+
129+
const { container } = render(<DashboardRenderer schema={schema} />);
130+
131+
// Should have a 2-column grid for metrics
132+
const metricGrid = container.querySelector('.grid.grid-cols-2');
133+
expect(metricGrid).toBeTruthy();
134+
135+
// Should have metric widgets in the grid
136+
const metricWidgets = metricGrid?.children;
137+
expect(metricWidgets?.length).toBe(2);
138+
139+
// Should have a flex-col container for other widgets
140+
const otherWidgetsContainer = container.querySelector('.flex.flex-col.gap-4');
141+
expect(otherWidgetsContainer).toBeTruthy();
142+
});
143+
144+
it('should handle mobile layout with only metric widgets', () => {
145+
const schema: DashboardSchema = {
146+
type: 'dashboard',
147+
name: 'test',
148+
title: 'Test Dashboard',
149+
widgets: [
150+
{
151+
type: 'metric',
152+
title: 'Metric 1',
153+
options: { value: '100' },
154+
},
155+
{
156+
type: 'metric',
157+
title: 'Metric 2',
158+
options: { value: '200' },
159+
},
160+
],
161+
};
162+
163+
// Set mobile viewport width
164+
setWindowWidth(375);
165+
166+
const { container } = render(<DashboardRenderer schema={schema} />);
167+
168+
// Should have a 2-column grid for metrics
169+
const metricGrid = container.querySelector('.grid.grid-cols-2');
170+
expect(metricGrid).toBeTruthy();
171+
expect(metricGrid?.children.length).toBe(2);
172+
});
173+
174+
it('should handle mobile layout with only non-metric widgets', () => {
175+
const schema: DashboardSchema = {
176+
type: 'dashboard',
177+
name: 'test',
178+
title: 'Test Dashboard',
179+
widgets: [
180+
{
181+
type: 'bar',
182+
title: 'Chart 1',
183+
options: {
184+
data: { items: [{ name: 'A', value: 10 }] },
185+
xField: 'name',
186+
yField: 'value',
187+
},
188+
},
189+
{
190+
type: 'line',
191+
title: 'Chart 2',
192+
options: {
193+
data: { items: [{ name: 'B', value: 20 }] },
194+
xField: 'name',
195+
yField: 'value',
196+
},
197+
},
198+
],
199+
};
200+
201+
// Set mobile viewport width
202+
setWindowWidth(375);
203+
204+
const { container } = render(<DashboardRenderer schema={schema} />);
205+
206+
// Should not have a metric grid
207+
const metricGrid = container.querySelector('.grid.grid-cols-2');
208+
expect(metricGrid).toBeFalsy();
209+
210+
// Should have a flex-col container for other widgets
211+
const otherWidgetsContainer = container.querySelector('.flex.flex-col.gap-4');
212+
expect(otherWidgetsContainer).toBeTruthy();
213+
});
214+
});

0 commit comments

Comments
 (0)