feat: schema builder's create flow

This commit is contained in:
Florian Sylvain committed 2026-10-20 00:29:01 +02:00
1 parent f514146fed
commit 083cc9e23e
71 files changed
+7223 -61

No files matched your search

+65
View File
@@ -6515,6 +6515,21 @@ function schemaApi(overrides: Record<string, ApiMock> = {}): Record<string, ApiM
}
}
function schemaIsMobile(page: Page) {
return (page.viewportSize()?.width ?? 0) < 768
}
async function schemaOpenRow(page: Page, label: string) {
await page.locator('[data-field-row]', { hasText: label }).first().click()
}
async function schemaCloseSheet(page: Page) {
if (schemaIsMobile(page)) {
await page.getByRole('button', { name: 'Done' }).click()
await page.getByRole('dialog').waitFor({ state: 'detached' })
}
}
const schemaStates: Record<string, VisualState> = {
Populated: { path: '/schema', api: schemaApi() },
Loading: {
@@ -6536,6 +6551,56 @@ const schemaStates: Record<string, VisualState> = {
}),
},
'Built-in type: read-only view': { path: '/schema/articles', api: schemaApi() },
'New type': { path: '/schema/new', api: schemaApi() },
'Editing an existing type': { path: '/schema/events', skip: 'pending' },
'Locked key: tooltip': { path: '/schema/events', skip: 'pending' },
'Unsaved changes': { path: '/schema/events', skip: 'pending' },
'Field errors': { path: '/schema/events', skip: 'pending' },
'Type-level errors': {
path: '/schema/new',
api: schemaApi(),
steps: async (page) => {
await page.getByPlaceholder('For example, Events').fill('x')
await page.getByRole('button', { name: 'Edit key' }).first().click()
await page.locator('input[name="key"]').fill('e')
await page.getByPlaceholder('For example, Events').fill('')
await schemaOpenRow(page, 'Title')
await page.getByRole('button', { name: 'Remove', exact: true }).click()
await page.getByText('3 problems to fix').first().waitFor()
await page.mouse.move(0, 0)
},
},
'Field key error': { path: '/schema/new', skip: 'pending' },
'Choice list editor': { path: '/schema/events', skip: 'pending' },
'Keyboard reorder': { path: '/schema/events', skip: 'pending' },
'API preview open': { path: '/schema/events', skip: 'pending' },
Saving: { path: '/schema/events', skip: 'pending' },
Saved: { path: '/schema/events', skip: 'pending' },
'Save failed': { path: '/schema/events', skip: 'pending' },
'Key already taken': {
path: '/schema/new',
api: schemaApi({
'POST /v1/content-type': { status: 409, body: 'content_type_key_taken' },
}),
steps: async (page) => {
await page.getByPlaceholder('For example, Events').fill('Events')
await schemaOpenRow(page, 'Title')
await page.getByRole('switch', { name: 'Required' }).click()
await schemaCloseSheet(page)
await page.getByRole('button', { name: 'Add field' }).click()
await page.locator('input[name="label"]').fill('Starts on')
await page.locator('label:has([role="radio"][value="date"])').click()
await schemaCloseSheet(page)
if (!schemaIsMobile(page)) {
await schemaOpenRow(page, 'Title')
}
await page.getByRole('button', { name: 'Save', exact: true }).click()
await page.getByText('is already used by another content type').waitFor()
await page.mouse.move(0, 0)
},
},
'Schema incompatible': { path: '/schema/events', skip: 'pending' },
Offline: { path: '/schema/events', skip: 'pending' },
}
export const visualStates: Record<string, Record<string, VisualState>> = {