Skip to content

Commit 67d4d5b

Browse files
Copilothotlong
andcommitted
Add integration test for ReportView data loading
- Test data loading from objectName - Test inline data handling - Test loading state display - Test missing report error handling Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 111169d commit 67d4d5b

1 file changed

Lines changed: 211 additions & 0 deletions

File tree

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/**
2+
* ReportView Integration Tests
3+
*
4+
* Tests ReportView component with data loading from adapter
5+
*/
6+
7+
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
8+
import { render, screen, waitFor } from '@testing-library/react';
9+
import '@testing-library/jest-dom';
10+
import { MemoryRouter, Route, Routes } from 'react-router-dom';
11+
import { ReportView } from '../components/ReportView';
12+
import { MetadataProvider } from '../context/MetadataProvider';
13+
import { startMockServer, stopMockServer, getDriver } from '../mocks/server';
14+
import { ObjectStackAdapter } from '@object-ui/data-objectstack';
15+
import type { DataSource } from '@object-ui/types';
16+
17+
describe('ReportView Data Loading', () => {
18+
let adapter: ObjectStackAdapter;
19+
20+
beforeAll(async () => {
21+
await startMockServer();
22+
adapter = new ObjectStackAdapter({
23+
baseUrl: '',
24+
autoReconnect: false,
25+
});
26+
await adapter.connect();
27+
28+
// Seed test data for the opportunity object
29+
const driver = getDriver();
30+
await driver.insert('opportunity', {
31+
id: '1',
32+
name: 'Deal Alpha',
33+
amount: 50000,
34+
stage: 'Proposal',
35+
close_date: '2024-03-31',
36+
});
37+
await driver.insert('opportunity', {
38+
id: '2',
39+
name: 'Deal Beta',
40+
amount: 75000,
41+
stage: 'Negotiation',
42+
close_date: '2024-04-15',
43+
});
44+
await driver.insert('opportunity', {
45+
id: '3',
46+
name: 'Deal Gamma',
47+
amount: 100000,
48+
stage: 'Closed Won',
49+
close_date: '2024-02-28',
50+
});
51+
});
52+
53+
afterAll(() => {
54+
stopMockServer();
55+
});
56+
57+
it('should load and display report data from objectName', async () => {
58+
render(
59+
<MemoryRouter initialEntries={['/apps/crm_app/report/sales_performance_q1']}>
60+
<MetadataProvider adapter={adapter}>
61+
<Routes>
62+
<Route
63+
path="/apps/:appName/report/:reportName"
64+
element={<ReportView dataSource={adapter as DataSource} />}
65+
/>
66+
</Routes>
67+
</MetadataProvider>
68+
</MemoryRouter>
69+
);
70+
71+
// Wait for metadata to load
72+
await waitFor(
73+
() => {
74+
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
75+
},
76+
{ timeout: 3000 }
77+
);
78+
79+
// Check that the report viewer is rendered
80+
await waitFor(
81+
() => {
82+
expect(screen.getByText(/Q1 Sales Performance/i)).toBeInTheDocument();
83+
},
84+
{ timeout: 3000 }
85+
);
86+
87+
// The report should render with data (checking for toolbar presence)
88+
expect(screen.getByRole('button', { name: /print/i })).toBeInTheDocument();
89+
});
90+
91+
it('should handle inline data in report definition', async () => {
92+
// Mock adapter for this test
93+
const mockAdapter = {
94+
...adapter,
95+
find: vi.fn().mockResolvedValue({
96+
data: [],
97+
total: 0,
98+
page: 1,
99+
pageSize: 0,
100+
hasMore: false,
101+
}),
102+
} as unknown as DataSource;
103+
104+
render(
105+
<MemoryRouter initialEntries={['/apps/test_app/report/inline_data_report']}>
106+
<MetadataProvider adapter={adapter}>
107+
<Routes>
108+
<Route
109+
path="/apps/:appName/report/:reportName"
110+
element={<ReportView dataSource={mockAdapter} />}
111+
/>
112+
</Routes>
113+
</MetadataProvider>
114+
</MemoryRouter>
115+
);
116+
117+
// Wait for metadata to load
118+
await waitFor(
119+
() => {
120+
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
121+
},
122+
{ timeout: 3000 }
123+
);
124+
125+
// If report has inline data, adapter.find should NOT be called
126+
// (This test would need a report with inline data in the metadata)
127+
});
128+
129+
it('should display loading state while fetching data', async () => {
130+
// Create a mock adapter that delays the response
131+
const delayedAdapter = {
132+
...adapter,
133+
find: vi.fn().mockImplementation(
134+
() =>
135+
new Promise((resolve) =>
136+
setTimeout(
137+
() =>
138+
resolve({
139+
data: [{ id: '1', name: 'Test' }],
140+
total: 1,
141+
page: 1,
142+
pageSize: 1,
143+
hasMore: false,
144+
}),
145+
100
146+
)
147+
)
148+
),
149+
} as unknown as DataSource;
150+
151+
render(
152+
<MemoryRouter initialEntries={['/apps/crm_app/report/sales_performance_q1']}>
153+
<MetadataProvider adapter={adapter}>
154+
<Routes>
155+
<Route
156+
path="/apps/:appName/report/:reportName"
157+
element={<ReportView dataSource={delayedAdapter} />}
158+
/>
159+
</Routes>
160+
</MetadataProvider>
161+
</MemoryRouter>
162+
);
163+
164+
// Initially, we should see metadata loading
165+
await waitFor(
166+
() => {
167+
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
168+
},
169+
{ timeout: 3000 }
170+
);
171+
172+
// Then the report should load
173+
await waitFor(
174+
() => {
175+
expect(screen.getByText(/Q1 Sales Performance/i)).toBeInTheDocument();
176+
},
177+
{ timeout: 3000 }
178+
);
179+
});
180+
181+
it('should handle missing report gracefully', async () => {
182+
render(
183+
<MemoryRouter initialEntries={['/apps/crm_app/report/nonexistent_report']}>
184+
<MetadataProvider adapter={adapter}>
185+
<Routes>
186+
<Route
187+
path="/apps/:appName/report/:reportName"
188+
element={<ReportView dataSource={adapter as DataSource} />}
189+
/>
190+
</Routes>
191+
</MetadataProvider>
192+
</MemoryRouter>
193+
);
194+
195+
// Wait for metadata to load
196+
await waitFor(
197+
() => {
198+
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
199+
},
200+
{ timeout: 3000 }
201+
);
202+
203+
// Should show "Report Not Found" message
204+
await waitFor(
205+
() => {
206+
expect(screen.getByText(/Report Not Found/i)).toBeInTheDocument();
207+
},
208+
{ timeout: 3000 }
209+
);
210+
});
211+
});

0 commit comments

Comments
 (0)