import { describe, it, expect } from 'vitest' import { generate } from '../generate.js' import type { ScaffoldComponentInput, PageSpecMin } from '../types.js' /** * Typographic-scale parity on the pages scaffold-component emits (client * defect 2026-08-25, extended): labels, options and buttons read at text-sm, * so every surface the user TYPES into must carry text-sm too — the theme * sets no font-size on html/body, so a classless field inherits the 16px * browser default and reads bigger than its own label. The primitives' half * of this contract lives in scaffold-ui-primitives/__tests__/font-scale.test.ts. */ const I18N: Record = { 'list.title': 'Commandes', 'list.subtitle': 'x', 'list.search': 'x', 'list.loading': 'x', 'list.empty': 'x', 'filters.note': 'Note', 'form.title.create': 'x', 'form.title.edit': 'x', } function input(overrides: Partial = {}, ps: Partial = {}): ScaffoldComponentInput { return { module: 'sales', appCode: 'TestV2', entity: 'Order', section: 'orders', views: ['list'], fields: [ { name: 'code', type: 'string', required: true }, { name: 'note', type: 'string', required: false }, ], projectPath: '/web', pageSpec: { screenCode: 'SCR-SALES-ORDERS-LIST-001', module: 'sales', appCode: 'testv2', section: 'orders', entity: 'Order', view: 'list', filePath: 'src/pages/testv2/sales/orders/OrdersListPage.tsx', permission: 'sales.orders.read', actions: [], i18nKeys: { fr: I18N, en: I18N, it: I18N, de: I18N }, needsRefinement: false, specHash: 'f'.repeat(64), ...ps, } as PageSpecMin, ...overrides, } } const pageOf = (i: ScaffoldComponentInput, suffix: string) => generate(i, { warnings: [] }).find((f) => f.path.endsWith(suffix))!.content describe('scaffold-component / font scale — typed surfaces carry text-sm', () => { it('form text inputs type at the chrome scale (same as their labels)', () => { const c = pageOf(input({ views: ['form'] }), 'OrderFormPage.tsx') expect(c).toMatch(/w-full px-3 py-2 text-sm rounded-\[var\(--radius-input/) }) it('the list search box types at the chrome scale', () => { const c = pageOf(input({ routeMode: 'screens' }, { filters: [{ field: 'note', labelKey: 'filters.note', control: 'text' }], } as Partial), 'OrdersListPage.tsx') expect(c).toContain('className="input text-sm w-full pl-10 pr-10"') }) it('legacy client-filtered text inputs carry text-sm too', () => { // routeMode 'integration' (default) + a text filter → the legacy // client-filtered path with its bare `.input` controls. const c = pageOf(input({}, { filters: [{ field: 'note', labelKey: 'filters.note', control: 'text' }], } as Partial), 'OrdersListPage.tsx') expect(c).not.toMatch(/className="input"/) expect(c).toMatch(/className="input text-sm"/) }) })