Skip to content

Commit 7f5d9f6

Browse files
Copilothotlong
andcommitted
Create MSW ObjectForm example with comprehensive test suite
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 69dd24b commit 7f5d9f6

19 files changed

Lines changed: 1520 additions & 0 deletions
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
25+
26+
# MSW
27+
public/mockServiceWorker.js

examples/msw-object-form/README.md

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
# MSW ObjectForm Example
2+
3+
This example demonstrates a complete **ObjectForm** integration with **Mock Service Worker (MSW)** for testing and development. It runs a real ObjectStack Runtime in the browser using an in-memory driver, allowing you to develop and test forms without a backend server.
4+
5+
## 🏗️ Architecture
6+
7+
This example uses the same architecture as the [msw-react-crud](https://github.com/objectstack-ai/spec/tree/main/examples/msw-react-crud) reference implementation:
8+
9+
```mermaid
10+
graph TD
11+
ObjectForm["ObjectForm Component"] -->|Data Operations| DataSource["ObjectStackDataSource"]
12+
DataSource -->|REST API Calls| Network["Browser Network Layer"]
13+
Network -->|Intercepted by| SW["Service Worker <br/> MockServiceWorker"]
14+
SW -->|Delegates to| Kernel["ObjectStack Kernel <br/> (Running in Browser)"]
15+
Kernel -->|Uses| MemoryDriver["In-Memory Driver"]
16+
17+
Kernel -.->|Reads| Config["objectstack.config.ts <br/> Schema Definitions"]
18+
```
19+
20+
## 🎯 Key Features
21+
22+
- **ObjectForm Component**: Smart form component that auto-generates forms from ObjectStack schemas
23+
- **MSW Integration**: Complete ObjectStack runtime running in the browser via Service Worker
24+
- **Full CRUD Operations**: Create, Read, Update, Delete contacts with validation
25+
- **Real Logic**: Schema validation, defaults, and field types enforced by ObjectStack Kernel
26+
- **Comprehensive Tests**: Test suite covering all form operations and field types
27+
- **Zero Backend**: Develop and test frontend forms before backend exists
28+
29+
## 📦 What's Inside
30+
31+
### Core Files
32+
33+
- **`src/App.tsx`** - Main application component with ObjectForm integration
34+
- **`src/components/ContactList.tsx`** - Contact list component with edit/delete
35+
- **`src/dataSource.ts`** - ObjectStack DataSource adapter for ObjectForm
36+
- **`src/mocks/browser.ts`** - MSW setup with ObjectStack Kernel
37+
- **`objectstack.config.ts`** - Contact object schema definition
38+
39+
### Test Files
40+
41+
- **`src/__tests__/ObjectForm.test.tsx`** - Comprehensive test suite covering:
42+
- Create mode with field validation
43+
- Edit mode with data loading and updates
44+
- View mode (read-only)
45+
- Different field types (text, email, phone, checkbox, number, textarea)
46+
- Form callbacks (onSuccess, onCancel, onError)
47+
- Data persistence in MSW memory
48+
49+
## 🚀 Getting Started
50+
51+
### Installation
52+
53+
```bash
54+
# Install dependencies (from repository root)
55+
pnpm install
56+
57+
# Navigate to example directory
58+
cd examples/msw-object-form
59+
```
60+
61+
### Development
62+
63+
```bash
64+
# Start development server
65+
pnpm dev
66+
```
67+
68+
Open [http://localhost:5173](http://localhost:5173) to view the app. You can:
69+
- Create new contacts using the form
70+
- Edit existing contacts
71+
- Delete contacts
72+
- See data persist in browser memory
73+
74+
### Testing
75+
76+
```bash
77+
# Run tests
78+
pnpm test
79+
80+
# Run tests in watch mode
81+
pnpm test:watch
82+
83+
# Run tests with UI
84+
pnpm test:ui
85+
```
86+
87+
### Build
88+
89+
```bash
90+
# Build for production
91+
pnpm build
92+
93+
# Preview production build
94+
pnpm preview
95+
```
96+
97+
## 📝 Usage Example
98+
99+
### Basic ObjectForm Integration
100+
101+
```tsx
102+
import { ObjectForm } from '@object-ui/plugin-form';
103+
import { ObjectStackDataSource } from './dataSource';
104+
import { ObjectStackClient } from '@objectstack/client';
105+
106+
// Initialize client and data source
107+
const client = new ObjectStackClient({ baseUrl: '' });
108+
await client.connect();
109+
const dataSource = new ObjectStackDataSource(client);
110+
111+
// Render ObjectForm
112+
<ObjectForm
113+
schema={{
114+
type: 'object-form',
115+
objectName: 'contact',
116+
mode: 'create', // or 'edit' or 'view'
117+
fields: ['name', 'email', 'phone', 'company'],
118+
layout: 'vertical',
119+
onSuccess: (data) => console.log('Created:', data),
120+
}}
121+
dataSource={dataSource}
122+
/>
123+
```
124+
125+
### Testing with MSW
126+
127+
```tsx
128+
import { startMockServer } from './mocks/browser';
129+
import { ObjectStackClient } from '@objectstack/client';
130+
131+
// Start MSW before tests
132+
beforeAll(async () => {
133+
await startMockServer();
134+
135+
client = new ObjectStackClient({ baseUrl: '' });
136+
await client.connect();
137+
138+
dataSource = new ObjectStackDataSource(client);
139+
});
140+
141+
// Test form creation
142+
it('should create a contact', async () => {
143+
render(
144+
<ObjectForm
145+
schema={{
146+
type: 'object-form',
147+
objectName: 'contact',
148+
mode: 'create',
149+
fields: ['name', 'email'],
150+
onSuccess,
151+
}}
152+
dataSource={dataSource}
153+
/>
154+
);
155+
156+
await user.type(screen.getByLabelText(/name/i), 'Test User');
157+
await user.type(screen.getByLabelText(/email/i), 'test@example.com');
158+
await user.click(screen.getByRole('button', { name: /create/i }));
159+
160+
await waitFor(() => {
161+
expect(onSuccess).toHaveBeenCalled();
162+
});
163+
});
164+
```
165+
166+
## 🔧 Customization
167+
168+
### Modify the Schema
169+
170+
Edit `objectstack.config.ts` to add/remove fields or change object properties:
171+
172+
```typescript
173+
export const ContactObject = {
174+
name: 'contact',
175+
fields: {
176+
// Add your custom fields here
177+
custom_field: {
178+
name: 'custom_field',
179+
label: 'Custom Field',
180+
type: 'text'
181+
},
182+
}
183+
};
184+
```
185+
186+
### Add Custom Validation
187+
188+
Implement custom validation in the ObjectForm schema:
189+
190+
```tsx
191+
<ObjectForm
192+
schema={{
193+
customFields: [
194+
{
195+
name: 'email',
196+
label: 'Email',
197+
type: 'email',
198+
validation: {
199+
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
200+
message: 'Invalid email format'
201+
}
202+
}
203+
]
204+
}}
205+
/>
206+
```
207+
208+
## 📚 Learn More
209+
210+
- [ObjectForm Documentation](../../packages/plugin-form/README.md)
211+
- [ObjectStack Documentation](https://objectstack.dev)
212+
- [MSW Documentation](https://mswjs.io/)
213+
- [Reference Example](https://github.com/objectstack-ai/spec/tree/main/examples/msw-react-crud)
214+
215+
## 🧪 Test Coverage
216+
217+
The test suite covers:
218+
219+
✅ Create mode with all field types
220+
✅ Form validation (required fields, field types)
221+
✅ Default values from schema
222+
✅ Edit mode with data loading
223+
✅ Update operations
224+
✅ View mode (read-only)
225+
✅ Error handling
226+
✅ Form callbacks (onSuccess, onCancel, onError)
227+
✅ Data persistence in MSW memory
228+
✅ Various field types (text, email, phone, number, checkbox, textarea)
229+
230+
## 📄 License
231+
232+
MIT © ObjectStack Inc.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>MSW ObjectForm Example - ObjectUI</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>

0 commit comments

Comments
 (0)