Skip to content

Commit 5c24e30

Browse files
committed
Add ObjectGrid interaction tests for sorting and filtering features
1 parent 7767297 commit 5c24e30

2 files changed

Lines changed: 161 additions & 1 deletion

File tree

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* ObjectGrid Interaction Tests
3+
*
4+
* Verifies interactive features of the ObjectGrid:
5+
* - Sorting (Clicking headers)
6+
* - Filtering (Using search bar)
7+
* - Pagination
8+
*/
9+
10+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
11+
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
12+
import '@testing-library/jest-dom';
13+
import { ObjectStackClient } from '@objectstack/client';
14+
import { ObjectGrid } from '@object-ui/plugin-grid';
15+
import { startMockServer, stopMockServer } from '../mocks/server';
16+
import { ObjectStackDataSource } from '../dataSource';
17+
18+
describe('ObjectGrid Interactions', () => {
19+
let client: ObjectStackClient;
20+
let dataSource: ObjectStackDataSource;
21+
22+
// Sample data for checking Sort/Filter orders
23+
const staticData = [
24+
{ id: '1', name: 'Zebra', score: 10 },
25+
{ id: '2', name: 'Alpha', score: 20 },
26+
{ id: '3', name: 'Beta', score: 30 },
27+
];
28+
29+
beforeAll(async () => {
30+
await startMockServer();
31+
client = new ObjectStackClient({ baseUrl: 'http://localhost:3000' });
32+
await client.connect();
33+
dataSource = new ObjectStackDataSource(client);
34+
});
35+
36+
afterAll(() => {
37+
stopMockServer();
38+
});
39+
40+
it('should sort rows when column header is clicked', async () => {
41+
render(
42+
<ObjectGrid
43+
schema={{
44+
type: 'object-grid',
45+
objectName: 'test_obj',
46+
columns: ['name', 'score'],
47+
data: {
48+
provider: 'value',
49+
items: staticData
50+
}
51+
}}
52+
dataSource={dataSource}
53+
/>
54+
);
55+
56+
// Wait for rendering
57+
await waitFor(() => {
58+
expect(screen.getByText('Zebra')).toBeInTheDocument();
59+
});
60+
61+
const rows = screen.getAllByRole('row');
62+
// Row 0 is header. Rows 1..3 are data.
63+
// Initial order: Zebra, Alpha, Beta (Mock data order)
64+
expect(rows[1]).toHaveTextContent('Zebra');
65+
expect(rows[2]).toHaveTextContent('Alpha');
66+
expect(rows[3]).toHaveTextContent('Beta');
67+
68+
// Click "Name" header to Sort ASC
69+
const nameHeader = screen.getByRole('columnheader', { name: /Name/i });
70+
fireEvent.click(nameHeader);
71+
72+
// Expect: Alpha, Beta, Zebra
73+
await waitFor(() => {
74+
const sortedRows = screen.getAllByRole('row');
75+
expect(sortedRows[1]).toHaveTextContent('Alpha');
76+
expect(sortedRows[2]).toHaveTextContent('Beta');
77+
expect(sortedRows[3]).toHaveTextContent('Zebra');
78+
});
79+
80+
// Click "Name" header again to Sort DESC
81+
fireEvent.click(nameHeader);
82+
83+
// Expect: Zebra, Beta, Alpha
84+
await waitFor(() => {
85+
const sortedRows = screen.getAllByRole('row');
86+
expect(sortedRows[1]).toHaveTextContent('Zebra');
87+
expect(sortedRows[2]).toHaveTextContent('Beta');
88+
expect(sortedRows[3]).toHaveTextContent('Alpha');
89+
});
90+
});
91+
92+
it('should sort rows when column header is clicked (Server Data)', async () => {
93+
render(
94+
<ObjectGrid
95+
schema={{
96+
type: 'object-grid',
97+
objectName: 'contact',
98+
columns: ['name', 'email'],
99+
}}
100+
dataSource={dataSource}
101+
/>
102+
);
103+
104+
await waitFor(() => {
105+
expect(screen.getByText('Alice Johnson')).toBeInTheDocument();
106+
});
107+
108+
// Test if sorting interaction works seamlessly on server data which is rendered client-side by DataTable
109+
// Note: ObjectGrid fetches a page, and DataTable sorts that page client-side.
110+
// This test verifies that connection functionality remains valid.
111+
112+
const nameHeader = screen.getByRole('columnheader', { name: /Name/i });
113+
fireEvent.click(nameHeader); // Sort ASC
114+
115+
// Wait for potential re-render/sort
116+
await waitFor(() => {
117+
const rows = screen.getAllByRole('row');
118+
// Just ensure rows are still present and structure is valid
119+
expect(rows.length).toBeGreaterThan(1);
120+
});
121+
});
122+
123+
it('should filter rows when search input is used', async () => {
124+
// DataTableRenderer renders a "Search..." input if searchable is true (default?)
125+
render(
126+
<ObjectGrid
127+
schema={{
128+
type: 'object-grid',
129+
objectName: 'test_obj',
130+
columns: ['name'],
131+
data: {
132+
provider: 'value',
133+
items: staticData
134+
},
135+
searchableFields: ['name'] // Triggers search input
136+
}}
137+
dataSource={dataSource}
138+
/>
139+
);
140+
141+
await waitFor(() => {
142+
expect(screen.getByText('Zebra')).toBeInTheDocument();
143+
});
144+
145+
// Find Search Input
146+
const searchInput = screen.getByPlaceholderText('Search...');
147+
148+
// Type "Ze"
149+
fireEvent.change(searchInput, { target: { value: 'Ze' } });
150+
151+
await waitFor(() => {
152+
expect(screen.getByText('Zebra')).toBeInTheDocument();
153+
expect(screen.queryByText('Alpha')).not.toBeInTheDocument();
154+
expect(screen.queryByText('Beta')).not.toBeInTheDocument();
155+
});
156+
});
157+
});

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ vi.mock('@object-ui/components', async () => {
3737
<button data-testid="tabs-trigger" data-tab-value={value}>
3838
{children}
3939
</button>
40-
)
40+
),
41+
Empty: ({ children }: any) => <div data-testid="empty">{children}</div>,
42+
EmptyTitle: ({ children }: any) => <div data-testid="empty-title">{children}</div>,
43+
EmptyDescription: ({ children }: any) => <div data-testid="empty-description">{children}</div>
4144
};
4245
});
4346

0 commit comments

Comments
 (0)