import { describe, it, expect } from 'vitest';
import { generate } from '../generate.js';
import type { ScaffoldUiPrimitivesInput } from '../types.js';
/**
* Typographic-scale parity (client defect 2026-08-25 — "les cellules d'un
* tableau sont plus grosses que ses en-têtes", extended to every typed
* surface). The UI chrome — labels, dropdown options, buttons (`.btn` in the
* package fixes 0.875rem), table headers — reads at text-sm; the theme sets
* NO font-size on html/body, so anything without an explicit class inherits
* the 16px browser default. Every data cell and every surface the user types
* into must therefore carry text-sm explicitly, matching its own label and
* its own suggestion list. (The iOS focus-zoom fallback for touch lives in
* scaffold-theme: `@media (pointer: coarse)` bumps text-sm fields to 1rem.)
*/
function files() {
const input: ScaffoldUiPrimitivesInput = { projectPath: '/tmp/web', appCode: 'crm', force: false };
return generate(input);
}
const contentOf = (name: string) => {
const f = files().find((x) => x.path === `src/components/ui/${name}`);
expect(f, `missing ${name}`).toBeDefined();
return f!.content;
};
describe('scaffold-ui-primitives / font scale — DataTable header/cell parity', () => {
it('column
and BOTH | emissions (data + skeleton) share text-sm', () => {
const c = contentOf('DataTable.tsx');
// Header keeps its scale…
expect(c).toMatch(/text-sm font-medium text-\[var\(--table-header-text\)\]/);
// …and the two cell templates now carry the SAME scale (data + skeleton):
const cellSites = c.match(/\$\{cellPadding\} text-sm/g) ?? [];
expect(cellSites.length).toBeGreaterThanOrEqual(2);
// No column | template is left without a size (the historical defect:
// cells inherited the 16px body default under 14px headers).
expect(c).not.toMatch(/\$\{cellPadding\} \$\{getResponsiveHideClass/);
expect(c).not.toMatch(/\$\{cellPadding\} text-\$\{getEffectiveAlign/);
});
it('the built-in search box types at the chrome scale', () => {
const c = contentOf('DataTable.tsx');
expect(c).toContain('className="input text-sm w-full pl-10 pr-10"');
});
});
describe('scaffold-ui-primitives / font scale — typed surfaces match their labels', () => {
const cases: Array<[file: string, anchor: RegExp]> = [
// Each primitive's input/trigger carries text-sm — the same scale as its
// own text-sm label above and its own text-sm option list below.
['EntityLookup.tsx', /pl-3 pr-16 py-2 text-sm rounded-\[var\(--radius-input/],
['DateInput.tsx', /pl-3 pr-16 py-2 text-sm rounded-\[var\(--radius-input/],
['EnumSelect.tsx', /pl-3 pr-9 py-2 text-sm text-left rounded-\[var\(--radius-input/],
['MultiSelect.tsx', /pl-2 pr-9 py-1\.5 text-sm cursor-pointer rounded-\[var\(--radius-input/],
['Textarea.tsx', /px-3 py-2 text-sm resize-none/],
];
for (const [file, anchor] of cases) {
it(`${file} input/trigger carries text-sm`, () => {
expect(contentOf(file)).toMatch(anchor);
});
}
});
|