Skip to content

Commit df4dab0

Browse files
committed
Add integration tests for ObjectGallery and ListView components; verify data rendering and handling of empty states
1 parent bbca162 commit df4dab0

File tree

2 files changed

+159
-1
lines changed

2 files changed

+159
-1
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
2+
import { describe, it, expect, vi, beforeEach } from 'vitest';
3+
import { render, screen, act, waitFor } from '@testing-library/react';
4+
import '@testing-library/jest-dom';
5+
import { ListView } from '@object-ui/plugin-list';
6+
import { ObjectGallery } from '@object-ui/plugin-list/ObjectGallery';
7+
import { ComponentRegistry } from '@object-ui/core';
8+
import { SchemaRendererProvider } from '@object-ui/react';
9+
10+
// Mock UI components
11+
vi.mock('@object-ui/components', async () => {
12+
return {
13+
cn: (...inputs: any[]) => inputs.filter(Boolean).join(' '),
14+
Button: ({ children, onClick }: any) => <button onClick={onClick}>{children}</button>,
15+
Input: (props: any) => <input {...props} data-testid="mock-input" />,
16+
ToggleGroup: ({ children, value, onValueChange }: any) => <div data-value={value} onChange={onValueChange}>{children}</div>,
17+
ToggleGroupItem: ({ children, value }: any) => <button data-value={value}>{children}</button>,
18+
Tabs: ({ children }: any) => <div>{children}</div>,
19+
TabsList: ({ children }: any) => <div>{children}</div>,
20+
TabsTrigger: ({ children }: any) => <button>{children}</button>,
21+
Empty: ({ children }: any) => <div>{children}</div>,
22+
};
23+
});
24+
25+
describe('ObjectGallery & ListView Integration', () => {
26+
27+
beforeEach(() => {
28+
// Register the gallery component so SchemaRenderer can find it
29+
ComponentRegistry.register('object-gallery', ObjectGallery, { namespace: 'plugin-list' });
30+
// Register other views to avoid warnings
31+
ComponentRegistry.register('object-grid', () => <div>Grid</div>);
32+
});
33+
34+
const mockData = [
35+
{ _id: '1', name: 'Product A', category: 'Tech', image: 'http://img/a.jpg' },
36+
{ _id: '2', name: 'Product B', category: 'Home', image: 'http://img/b.jpg' },
37+
];
38+
39+
const mockDataSource = {
40+
find: vi.fn(),
41+
delete: vi.fn()
42+
};
43+
44+
it('should receive data from ListView and render items', async () => {
45+
mockDataSource.find.mockResolvedValue(mockData);
46+
47+
const schema = {
48+
objectName: 'product',
49+
viewType: 'gallery',
50+
options: {
51+
gallery: {
52+
imageField: 'image',
53+
titleField: 'name',
54+
subtitleField: 'category'
55+
}
56+
}
57+
};
58+
59+
await act(async () => {
60+
render(
61+
<SchemaRendererProvider dataSource={mockDataSource}>
62+
<ListView schema={schema as any} dataSource={mockDataSource} />
63+
</SchemaRendererProvider>
64+
);
65+
});
66+
67+
// Wait for data fetch
68+
await waitFor(() => {
69+
expect(mockDataSource.find).toHaveBeenCalledWith('product', expect.objectContaining({
70+
$top: 100
71+
}));
72+
});
73+
74+
// Check if items are rendered
75+
// ObjectGallery uses: <h3 ...>{item[titleField]}</h3>
76+
expect(screen.getByText('Product A')).toBeInTheDocument();
77+
expect(screen.getByText('Product B')).toBeInTheDocument();
78+
expect(screen.getByText('Tech')).toBeInTheDocument();
79+
});
80+
81+
it('should handle empty data gracefully', async () => {
82+
mockDataSource.find.mockResolvedValue([]);
83+
84+
const schema = {
85+
objectName: 'product',
86+
viewType: 'gallery',
87+
options: { gallery: {} }
88+
};
89+
90+
await act(async () => {
91+
render(
92+
<SchemaRendererProvider dataSource={mockDataSource}>
93+
<ListView schema={schema as any} dataSource={mockDataSource} />
94+
</SchemaRendererProvider>
95+
);
96+
});
97+
98+
expect(screen.getByText('No items to display')).toBeInTheDocument();
99+
});
100+
101+
it('should use default configured fields if not specified in schema', async () => {
102+
mockDataSource.find.mockResolvedValue([{ name: 'Mystery Item', image: 'test.jpg' }]);
103+
104+
const schema = {
105+
objectName: 'product',
106+
viewType: 'gallery',
107+
// No options provided, defaults should be imageField='image', titleField='name'
108+
};
109+
110+
await act(async () => {
111+
render(
112+
<SchemaRendererProvider dataSource={mockDataSource}>
113+
<ListView schema={schema as any} dataSource={mockDataSource} />
114+
</SchemaRendererProvider>
115+
);
116+
});
117+
118+
expect(screen.getByText('Mystery Item')).toBeInTheDocument();
119+
// Since we didn't provide imageField in schema, ObjectGallery defaults to 'image'
120+
// The img tag should be present
121+
const img = screen.getByRole('img');
122+
expect(img).toHaveAttribute('src', 'test.jpg');
123+
});
124+
125+
it('should show placeholder if image is missing', async () => {
126+
mockDataSource.find.mockResolvedValue([{ name: 'No Image Item' }]); // Missing 'image' field
127+
128+
const schema = {
129+
objectName: 'product',
130+
viewType: 'gallery',
131+
options: {
132+
gallery: {
133+
imageField: 'photo' // Key that doesn't exist
134+
}
135+
}
136+
};
137+
138+
await act(async () => {
139+
render(
140+
<SchemaRendererProvider dataSource={mockDataSource}>
141+
<ListView schema={schema as any} dataSource={mockDataSource} />
142+
</SchemaRendererProvider>
143+
);
144+
});
145+
146+
expect(screen.getByText('No Image Item')).toBeInTheDocument();
147+
// Should verify fallback rendered.
148+
// Logic: if (item[imageField]) render img else render div with initial
149+
expect(screen.queryByRole('img')).toBeNull();
150+
expect(screen.getByText('N')).toBeInTheDocument(); // Initial of 'No Image Item'
151+
});
152+
});
153+

packages/plugin-list/src/ListView.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,12 @@ export const ListView: React.FC<ListViewProps> = ({
315315

316316
{/* View Content */}
317317
<div className="flex-1">
318-
<SchemaRenderer schema={viewComponentSchema} {...props} />
318+
<SchemaRenderer
319+
schema={viewComponentSchema}
320+
{...props}
321+
data={data}
322+
loading={loading}
323+
/>
319324
</div>
320325
</div>
321326
);

0 commit comments

Comments
 (0)