diff --git a/packages/@luke-ui/react/src/box/box.browser.test.tsx b/packages/@luke-ui/react/src/box/box.browser.test.tsx
index 31a7c7d3..2d552e0e 100644
--- a/packages/@luke-ui/react/src/box/box.browser.test.tsx
+++ b/packages/@luke-ui/react/src/box/box.browser.test.tsx
@@ -2,17 +2,15 @@ import { afterEach, expect, test } from 'vite-plus/test';
import { page } from 'vite-plus/test/context';
import { testUniversalConformance } from '../conformance/helpers.js';
import { render } from '../test-utils/render.js';
-import { componentTestRegistration } from './component-test-registration.js';
import { Box } from './index.js';
testUniversalConformance({
+ path: 'box',
getTarget: (result) => {
const target = result.container.firstElementChild;
if (!(target instanceof HTMLElement)) throw new Error('Expected a Box element.');
return target;
},
- name: 'Box',
- registration: componentTestRegistration,
render: (props = {}) => render(Content),
});
diff --git a/packages/@luke-ui/react/src/box/component-test-registration.ts b/packages/@luke-ui/react/src/box/component-test-registration.ts
deleted file mode 100644
index aa260f34..00000000
--- a/packages/@luke-ui/react/src/box/component-test-registration.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: 'universal',
- integrationTripwire: 'none',
- path: 'box',
-});
diff --git a/packages/@luke-ui/react/src/button/button.browser.test.tsx b/packages/@luke-ui/react/src/button/button.browser.test.tsx
index 568fbad8..8b17c8ee 100644
--- a/packages/@luke-ui/react/src/button/button.browser.test.tsx
+++ b/packages/@luke-ui/react/src/button/button.browser.test.tsx
@@ -1,23 +1,21 @@
import { expect } from 'vite-plus/test';
import { testIntegration, testUniversalConformance } from '../conformance/helpers.js';
import { render } from '../test-utils/render.js';
-import { componentTestRegistration } from './component-test-registration.js';
import { Button } from './index.js';
testUniversalConformance({
+ path: 'button',
getTarget: (result) => {
const target = result.locator.getByRole('button').element();
if (!(target instanceof HTMLElement)) throw new Error('Expected a button.');
return target;
},
- name: 'Button',
- registration: componentTestRegistration,
render: (props = {}) => {
return render();
},
});
-testIntegration(componentTestRegistration, 'Button', async () => {
+testIntegration('button', async () => {
let pressed = false;
const { locator, user } = render();
diff --git a/packages/@luke-ui/react/src/button/component-test-registration.ts b/packages/@luke-ui/react/src/button/component-test-registration.ts
deleted file mode 100644
index 0407f93b..00000000
--- a/packages/@luke-ui/react/src/button/component-test-registration.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: 'universal',
- integrationTripwire: 'required',
- path: 'button',
-});
diff --git a/packages/@luke-ui/react/src/checkbox/checkbox.browser.test.tsx b/packages/@luke-ui/react/src/checkbox/checkbox.browser.test.tsx
index 6a6d1767..99cec955 100644
--- a/packages/@luke-ui/react/src/checkbox/checkbox.browser.test.tsx
+++ b/packages/@luke-ui/react/src/checkbox/checkbox.browser.test.tsx
@@ -2,10 +2,10 @@ import { expect, test } from 'vite-plus/test';
import { cdp, page } from 'vite-plus/test/context';
import { testFieldShapedConformance, testIntegration } from '../conformance/helpers.js';
import { render } from '../test-utils/render.js';
-import { componentTestRegistration } from './component-test-registration.js';
import { Checkbox } from './index.js';
testFieldShapedConformance({
+ path: 'checkbox',
assertAssociation: (result) => {
// oxlint-disable-next-line vitest/no-standalone-expect
expect(result.locator.getByRole('checkbox', { name: 'Terms' }).element()).toHaveAccessibleName(
@@ -17,19 +17,12 @@ testFieldShapedConformance({
if (!(control instanceof HTMLElement)) throw new Error('Expected a checkbox control.');
return control;
},
- getTarget: (result) => {
- const target = result.container.querySelector('label');
- if (!(target instanceof HTMLElement)) throw new Error('Expected a checkbox label.');
- return target;
- },
- name: 'Checkbox',
- registration: componentTestRegistration,
render: (props = {}) => {
return render(Terms);
},
});
-testIntegration(componentTestRegistration, 'Checkbox', async () => {
+testIntegration('checkbox', async () => {
const { locator, user } = render(Terms);
const checkbox = locator.getByRole('checkbox', { name: 'Terms' });
diff --git a/packages/@luke-ui/react/src/checkbox/component-test-registration.ts b/packages/@luke-ui/react/src/checkbox/component-test-registration.ts
deleted file mode 100644
index 5474cd16..00000000
--- a/packages/@luke-ui/react/src/checkbox/component-test-registration.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: 'field-shaped',
- integrationTripwire: 'required',
- path: 'checkbox',
-});
diff --git a/packages/@luke-ui/react/src/combobox-field/combobox-field.browser.test.tsx b/packages/@luke-ui/react/src/combobox-field/combobox-field.browser.test.tsx
index ddb13406..00cb11c2 100644
--- a/packages/@luke-ui/react/src/combobox-field/combobox-field.browser.test.tsx
+++ b/packages/@luke-ui/react/src/combobox-field/combobox-field.browser.test.tsx
@@ -9,7 +9,6 @@ import { ComboboxRoot } from '../primitives/combobox/root.js';
import { mockScreenWidth } from '../test-utils/mock-screen-width.js';
import { render } from '../test-utils/render.js';
import { waitForOverlayEnter } from '../test-utils/wait-for-overlay-enter.js';
-import { componentTestRegistration } from './component-test-registration.js';
import { ComboboxField } from './index.js';
type CountryItem = {
@@ -25,6 +24,7 @@ const countryItems: Array = [
const renderCountryItem = (item: CountryItem) => {item.label};
testFieldShapedConformance({
+ path: 'combobox-field',
assertAssociation: (result) => {
// oxlint-disable-next-line vitest/no-standalone-expect
expect(result.locator.getByRole('combobox', { name: 'Country' }).element()).toHaveAttribute(
@@ -44,13 +44,6 @@ testFieldShapedConformance({
if (!(control instanceof HTMLElement)) throw new Error('Expected a combobox input.');
return control;
},
- getTarget: (result) => {
- const target = result.container.firstElementChild;
- if (!(target instanceof HTMLElement)) throw new Error('Expected a combobox root.');
- return target;
- },
- name: 'ComboboxField',
- registration: componentTestRegistration,
render: (props = {}) => {
return render(
@@ -65,7 +58,7 @@ testFieldShapedConformance({
},
});
-testIntegration(componentTestRegistration, 'ComboboxField', async () => {
+testIntegration('combobox-field', async () => {
const { locator, user } = render(
{renderCountryItem}
diff --git a/packages/@luke-ui/react/src/combobox-field/component-test-registration.ts b/packages/@luke-ui/react/src/combobox-field/component-test-registration.ts
deleted file mode 100644
index 60cc8edd..00000000
--- a/packages/@luke-ui/react/src/combobox-field/component-test-registration.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: 'field-shaped',
- integrationTripwire: 'required',
- path: 'combobox-field',
-});
diff --git a/packages/@luke-ui/react/src/conformance/helpers.ts b/packages/@luke-ui/react/src/conformance/helpers.ts
index 1add77e8..49eeadef 100644
--- a/packages/@luke-ui/react/src/conformance/helpers.ts
+++ b/packages/@luke-ui/react/src/conformance/helpers.ts
@@ -1,33 +1,41 @@
import { expect, test } from 'vite-plus/test';
import type { RenderResult } from '../test-utils/render.js';
-import type { ComponentTestRegistration } from './registrations.js';
+import { componentTestManifest } from './manifest.js';
type RenderComponent = (props?: Record) => RenderResult;
type UniversalConformanceOptions = {
- name: string;
- registration: ComponentTestRegistration;
+ path: string;
render: RenderComponent;
getTarget: (result: RenderResult) => HTMLElement;
};
-type FieldConformanceOptions = UniversalConformanceOptions & {
+type FieldConformanceOptions = {
assertName?: (result: RenderResult, control: HTMLElement) => void;
getControl: (result: RenderResult) => HTMLElement;
assertAssociation?: (result: RenderResult) => void;
+ path: string;
+ render: RenderComponent;
};
+function getManifestEntry(path: string) {
+ const entry = componentTestManifest.find((candidate) => candidate.path === path);
+ if (entry == null) throw new Error(`Unknown component test path: ${path}`);
+ return entry;
+}
+
function assertNativeName(_: RenderResult, control: HTMLElement) {
expect(control).toHaveAttribute('name', 'conformance-field');
}
export function testUniversalConformance(options: UniversalConformanceOptions) {
- const { getTarget, name, registration, render } = options;
- if (registration.conformanceTier !== 'universal') {
- throw new Error(`Expected a universal registration for ${registration.path}.`);
+ const { getTarget, path, render } = options;
+ const entry = getManifestEntry(path);
+ if (entry.conformanceTier !== 'universal') {
+ throw new Error(`Expected universal conformance for ${path}.`);
}
- test(`${name} forwards its universal DOM contract`, () => {
+ test(`${entry.name} forwards its universal DOM contract`, () => {
const ref = { current: null as HTMLElement | null };
const result = render({
className: 'conformance-class',
@@ -46,11 +54,12 @@ export function testUniversalConformance(options: UniversalConformanceOptions) {
}
export function testFieldShapedConformance(options: FieldConformanceOptions) {
- const { assertAssociation, assertName, getControl, name, registration, render } = options;
- if (registration.conformanceTier !== 'field-shaped') {
- throw new Error(`Expected a field-shaped registration for ${registration.path}.`);
+ const { assertAssociation, assertName, getControl, path, render } = options;
+ const entry = getManifestEntry(path);
+ if (entry.conformanceTier !== 'field-shaped') {
+ throw new Error(`Expected field-shaped conformance for ${path}.`);
}
- test(`${name} forwards its field contract`, async () => {
+ test(`${entry.name} forwards its field contract`, async () => {
const inputRef = { current: null as HTMLElement | null };
let blurred = false;
const result = render({
@@ -97,7 +106,7 @@ export function testFieldShapedConformance(options: FieldConformanceOptions) {
// React Aria types `inputRef` as a ref object. Luke UI widens it to accept a
// callback so React Hook Form's `field.ref` works without an adapter.
- test(`${name} resolves a callback inputRef to the control`, () => {
+ test(`${entry.name} resolves a callback inputRef to the control`, () => {
const resolved: Array = [];
const result = render({
inputRef: (node: HTMLElement | null) => {
@@ -112,15 +121,12 @@ export function testFieldShapedConformance(options: FieldConformanceOptions) {
});
}
-export function testIntegration(
- registration: ComponentTestRegistration,
- name: string,
- run: () => void | Promise,
-) {
- if (registration.integrationTripwire !== 'required') {
- throw new Error(`Expected an integration registration for ${registration.path}.`);
+export function testIntegration(path: string, run: () => void | Promise) {
+ const entry = getManifestEntry(path);
+ if (entry.integrationTripwire !== 'required') {
+ throw new Error(`Expected an integration tripwire for ${path}.`);
}
- test(`${name} integration`, async () => {
+ test(`${entry.name} integration`, async () => {
expect.hasAssertions();
await run();
});
diff --git a/packages/@luke-ui/react/src/conformance/manifest.test.ts b/packages/@luke-ui/react/src/conformance/manifest.test.ts
index cd36948d..ec889940 100644
--- a/packages/@luke-ui/react/src/conformance/manifest.test.ts
+++ b/packages/@luke-ui/react/src/conformance/manifest.test.ts
@@ -1,6 +1,9 @@
import { existsSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';
+import type { Node } from 'oxc-parser';
+import { parseSync } from 'oxc-parser';
import { expect, test } from 'vite-plus/test';
+import type { ComponentTestManifestEntry } from './manifest.js';
import { componentTestManifest } from './manifest.js';
const sourceRoot = resolve(import.meta.dirname, '..');
@@ -39,6 +42,80 @@ function getExportPaths() {
return paths.sort();
}
+function componentFile(path: string, suffix: 'browser.test.tsx' | 'visual.test.tsx') {
+ const basename = path.split('/').at(-1);
+ if (basename == null) throw new Error(`Invalid component test path: ${path}`);
+ return resolve(sourceRoot, path, `${basename}.${suffix}`);
+}
+
+function hasHelperCall(source: string, helperName: string, path: string): boolean {
+ const parsed = parseSync(`${path}.browser.test.tsx`, source, { lang: 'tsx' });
+ if (parsed.errors.length > 0) {
+ throw new Error(`Could not parse ${path}.browser.test.tsx: ${parsed.errors[0]?.message}`);
+ }
+
+ for (const statement of parsed.program.body) {
+ if (statement.type !== 'ExpressionStatement') continue;
+ const expression = statement.expression;
+ if (expression.type !== 'CallExpression') continue;
+ if (expression.callee.type !== 'Identifier' || expression.callee.name !== helperName) {
+ continue;
+ }
+ if (helperPath(expression.arguments[0], helperName) === path) return true;
+ }
+ return false;
+}
+
+function helperPath(argument: Node | undefined, helperName: string): string | undefined {
+ if (helperName === 'testIntegration') return stringLiteral(argument);
+ if (argument?.type !== 'ObjectExpression') return undefined;
+
+ for (const property of argument.properties) {
+ if (property.type !== 'Property' || property.computed) continue;
+ if (propertyName(property.key) !== 'path') continue;
+ return stringLiteral(property.value);
+ }
+}
+
+function propertyName(node: Node): string | undefined {
+ if (node.type === 'Identifier') return node.name;
+ return stringLiteral(node);
+}
+
+function stringLiteral(node: Node | undefined): string | undefined {
+ if (node?.type === 'Literal' && typeof node.value === 'string') return node.value;
+}
+
+function getBrowserCoverageErrors(
+ manifest: ReadonlyArray,
+ readBrowserSource: (path: string) => string,
+) {
+ const errors: Array = [];
+ for (const entry of manifest) {
+ if (entry.conformanceTier === 'none' && entry.integrationTripwire === 'none') continue;
+ const source = readBrowserSource(entry.path);
+ if (
+ entry.conformanceTier !== 'none' &&
+ !hasHelperCall(
+ source,
+ entry.conformanceTier === 'universal'
+ ? 'testUniversalConformance'
+ : 'testFieldShapedConformance',
+ entry.path,
+ )
+ ) {
+ errors.push(`${entry.path} must invoke its ${entry.conformanceTier} conformance helper.`);
+ }
+ if (
+ entry.integrationTripwire === 'required' &&
+ !hasHelperCall(source, 'testIntegration', entry.path)
+ ) {
+ errors.push(`${entry.path} must invoke its integration tripwire.`);
+ }
+ }
+ return errors;
+}
+
test('covers every public component entrypoint exactly once', () => {
const paths = componentTestManifest.map((entry) => entry.path);
@@ -56,3 +133,75 @@ test('declares every conformance dimension explicitly', () => {
expect(entry.visualApplicability).toBeTypeOf('string');
}
});
+
+test('browser tests invoke the helpers required by their manifest entry', () => {
+ expect(
+ getBrowserCoverageErrors(componentTestManifest, (path) => {
+ return readFileSync(componentFile(path, 'browser.test.tsx'), 'utf8');
+ }),
+ ).toEqual([]);
+});
+
+test('visual fixtures match their manifest entries', () => {
+ for (const entry of componentTestManifest) {
+ expect(existsSync(componentFile(entry.path, 'visual.test.tsx'))).toBe(
+ entry.visualApplicability === 'applicable',
+ );
+ }
+});
+
+test('rejects helper calls for another manifest path and source lookalikes', () => {
+ const [button] = componentTestManifest.filter((entry) => entry.path === 'button');
+ if (button == null) throw new Error('Expected the Button manifest entry.');
+
+ const wrongPathSource = `
+ // testUniversalConformance({ path: 'button' });
+ const description = "testIntegration('button', async () => {})";
+ const fake = \`
+ testUniversalConformance({ path: 'button' });
+ testIntegration('button', async () => {});
+ \`;
+ testUniversalConformance({ path: 'link' });
+ testIntegration('link', async () => {});
+ `;
+ expect(getBrowserCoverageErrors([button], () => wrongPathSource)).toEqual([
+ 'button must invoke its universal conformance helper.',
+ 'button must invoke its integration tripwire.',
+ ]);
+});
+
+test('accepts a conformance helper when path is not the first property', () => {
+ const [button] = componentTestManifest.filter((entry) => entry.path === 'button');
+ if (button == null) throw new Error('Expected the Button manifest entry.');
+
+ const source = `
+ testUniversalConformance({
+ render: () => render(),
+ path: 'button',
+ getTarget: (result) => result.locator.getByRole('button').element(),
+ });
+ testIntegration('button', async () => {});
+ `;
+ expect(getBrowserCoverageErrors([button], () => source)).toEqual([]);
+});
+
+test('accepts the generated helper shape', () => {
+ const [button] = componentTestManifest.filter((entry) => entry.path === 'button');
+ if (button == null) throw new Error('Expected the Button manifest entry.');
+
+ const source = `
+ testUniversalConformance({
+ path: 'button',
+ getTarget: (result) => {
+ const target = result.locator.getByRole('button').element();
+ if (!(target instanceof HTMLElement)) throw new Error('Expected a button.');
+ return target;
+ },
+ render: (props = {}) => {
+ return render();
+ },
+ });
+ testIntegration('button', async () => {});
+ `;
+ expect(getBrowserCoverageErrors([button], () => source)).toEqual([]);
+});
diff --git a/packages/@luke-ui/react/src/conformance/registrations.browser.test.tsx b/packages/@luke-ui/react/src/conformance/registrations.browser.test.tsx
deleted file mode 100644
index f339261c..00000000
--- a/packages/@luke-ui/react/src/conformance/registrations.browser.test.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { expect, test } from 'vite-plus/test';
-import { componentTestManifest } from './manifest.js';
-import type { ComponentTestRegistration } from './registrations.js';
-
-const registrationModules = import.meta.glob<{
- componentTestRegistration?: ComponentTestRegistration;
-}>('../*/component-test-registration.ts', { eager: true });
-const browserTestModules = import.meta.glob('../*/**/*.browser.test.tsx');
-
-test('registered component contracts match the manifest', () => {
- const expected = componentTestManifest
- .filter((entry) => entry.conformanceTier !== 'none' || entry.integrationTripwire !== 'none')
- .map(({ path, conformanceTier, integrationTripwire }) => ({
- conformanceTier,
- integrationTripwire,
- path,
- }))
- .sort((left, right) => left.path.localeCompare(right.path));
-
- const registrations = Object.values(registrationModules)
- .map((module) => module.componentTestRegistration)
- .filter((registration): registration is ComponentTestRegistration => registration != null)
- .sort((left, right) => left.path.localeCompare(right.path));
-
- expect(registrations).toEqual(expected);
- for (const registration of registrations) {
- const componentName = registration.path.split('/').at(-1);
- if (componentName == null) throw new Error(`Invalid component test path: ${registration.path}`);
- const testFile = `../${registration.path}/${componentName}.browser.test.tsx`;
- expect(browserTestModules).toHaveProperty(testFile);
- }
-});
diff --git a/packages/@luke-ui/react/src/conformance/registrations.ts b/packages/@luke-ui/react/src/conformance/registrations.ts
deleted file mode 100644
index 38c9a4e6..00000000
--- a/packages/@luke-ui/react/src/conformance/registrations.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { ComponentTestManifestEntry } from './manifest.js';
-import { componentTestManifest } from './manifest.js';
-
-export type ComponentTestRegistration = Pick<
- ComponentTestManifestEntry,
- 'path' | 'conformanceTier' | 'integrationTripwire'
->;
-
-export function defineComponentTestRegistration(registration: ComponentTestRegistration) {
- const manifestEntry = componentTestManifest.find((entry) => entry.path === registration.path);
- if (manifestEntry == null) throw new Error(`Unknown component test path: ${registration.path}`);
- if (
- manifestEntry.conformanceTier !== registration.conformanceTier ||
- manifestEntry.integrationTripwire !== registration.integrationTripwire
- ) {
- throw new Error(
- `Component test registration does not match the manifest: ${registration.path}`,
- );
- }
-
- return registration;
-}
diff --git a/packages/@luke-ui/react/src/icon-button/component-test-registration.ts b/packages/@luke-ui/react/src/icon-button/component-test-registration.ts
deleted file mode 100644
index f0b58b20..00000000
--- a/packages/@luke-ui/react/src/icon-button/component-test-registration.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: 'universal',
- integrationTripwire: 'required',
- path: 'icon-button',
-});
diff --git a/packages/@luke-ui/react/src/icon-button/icon-button.browser.test.tsx b/packages/@luke-ui/react/src/icon-button/icon-button.browser.test.tsx
index c6921dce..64dd9e6a 100644
--- a/packages/@luke-ui/react/src/icon-button/icon-button.browser.test.tsx
+++ b/packages/@luke-ui/react/src/icon-button/icon-button.browser.test.tsx
@@ -1,23 +1,21 @@
import { expect } from 'vite-plus/test';
import { testIntegration, testUniversalConformance } from '../conformance/helpers.js';
import { render } from '../test-utils/render.js';
-import { componentTestRegistration } from './component-test-registration.js';
import { IconButton } from './index.js';
testUniversalConformance({
+ path: 'icon-button',
getTarget: (result) => {
const target = result.locator.getByRole('button', { name: 'Add' }).element();
if (!(target instanceof HTMLElement)) throw new Error('Expected an icon button.');
return target;
},
- name: 'IconButton',
- registration: componentTestRegistration,
render: (props = {}) => {
return render();
},
});
-testIntegration(componentTestRegistration, 'IconButton', async () => {
+testIntegration('icon-button', async () => {
let pressed = false;
const { locator, user } = render(
(pressed = true)} />,
diff --git a/packages/@luke-ui/react/src/link/component-test-registration.ts b/packages/@luke-ui/react/src/link/component-test-registration.ts
deleted file mode 100644
index 850a5485..00000000
--- a/packages/@luke-ui/react/src/link/component-test-registration.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: 'universal',
- integrationTripwire: 'required',
- path: 'link',
-});
diff --git a/packages/@luke-ui/react/src/link/link.browser.test.tsx b/packages/@luke-ui/react/src/link/link.browser.test.tsx
index 1b71be36..7f45a1c1 100644
--- a/packages/@luke-ui/react/src/link/link.browser.test.tsx
+++ b/packages/@luke-ui/react/src/link/link.browser.test.tsx
@@ -1,17 +1,15 @@
import { expect } from 'vite-plus/test';
import { testIntegration, testUniversalConformance } from '../conformance/helpers.js';
import { render } from '../test-utils/render.js';
-import { componentTestRegistration } from './component-test-registration.js';
import { Link } from './index.js';
testUniversalConformance({
+ path: 'link',
getTarget: (result) => {
const target = result.locator.getByRole('link', { name: 'Settings' }).element();
if (!(target instanceof HTMLElement)) throw new Error('Expected a link.');
return target;
},
- name: 'Link',
- registration: componentTestRegistration,
render: (props = {}) => {
return render(
@@ -21,7 +19,7 @@ testUniversalConformance({
},
});
-testIntegration(componentTestRegistration, 'Link', async () => {
+testIntegration('link', async () => {
let pressed = false;
const { locator, user } = render( (pressed = true)}>Settings);
diff --git a/packages/@luke-ui/react/src/text-field/component-test-registration.ts b/packages/@luke-ui/react/src/text-field/component-test-registration.ts
deleted file mode 100644
index 199be1ac..00000000
--- a/packages/@luke-ui/react/src/text-field/component-test-registration.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: 'field-shaped',
- integrationTripwire: 'required',
- path: 'text-field',
-});
diff --git a/packages/@luke-ui/react/src/text-field/text-field.browser.test.tsx b/packages/@luke-ui/react/src/text-field/text-field.browser.test.tsx
index 56a8279c..773b473a 100644
--- a/packages/@luke-ui/react/src/text-field/text-field.browser.test.tsx
+++ b/packages/@luke-ui/react/src/text-field/text-field.browser.test.tsx
@@ -10,10 +10,10 @@ import {
} from '../primitives/input-group/index.js';
import { inputGroupRecipe } from '../primitives/input-group/recipe.css.js';
import { render } from '../test-utils/render.js';
-import { componentTestRegistration } from './component-test-registration.js';
import { TextField } from './index.js';
testFieldShapedConformance({
+ path: 'text-field',
assertAssociation: (result) => {
const input = result.locator.getByRole('textbox', { name: 'Name' }).element();
// oxlint-disable-next-line vitest/no-standalone-expect
@@ -24,19 +24,12 @@ testFieldShapedConformance({
if (!(control instanceof HTMLElement)) throw new Error('Expected a text input.');
return control;
},
- getTarget: (result) => {
- const target = result.container.firstElementChild;
- if (!(target instanceof HTMLElement)) throw new Error('Expected a text-field root.');
- return target;
- },
- name: 'TextField',
- registration: componentTestRegistration,
render: (props = {}) => {
return render();
},
});
-testIntegration(componentTestRegistration, 'TextField', async () => {
+testIntegration('text-field', async () => {
let value = '';
const { locator, user } = render( (value = next)} />);
const input = locator.getByRole('textbox', { name: 'Name' });
diff --git a/packages/turbo-generators/src/component-creation-plan.test.ts b/packages/turbo-generators/src/component-creation-plan.test.ts
index 0da0846c..e5e3b5e0 100644
--- a/packages/turbo-generators/src/component-creation-plan.test.ts
+++ b/packages/turbo-generators/src/component-creation-plan.test.ts
@@ -35,7 +35,6 @@ describe('createComponentPlan', () => {
expect(plan.files.map((file) => file.path).sort()).toEqual([
'apps/docs/content/docs/components/feedback/status-badge.mdx',
'apps/docs/src/examples/status-badge/basic.tsx',
- 'packages/@luke-ui/react/src/status-badge/component-test-registration.ts',
'packages/@luke-ui/react/src/status-badge/index.ts',
'packages/@luke-ui/react/src/status-badge/recipe.css.ts',
'packages/@luke-ui/react/src/status-badge/status-badge.browser.test.tsx',
@@ -77,7 +76,7 @@ describe('createComponentPlan', () => {
);
});
- it('scaffolds field-shaped conformance registrations', () => {
+ it('scaffolds field-shaped conformance coverage without a universal target', () => {
const plan = createComponentPlan({
conformanceTier: 'field-shaped',
docsGroup: 'forms',
@@ -87,9 +86,13 @@ describe('createComponentPlan', () => {
expect(plan.textFileInserts?.[0]?.lines).toEqual([
"\t['DateField', 'date-field', 'field-shaped', 'none', 'applicable'],",
]);
- expect(
- plan.files.find((file) => file.path.endsWith('/date-field.browser.test.tsx'))?.contents,
- ).toContain('testFieldShapedConformance');
+ const browserTest = plan.files.find((file) =>
+ file.path.endsWith('/date-field.browser.test.tsx'),
+ )?.contents;
+ expect(browserTest).toContain('testFieldShapedConformance');
+ expect(browserTest).toContain("path: 'date-field'");
+ expect(browserTest).not.toContain('getTarget');
+ expect(browserTest).not.toContain("name: 'DateField'");
});
it('scaffolds integration tripwire coverage when requested', () => {
@@ -104,7 +107,7 @@ describe('createComponentPlan', () => {
]);
expect(
plan.files.find((file) => file.path.endsWith('/action-chip.browser.test.tsx'))?.contents,
- ).toContain('testIntegration');
+ ).toContain("testIntegration('action-chip', async");
});
it('omits visual coverage when it does not apply', () => {
diff --git a/packages/turbo-generators/src/component-creation-plan.ts b/packages/turbo-generators/src/component-creation-plan.ts
index ad346011..3c68728b 100644
--- a/packages/turbo-generators/src/component-creation-plan.ts
+++ b/packages/turbo-generators/src/component-creation-plan.ts
@@ -107,17 +107,6 @@ export function createComponentPlan(input: CreateComponentInput): ComponentCreat
},
];
- if (conformanceTier !== 'none' || integrationTripwire === 'required') {
- files.push({
- contents: renderComponentTestRegistration({
- conformanceTier,
- integrationTripwire,
- name,
- }),
- path: `packages/@luke-ui/react/src/${name}/component-test-registration.ts`,
- });
- }
-
if (input.visualCoverage !== false) {
files.push({
contents: renderVisualTest({ name, pascalName }),
@@ -302,9 +291,6 @@ function renderComponentTest(input: {
? [`import { ${helperImports.join(', ')} } from '../conformance/helpers.js';`]
: []),
"import { render } from '../test-utils/render.js';",
- ...(input.conformanceTier !== 'none' || input.integrationTripwire === 'required'
- ? ["import { componentTestRegistration } from './component-test-registration.js';"]
- : []),
`import { ${input.pascalName} } from './index.js';`,
];
@@ -312,24 +298,22 @@ function renderComponentTest(input: {
const contract =
input.conformanceTier === 'universal'
? `testUniversalConformance({
+ path: '${input.name}',
getTarget: (result) => {
const target = result.container.firstElementChild;
if (!(target instanceof HTMLElement)) throw new Error('Expected ${input.pascalName} element.');
return target;
},
- name: '${input.pascalName}',
- registration: componentTestRegistration,
render: (props = {}) => ${renderComponent},
});`
: input.conformanceTier === 'field-shaped'
? `testFieldShapedConformance({
+ path: '${input.name}',
getControl: (result) => {
const control = result.container.querySelector('[name="conformance-field"]');
if (!(control instanceof HTMLElement)) throw new Error('Expected a native field control.');
return control;
},
- name: '${input.pascalName}',
- registration: componentTestRegistration,
render: (props = {}) => ${renderComponent},
});`
: `test('${input.pascalName} renders its root element', () => {
@@ -340,7 +324,7 @@ function renderComponentTest(input: {
const integration =
input.integrationTripwire === 'required'
? `
-testIntegration(componentTestRegistration, '${input.pascalName}', async () => {
+testIntegration('${input.name}', async () => {
let clicked = false;
const { locator, user } = render(
<${input.pascalName} onClick={() => (clicked = true)}>Content${input.pascalName}>,
@@ -357,21 +341,6 @@ ${contract}${integration}
`;
}
-function renderComponentTestRegistration(input: {
- conformanceTier: ConformanceTier;
- integrationTripwire: 'none' | 'required';
- name: string;
-}): string {
- return `import { defineComponentTestRegistration } from '../conformance/registrations.js';
-
-export const componentTestRegistration = defineComponentTestRegistration({
- conformanceTier: '${input.conformanceTier}',
- integrationTripwire: '${input.integrationTripwire}',
- path: '${input.name}',
-});
-`;
-}
-
function renderVisualTest(input: { name: string; pascalName: string }): string {
return `import { test } from 'vite-plus/test';
import { render } from '../test-utils/render.js';