@kiwa-test/component 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # `@kiwa-test/component`
2
+
3
+ Component test mock harness for kiwa — 3 unified integrations across Storybook 8, Playwright Component Testing, and Chromatic. One API for story registration + args resolution + play function runner, mount + interact, and visual regression baseline / diff / accept workflow.
4
+
5
+ v0.1 lays the foundation for the v1.16 milestone dogfood apps (design system + form CT + visual regression).
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ pnpm add -D @kiwa-test/component @kiwa-test/quality-metrics
11
+ ```
12
+
13
+ ## Quick start — 3 unified mocks
14
+
15
+ ### Storybook 8 story registry
16
+
17
+ ```ts
18
+ import {
19
+ createStoryRegistry,
20
+ buildButton,
21
+ } from '@kiwa-test/component';
22
+
23
+ const registry = createStoryRegistry();
24
+ registry.register({
25
+ title: 'Components/Button',
26
+ render: buildButton,
27
+ args: { label: 'default' },
28
+ stories: {
29
+ Primary: { args: { variant: 'primary' } },
30
+ Interactive: {
31
+ args: { label: 'Click me' },
32
+ play: async ({ canvasElement, step }) => {
33
+ await step('click the button', async () => {
34
+ const btn = canvasElement.getByRole('button');
35
+ btn.handlers['click']?.[0]?.({ type: 'click', target: btn });
36
+ });
37
+ },
38
+ },
39
+ },
40
+ });
41
+
42
+ const { canvas } = registry.mount('Components/Button', 'Interactive');
43
+ const result = await registry.play('Components/Button', 'Interactive', canvas);
44
+ console.log(result.steps); // [{ label: 'click the button', ok: true }]
45
+ ```
46
+
47
+ Supports `StoryObj.args + play + parameters`, meta / story deep merge, `parameters.chromatic` / `parameters.a11y` passthrough, and a heuristic a11y checker (button-name, image-alt, label rules).
48
+
49
+ ### Playwright Component Testing
50
+
51
+ ```ts
52
+ import {
53
+ createPlaywrightCTMock,
54
+ buildForm,
55
+ } from '@kiwa-test/component';
56
+
57
+ const ct = createPlaywrightCTMock();
58
+ let submitted: Record<string, string> | null = null;
59
+ const form = ct.mount(buildForm, {
60
+ title: 'Signup',
61
+ fields: [
62
+ { id: 'email', label: 'Email', type: 'email', required: true },
63
+ ],
64
+ onSubmit: (data) => {
65
+ submitted = data;
66
+ },
67
+ });
68
+
69
+ // interact via Playwright API surface
70
+ await form.getByRole('textbox').fill('user@example.com');
71
+ await form.getByRole('button').click();
72
+ console.log(submitted); // { email: 'user@example.com' }
73
+ form.unmount();
74
+ ```
75
+
76
+ Supports `mount + getByText + getByRole + click + fill + textContent + count`, framework agnostic, no browser process, deterministic in-memory DOM.
77
+
78
+ ### Chromatic visual regression
79
+
80
+ ```ts
81
+ import {
82
+ createChromaticVisualMock,
83
+ createStoryRegistry,
84
+ buildCard,
85
+ } from '@kiwa-test/component';
86
+
87
+ const chromatic = createChromaticVisualMock();
88
+ const registry = createStoryRegistry();
89
+ registry.register({
90
+ title: 'Card',
91
+ render: buildCard,
92
+ parameters: { chromatic: { viewports: ['mobile', 'desktop'], diffThreshold: 0.01 } },
93
+ stories: { Default: { args: { title: 'Hello', body: 'World' } } },
94
+ });
95
+
96
+ const { canvas, entry } = registry.mount('Card', 'Default');
97
+
98
+ // 1st pass — new baseline captured per viewport
99
+ let diffs = chromatic.captureAll({ entry, canvas });
100
+ console.log(diffs.map((d) => d.status)); // ['new', 'new']
101
+
102
+ // 2nd pass — identical markup → passed
103
+ diffs = chromatic.captureAll({ entry, canvas });
104
+ console.log(diffs.every((d) => d.status === 'passed')); // true
105
+
106
+ // Simulate a design change
107
+ const { canvas: changed, entry: changedEntry } = registry.mount('Card', 'Default', { title: 'Hi' });
108
+ const changedDiffs = chromatic.captureAll({ entry: changedEntry, canvas: changed });
109
+ console.log(changedDiffs[0]?.status); // 'failed'
110
+
111
+ // Approve the design change
112
+ chromatic.review({ storyId: changedEntry.id, viewport: 'mobile', action: 'accept' });
113
+ ```
114
+
115
+ Supports `capture + captureAll + review (accept/reject) + reviewHistory + seedBaseline + reset`, multi viewport, `parameters.chromatic.diffThreshold` and `disable` fields, deterministic SHA-256 hash comparison.
116
+
117
+ ## 5 component fixtures
118
+
119
+ Framework agnostic renderers usable from stories / component tests / visual capture. Cover the five SaaS frontend primitives.
120
+
121
+ | fixture | description |
122
+ |---|---|
123
+ | `buildButton` | text label + click handler + variant class + disabled state |
124
+ | `buildInput` | label + input pair with `for/id` association + change handler |
125
+ | `buildForm` | title + multi-field composition + submit validation |
126
+ | `buildModal` | open/close state + backdrop + close button + escape hooks |
127
+ | `buildCard` | title + body + optional footer + variant class |
128
+
129
+ ```ts
130
+ import { componentFixtures } from '@kiwa-test/component';
131
+
132
+ // batch register every fixture
133
+ const registry = createStoryRegistry();
134
+ for (const [name, render] of Object.entries(componentFixtures)) {
135
+ registry.register({
136
+ title: `Fixtures/${name}`,
137
+ render,
138
+ stories: { Default: {} },
139
+ });
140
+ }
141
+ ```
142
+
143
+ ## Design goals
144
+
145
+ - **1 API for 3 integrations** — the same `MockNode` tree is used for story rendering, Playwright CT mounting, and Chromatic capture.
146
+ - **Framework agnostic** — every component is a pure `(args) => MockNode` function, so React / Vue / Svelte / Solid tests share the harness.
147
+ - **Deterministic** — no jsdom, no browser process, no wall clock (all `now` sources injectable). Hashes and IDs are stable across runs.
148
+ - **Real-vs-mock parity** — API surface deliberately mirrors real Storybook 8 CSF3, Playwright CT `Locator`, and Chromatic baseline / diff / accept workflow, so a single test spec can run against the mock (fast) and a real environment (dogfood).
149
+
150
+ ## Related packages
151
+
152
+ - `@kiwa-test/quality-metrics` — 11-axis release gate that this harness will feed component test results into (Chromatic `status=failed` and a11y violations map to axes).
153
+ - `@kiwa-test/e2e` — Playwright browser-driven end-to-end tests. Complement, not replacement — CT covers component surface, e2e covers page flows.