Skip to content

Commit 52e6f27

Browse files
committed
feat: enhance ContainerRenderer and SchemaRenderer to support properties wrapper and add system integration test for help page rendering
1 parent 4881f0c commit 52e6f27

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
import { describe, it, expect, vi, beforeAll } from 'vitest';
3+
import { render, screen, waitFor } from '@testing-library/react';
4+
import { MemoryRouter, Routes, Route } from 'react-router-dom';
5+
import React from 'react';
6+
import appConfig from '../../objectstack.config';
7+
8+
// -----------------------------------------------------------------------------
9+
// SYSTEM INTEGRATION TEST
10+
// -----------------------------------------------------------------------------
11+
// This test simulates the exact browser runtime environment of the Console App.
12+
// It verifies that the configuration loaded from 'kitchen-sink' is correctly
13+
// processed by the router and the 'PageRenderer' component we just fixed.
14+
// -----------------------------------------------------------------------------
15+
16+
// 1. Mock the DataSource to avoid real network calls
17+
class MockDataSource {
18+
async retrieve() { return {}; }
19+
async find() { return []; }
20+
}
21+
const mockClient = {
22+
connect: vi.fn().mockResolvedValue(true)
23+
};
24+
25+
// 2. Mock App Dependencies that are outside the scope of UI rendering
26+
vi.mock('@objectstack/client', () => ({
27+
ObjectStackClient: vi.fn(() => mockClient)
28+
}));
29+
vi.mock('../dataSource', () => ({
30+
ObjectStackDataSource: vi.fn(() => new MockDataSource())
31+
}));
32+
33+
// 3. Import Components under test
34+
import { PageView } from '../components/PageView';
35+
36+
describe('System Integration: Help Page Rendering', () => {
37+
38+
it('should successfully locate and render the "help_page" from kitchen-sink config', async () => {
39+
// A. Verify Configuration Integrity
40+
const helpPage = appConfig.pages?.find((p: any) => p.name === 'help_page');
41+
expect(helpPage).toBeDefined();
42+
43+
// B. Simulate Browser Navigation
44+
// IMPORTANT: We must setup the Route path so :pageName param is captured
45+
render(
46+
<MemoryRouter initialEntries={['/page/help_page']}>
47+
<Routes>
48+
<Route path="/page/:pageName" element={<PageView />} />
49+
</Routes>
50+
</MemoryRouter>
51+
);
52+
53+
// C. Verify Visual Output
54+
await waitFor(() => {
55+
expect(screen.getByText(/Application Guide/i)).toBeInTheDocument();
56+
});
57+
58+
expect(screen.getByText(/Welcome to the ObjectStack Console/i)).toBeInTheDocument();
59+
expect(screen.getByText(/Dynamic Object CRUD/i)).toBeInTheDocument();
60+
});
61+
});

packages/components/src/renderers/layout/container.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,29 @@ const ContainerRenderer = forwardRef<HTMLDivElement, { schema: ContainerSchema;
5252
className
5353
);
5454

55-
// Extract designer-related props
55+
// Extract designer-related properties
5656
const {
5757
'data-obj-id': dataObjId,
5858
'data-obj-type': dataObjType,
5959
style,
60+
properties, // Handle properties wrapper if it exists (legacy/config fix)
6061
...containerProps
6162
} = props;
6263

64+
// Merge properties if they exist (handling the properties wrapper issue)
65+
const mergedProps = { ...containerProps, ...properties };
66+
6367
return (
6468
<div
6569
ref={ref}
6670
className={containerClass}
67-
{...containerProps}
71+
{...mergedProps}
6872
// Apply designer props
6973
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
7074
>
7175
{schema.children && renderChildren(schema.children)}
76+
{/* Support properties.children which comes from objectstack.config wrapper */}
77+
{properties?.children && renderChildren(properties.children)}
7278
</div>
7379
);
7480
}

packages/react/src/SchemaRenderer.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,15 @@ export const SchemaRenderer = forwardRef<any, { schema: SchemaNode } & Record<st
1919
if (!schema || typeof schema === 'string') return schema;
2020

2121
const evaluator = new ExpressionEvaluator({ data: dataSource });
22+
// Shallow copy
2223
const newSchema = { ...schema };
2324

25+
// COMPAT: Hoist 'properties' up to schema level
26+
// This allows support for strict configs that wrap all props in 'properties'
27+
if (newSchema.properties) {
28+
Object.assign(newSchema, newSchema.properties);
29+
}
30+
2431
// Evaluate 'content' (common in Text, Button)
2532
if (typeof newSchema.content === 'string') {
2633
newSchema.content = evaluator.evaluate(newSchema.content);

0 commit comments

Comments
 (0)