Skip to content

Commit 953d614

Browse files
authored
Merge pull request #363 from objectstack-ai/copilot/add-integration-tests-for-object-ui
2 parents 6ba688d + 7ad3259 commit 953d614

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed

apps/console/src/__tests__/BrowserSimulation.test.tsx

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,79 @@ describe('Console Application Simulation', () => {
217217
expect(screen.getAllByText('5000').length).toBeGreaterThan(0);
218218
});
219219

220+
// -----------------------------------------------------------------------------
221+
// SIMPLIFIED FORM INTEGRATION TESTS
222+
// -----------------------------------------------------------------------------
223+
it('Form Scenario B: Metadata-Driven Form Generation', async () => {
224+
vi.spyOn(mocks.MockDataSource.prototype, 'getObjectSchema').mockResolvedValue({
225+
name: 'kitchen_sink',
226+
fields: {
227+
name: { type: 'text', label: 'Name Field' },
228+
amount: { type: 'number', label: 'Amount Field' }
229+
}
230+
});
231+
232+
renderApp('/kitchen_sink');
233+
await waitFor(() => {
234+
expect(screen.getByRole('heading', { name: /Kitchen Sink/i })).toBeInTheDocument();
235+
});
236+
237+
// Verify the form can be opened (showing metadata was loaded)
238+
const newButton = screen.getByRole('button', { name: /New Kitchen Sink/i });
239+
fireEvent.click(newButton);
240+
241+
// Verify form loaded with schema-based fields
242+
await waitFor(() => {
243+
expect(screen.getByRole('dialog')).toBeInTheDocument();
244+
});
245+
246+
// Form should render based on mocked schema
247+
// The actual field labels might differ based on implementation
248+
// but the form should render without errors
249+
expect(screen.queryByText(/error/i)).not.toBeInTheDocument();
250+
});
251+
252+
// -----------------------------------------------------------------------------
253+
// SIMPLIFIED GRID INTEGRATION TESTS
254+
// -----------------------------------------------------------------------------
255+
it('Grid Scenario A: Grid Rendering and Actions', async () => {
256+
renderApp('/kitchen_sink');
257+
258+
await waitFor(() => {
259+
expect(screen.getByRole('heading', { name: /Kitchen Sink/i })).toBeInTheDocument();
260+
});
261+
262+
const newButton = screen.getByRole('button', { name: /New Kitchen Sink/i });
263+
expect(newButton).toBeInTheDocument();
264+
});
265+
266+
it('Grid Scenario B: Grid Data Loading', async () => {
267+
const seedData = [
268+
{ id: '1', name: 'Item 1', amount: 100 },
269+
{ id: '2', name: 'Item 2', amount: 200 }
270+
];
271+
272+
const findSpy = vi.spyOn(mocks.MockDataSource.prototype, 'find')
273+
.mockResolvedValue({ data: seedData });
274+
275+
renderApp('/kitchen_sink');
276+
277+
await waitFor(() => {
278+
expect(screen.getByRole('heading', { name: /Kitchen Sink/i })).toBeInTheDocument();
279+
});
280+
281+
// Verify data source was called to load grid data
282+
await waitFor(() => {
283+
expect(findSpy).toHaveBeenCalledWith('kitchen_sink', expect.any(Object));
284+
});
285+
286+
// Verify grid displays the loaded data
287+
await waitFor(() => {
288+
expect(screen.getByText('Item 1')).toBeInTheDocument();
289+
});
290+
expect(screen.getByText('Item 2')).toBeInTheDocument();
291+
});
292+
220293
});
221294

222295
// -----------------------------------------------------------------------------
@@ -664,3 +737,87 @@ describe('Kanban Integration', () => {
664737
expect(findSpy).toHaveBeenCalledWith('project_task', expect.any(Object));
665738
});
666739
});
740+
741+
742+
// -----------------------------------------------------------------------------
743+
// FIELDS INTEGRATION TESTS
744+
// -----------------------------------------------------------------------------
745+
describe('Fields Integration', () => {
746+
it('Scenario A: Field Type Mapping', async () => {
747+
const { mapFieldTypeToFormType } = await import('@object-ui/fields');
748+
749+
expect(mapFieldTypeToFormType('text')).toBe('field:text');
750+
expect(mapFieldTypeToFormType('email')).toBe('field:email');
751+
expect(mapFieldTypeToFormType('number')).toBe('field:number');
752+
expect(mapFieldTypeToFormType('boolean')).toBe('field:boolean');
753+
expect(mapFieldTypeToFormType('select')).toBe('field:select');
754+
});
755+
756+
it('Scenario A.2: Unknown Field Type Fallback in Form', async () => {
757+
const { mapFieldTypeToFormType } = await import('@object-ui/fields');
758+
759+
// Verify unknown types fallback to text
760+
expect(mapFieldTypeToFormType('unknown_type')).toBe('field:text');
761+
expect(mapFieldTypeToFormType('custom_widget')).toBe('field:text');
762+
763+
// This ensures forms don't break when encountering unknown field types
764+
// The actual rendering is tested via the full form integration tests
765+
});
766+
767+
it('Scenario B: Field Formatting Utilities', async () => {
768+
const { formatCurrency, formatDate, formatPercent } = await import('@object-ui/fields');
769+
770+
const formatted = formatCurrency(1234.56);
771+
expect(formatted).toContain('1,234.56');
772+
773+
const dateStr = formatDate(new Date('2024-01-15'));
774+
expect(dateStr).toContain('2024');
775+
776+
const percent = formatPercent(0.1234);
777+
expect(percent).toBe('12.34%');
778+
});
779+
});
780+
781+
// -----------------------------------------------------------------------------
782+
// DASHBOARD INTEGRATION TESTS
783+
// -----------------------------------------------------------------------------
784+
describe('Dashboard Integration', () => {
785+
const renderApp = (initialRoute: string) => {
786+
return render(
787+
<MemoryRouter initialEntries={[initialRoute]}>
788+
<AppContent />
789+
</MemoryRouter>
790+
);
791+
};
792+
793+
it('Scenario A: Dashboard Page Rendering', async () => {
794+
renderApp('/dashboard/sales_dashboard');
795+
796+
await waitFor(() => {
797+
expect(screen.getByText(/Sales Overview/i)).toBeInTheDocument();
798+
});
799+
800+
expect(screen.getByText(/Sales by Region/i)).toBeInTheDocument();
801+
});
802+
803+
it('Scenario B: Report Page Rendering', async () => {
804+
renderApp('/page/report_page');
805+
806+
await waitFor(() => {
807+
expect(screen.getByText(/Sales Performance Report/i)).toBeInTheDocument();
808+
});
809+
810+
expect(screen.getByText('Region')).toBeInTheDocument();
811+
expect(screen.getByText('North')).toBeInTheDocument();
812+
});
813+
814+
it('Scenario C: Component Registry Check', async () => {
815+
const { ComponentRegistry } = await import('@object-ui/core');
816+
817+
const dashboardRenderer = ComponentRegistry.get('dashboard');
818+
expect(dashboardRenderer).toBeDefined();
819+
820+
const reportRenderer = ComponentRegistry.get('report');
821+
expect(reportRenderer).toBeDefined();
822+
});
823+
});

0 commit comments

Comments
 (0)