@kiwa-test/component 0.3.0 → 0.4.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/dist/index.cjs +172 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -4
- package/dist/index.d.ts +55 -4
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -539,8 +539,8 @@ declare const componentFixtures: Record<string, ComponentRender<Record<string, u
|
|
|
539
539
|
* any of those runtimes, so the same axis can be replayed against each target.
|
|
540
540
|
*/
|
|
541
541
|
type ComponentTarget = 'storybook8' | 'playwright-ct' | 'chromatic';
|
|
542
|
-
type ComponentAxis = 'rsc-harness' | 'streaming-ssr' | 'view-transitions' | 'form-action-advanced';
|
|
543
|
-
type NeutralEventName = 'rsc.render_started' | 'rsc.suspense_boundary' | 'rsc.html_chunk_streamed' | 'rsc.render_completed' | 'ssr.suspense_pending' | 'ssr.error_boundary_captured' | 'ssr.progressive_hydration_started' | 'ssr.selective_hydration_completed' | 'transition.element_started' | 'transition.element_finished' | 'transition.document_started' | 'transition.animation_asserted' | 'form.status_pending' | 'form.optimistic_applied' | 'form.progressive_enhanced' | 'form.action_resolved';
|
|
542
|
+
type ComponentAxis = 'rsc-harness' | 'streaming-ssr' | 'view-transitions' | 'form-action-advanced' | 'react-19-actions' | 'islands-architecture';
|
|
543
|
+
type NeutralEventName = 'rsc.render_started' | 'rsc.suspense_boundary' | 'rsc.html_chunk_streamed' | 'rsc.render_completed' | 'ssr.suspense_pending' | 'ssr.error_boundary_captured' | 'ssr.progressive_hydration_started' | 'ssr.selective_hydration_completed' | 'transition.element_started' | 'transition.element_finished' | 'transition.document_started' | 'transition.animation_asserted' | 'form.status_pending' | 'form.optimistic_applied' | 'form.progressive_enhanced' | 'form.action_resolved' | 'action.state_initialized' | 'action.transition_pending' | 'action.optimistic_committed' | 'action.resolved' | 'islands.registered' | 'islands.hydration_started' | 'islands.interactive_ready' | 'islands.static_boundary_asserted';
|
|
544
544
|
interface AxisStep<TState extends string> {
|
|
545
545
|
neutralEvent: NeutralEventName;
|
|
546
546
|
providerEvent: string;
|
|
@@ -645,7 +645,7 @@ declare function startFormActionSession<TForm extends Record<string, unknown>>(i
|
|
|
645
645
|
initial: TForm;
|
|
646
646
|
}): FormActionSession<TForm>;
|
|
647
647
|
declare function markFormStatusPending<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, submitter: string): AxisStep<FormActionState>;
|
|
648
|
-
declare function applyOptimisticUpdate<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, patch: Partial<TForm>): AxisStep<FormActionState>;
|
|
648
|
+
declare function applyOptimisticUpdate$1<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, patch: Partial<TForm>): AxisStep<FormActionState>;
|
|
649
649
|
declare function enableProgressiveEnhancement<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, input: {
|
|
650
650
|
method?: 'post' | 'get';
|
|
651
651
|
actionUrl: string;
|
|
@@ -667,6 +667,57 @@ interface FidelityCoverage {
|
|
|
667
667
|
declare const COMPONENT_AXIS_TO_EVENTS: Record<ComponentAxis, NeutralEventName[]>;
|
|
668
668
|
declare function collectFidelityCoverage(providers?: ComponentTarget[]): FidelityCoverage;
|
|
669
669
|
|
|
670
|
+
/**
|
|
671
|
+
* v1.49 react-19-actions axis — useActionState + useOptimistic + useFormStatus
|
|
672
|
+
* を統合した React 19 Actions API の deterministic state machine。
|
|
673
|
+
*/
|
|
674
|
+
type ReactActionsState = 'idle' | 'transition-pending' | 'optimistic-committed' | 'resolved';
|
|
675
|
+
interface ReactActionsSession {
|
|
676
|
+
target: ComponentTarget;
|
|
677
|
+
actionId: string;
|
|
678
|
+
state: ReactActionsState;
|
|
679
|
+
pendingCount: number;
|
|
680
|
+
optimisticValues: string[];
|
|
681
|
+
resolvedValue: string | null;
|
|
682
|
+
history: AxisStep<ReactActionsState>[];
|
|
683
|
+
}
|
|
684
|
+
declare function initializeReactActions(input: {
|
|
685
|
+
target: ComponentTarget;
|
|
686
|
+
actionId: string;
|
|
687
|
+
}): ReactActionsSession;
|
|
688
|
+
declare function beginActionTransition(session: ReactActionsSession): AxisStep<ReactActionsState>;
|
|
689
|
+
declare function applyOptimisticUpdate(session: ReactActionsSession, optimisticValue: string): AxisStep<ReactActionsState>;
|
|
690
|
+
declare function resolveAction(session: ReactActionsSession, resolvedValue: string): AxisStep<ReactActionsState>;
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* v1.49 islands-architecture axis — Astro / Deno Fresh / Solid Start の
|
|
694
|
+
* Islands architecture (partial hydration + selective interactivity) を
|
|
695
|
+
* target-neutral に扱う state machine。
|
|
696
|
+
*/
|
|
697
|
+
type IslandsState = 'idle' | 'registered' | 'hydrating' | 'interactive' | 'static-verified';
|
|
698
|
+
interface IslandSpec {
|
|
699
|
+
islandId: string;
|
|
700
|
+
loadStrategy: 'load' | 'idle' | 'visible' | 'media' | 'only';
|
|
701
|
+
interactiveBoundary: boolean;
|
|
702
|
+
}
|
|
703
|
+
interface IslandsSession {
|
|
704
|
+
target: ComponentTarget;
|
|
705
|
+
routeId: string;
|
|
706
|
+
islands: IslandSpec[];
|
|
707
|
+
state: IslandsState;
|
|
708
|
+
hydratedIslandIds: string[];
|
|
709
|
+
staticBoundaryIds: string[];
|
|
710
|
+
history: AxisStep<IslandsState>[];
|
|
711
|
+
}
|
|
712
|
+
declare function bootstrapIslandsRoute(input: {
|
|
713
|
+
target: ComponentTarget;
|
|
714
|
+
routeId: string;
|
|
715
|
+
}): IslandsSession;
|
|
716
|
+
declare function registerIsland(session: IslandsSession, island: IslandSpec): AxisStep<IslandsState>;
|
|
717
|
+
declare function beginIslandHydration(session: IslandsSession, islandId: string): AxisStep<IslandsState>;
|
|
718
|
+
declare function markIslandInteractive(session: IslandsSession, islandId: string): AxisStep<IslandsState>;
|
|
719
|
+
declare function assertStaticBoundary(session: IslandsSession, boundaryId: string): AxisStep<IslandsState>;
|
|
720
|
+
|
|
670
721
|
type KiwaTestMode = 'mock' | 'real';
|
|
671
722
|
interface ResolvedMode {
|
|
672
723
|
mode: KiwaTestMode;
|
|
@@ -677,4 +728,4 @@ declare function resolveMode(provider: ComponentTarget, env?: Record<string, str
|
|
|
677
728
|
declare function resolveAllModes(env?: Record<string, string | undefined>): ResolvedMode[];
|
|
678
729
|
declare function assertMode(provider: ComponentTarget, expected: KiwaTestMode, env?: Record<string, string | undefined>): void;
|
|
679
730
|
|
|
680
|
-
export { type A11yViolation, type AxisStep, type ButtonArgs, COMPONENT_AXIS_TO_EVENTS, type CanvasElement, type CardArgs, type ChromaticConfig, type ChromaticVisualMock, type ComponentAxis, type ComponentLocator, type ComponentProvider, type ComponentRender, type ComponentTarget, type FidelityCoverage, type FidelityRow, type FormActionSession, type FormActionState, type FormArgs, type FormField, type InputArgs, type KiwaTestMode, type MockEvent, type MockNode, type ModalArgs, type NeutralEventName, type NodeLocator, type NodeOptions, type PlayContext, type PlaywrightCTMock, type ResolvedMode, type RscHarnessSession, type RscHarnessState, type StoryEntry, type StoryMeta, type StoryMountResult, type StoryObj, type StoryParameters, type StoryPlayResult, type StoryRegistry, type StreamingSsrSession, type StreamingSsrState, type ViewTransitionSession, type ViewTransitionState, type VisualBaseline, type VisualDiff, type VisualReviewAction, type VisualReviewEntry, addHandler, appendChild, applyOptimisticUpdate, assertAnimation, assertMode, beginRscRender, buildButton, buildCard, buildForm, buildInput, buildModal, captureErrorBoundary, collectFidelityCoverage, completeRscRender, completeSelectiveHydration, componentFixtures, createCanvas, createChromaticVisualMock, createNode, createPlaywrightCTMock, createStoryRegistry, enableProgressiveEnhancement, enterSuspenseBoundary, failRscRender, findByRole, findByText, finishElementTransition, fireEvent, hashMarkup, markFormStatusPending, markSuspensePending, providerEventName, query, rejectFormAction, renderMarkup, resolveAllModes, resolveFormAction, resolveMode, startDocumentTransition, startElementTransition, startFormActionSession, startProgressiveHydration, startRscHarness, startStreamingSsr, startViewTransitionSession, streamHtmlChunk };
|
|
731
|
+
export { type A11yViolation, type AxisStep, type ButtonArgs, COMPONENT_AXIS_TO_EVENTS, type CanvasElement, type CardArgs, type ChromaticConfig, type ChromaticVisualMock, type ComponentAxis, type ComponentLocator, type ComponentProvider, type ComponentRender, type ComponentTarget, type FidelityCoverage, type FidelityRow, type FormActionSession, type FormActionState, type FormArgs, type FormField, type InputArgs, type IslandSpec, type IslandsSession, type IslandsState, type KiwaTestMode, type MockEvent, type MockNode, type ModalArgs, type NeutralEventName, type NodeLocator, type NodeOptions, type PlayContext, type PlaywrightCTMock, type ReactActionsSession, type ReactActionsState, type ResolvedMode, type RscHarnessSession, type RscHarnessState, type StoryEntry, type StoryMeta, type StoryMountResult, type StoryObj, type StoryParameters, type StoryPlayResult, type StoryRegistry, type StreamingSsrSession, type StreamingSsrState, type ViewTransitionSession, type ViewTransitionState, type VisualBaseline, type VisualDiff, type VisualReviewAction, type VisualReviewEntry, addHandler, appendChild, applyOptimisticUpdate$1 as applyOptimisticUpdate, applyOptimisticUpdate as applyReactActionOptimistic, assertAnimation, assertMode, assertStaticBoundary, beginActionTransition, beginIslandHydration, beginRscRender, bootstrapIslandsRoute, buildButton, buildCard, buildForm, buildInput, buildModal, captureErrorBoundary, collectFidelityCoverage, completeRscRender, completeSelectiveHydration, componentFixtures, createCanvas, createChromaticVisualMock, createNode, createPlaywrightCTMock, createStoryRegistry, enableProgressiveEnhancement, enterSuspenseBoundary, failRscRender, findByRole, findByText, finishElementTransition, fireEvent, hashMarkup, initializeReactActions, markFormStatusPending, markIslandInteractive, markSuspensePending, providerEventName, query, registerIsland, rejectFormAction, renderMarkup, resolveAction, resolveAllModes, resolveFormAction, resolveMode, startDocumentTransition, startElementTransition, startFormActionSession, startProgressiveHydration, startRscHarness, startStreamingSsr, startViewTransitionSession, streamHtmlChunk };
|
package/dist/index.js
CHANGED
|
@@ -1118,6 +1118,19 @@ var COMPONENT_AXIS_TO_EVENTS = {
|
|
|
1118
1118
|
"form.optimistic_applied",
|
|
1119
1119
|
"form.progressive_enhanced",
|
|
1120
1120
|
"form.action_resolved"
|
|
1121
|
+
],
|
|
1122
|
+
// v1.49 advanced III
|
|
1123
|
+
"react-19-actions": [
|
|
1124
|
+
"action.state_initialized",
|
|
1125
|
+
"action.transition_pending",
|
|
1126
|
+
"action.optimistic_committed",
|
|
1127
|
+
"action.resolved"
|
|
1128
|
+
],
|
|
1129
|
+
"islands-architecture": [
|
|
1130
|
+
"islands.registered",
|
|
1131
|
+
"islands.hydration_started",
|
|
1132
|
+
"islands.interactive_ready",
|
|
1133
|
+
"islands.static_boundary_asserted"
|
|
1121
1134
|
]
|
|
1122
1135
|
};
|
|
1123
1136
|
function collectFidelityCoverage(providers = ["storybook8", "playwright-ct", "chromatic"]) {
|
|
@@ -1137,6 +1150,147 @@ function collectFidelityCoverage(providers = ["storybook8", "playwright-ct", "ch
|
|
|
1137
1150
|
return { providers, axes, rows };
|
|
1138
1151
|
}
|
|
1139
1152
|
|
|
1153
|
+
// src/semantics/react-19-actions.ts
|
|
1154
|
+
function emit5(session, neutralEvent, metadata) {
|
|
1155
|
+
const step = {
|
|
1156
|
+
neutralEvent,
|
|
1157
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
1158
|
+
state: session.state,
|
|
1159
|
+
amountCents: 0,
|
|
1160
|
+
metadata: { actionId: session.actionId, ...metadata }
|
|
1161
|
+
};
|
|
1162
|
+
session.history.push(step);
|
|
1163
|
+
return step;
|
|
1164
|
+
}
|
|
1165
|
+
function initializeReactActions(input) {
|
|
1166
|
+
if (input.actionId.length === 0) {
|
|
1167
|
+
throw new Error("initializeReactActions: actionId must not be empty");
|
|
1168
|
+
}
|
|
1169
|
+
const session = {
|
|
1170
|
+
target: input.target,
|
|
1171
|
+
actionId: input.actionId,
|
|
1172
|
+
state: "idle",
|
|
1173
|
+
pendingCount: 0,
|
|
1174
|
+
optimisticValues: [],
|
|
1175
|
+
resolvedValue: null,
|
|
1176
|
+
history: []
|
|
1177
|
+
};
|
|
1178
|
+
emit5(session, "action.state_initialized", { pendingCount: 0 });
|
|
1179
|
+
return session;
|
|
1180
|
+
}
|
|
1181
|
+
function beginActionTransition(session) {
|
|
1182
|
+
if (session.state !== "idle" && session.state !== "resolved") {
|
|
1183
|
+
throw new Error(`beginActionTransition: session is ${session.state}`);
|
|
1184
|
+
}
|
|
1185
|
+
session.state = "transition-pending";
|
|
1186
|
+
session.pendingCount += 1;
|
|
1187
|
+
return emit5(session, "action.transition_pending", {
|
|
1188
|
+
pendingCount: session.pendingCount
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
function applyOptimisticUpdate2(session, optimisticValue) {
|
|
1192
|
+
if (session.state !== "transition-pending") {
|
|
1193
|
+
throw new Error(`applyOptimisticUpdate: session is ${session.state}`);
|
|
1194
|
+
}
|
|
1195
|
+
session.state = "optimistic-committed";
|
|
1196
|
+
session.optimisticValues.push(optimisticValue);
|
|
1197
|
+
return emit5(session, "action.optimistic_committed", { optimisticValue });
|
|
1198
|
+
}
|
|
1199
|
+
function resolveAction(session, resolvedValue) {
|
|
1200
|
+
if (session.state !== "transition-pending" && session.state !== "optimistic-committed") {
|
|
1201
|
+
throw new Error(`resolveAction: session is ${session.state}`);
|
|
1202
|
+
}
|
|
1203
|
+
session.state = "resolved";
|
|
1204
|
+
session.resolvedValue = resolvedValue;
|
|
1205
|
+
session.pendingCount = Math.max(0, session.pendingCount - 1);
|
|
1206
|
+
return emit5(session, "action.resolved", {
|
|
1207
|
+
resolvedValue,
|
|
1208
|
+
pendingCount: session.pendingCount,
|
|
1209
|
+
optimisticCount: session.optimisticValues.length
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// src/semantics/islands-architecture.ts
|
|
1214
|
+
function emit6(session, neutralEvent, metadata) {
|
|
1215
|
+
const step = {
|
|
1216
|
+
neutralEvent,
|
|
1217
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
1218
|
+
state: session.state,
|
|
1219
|
+
amountCents: 0,
|
|
1220
|
+
metadata: { routeId: session.routeId, ...metadata }
|
|
1221
|
+
};
|
|
1222
|
+
session.history.push(step);
|
|
1223
|
+
return step;
|
|
1224
|
+
}
|
|
1225
|
+
function bootstrapIslandsRoute(input) {
|
|
1226
|
+
if (input.routeId.length === 0) {
|
|
1227
|
+
throw new Error("bootstrapIslandsRoute: routeId must not be empty");
|
|
1228
|
+
}
|
|
1229
|
+
return {
|
|
1230
|
+
target: input.target,
|
|
1231
|
+
routeId: input.routeId,
|
|
1232
|
+
islands: [],
|
|
1233
|
+
state: "idle",
|
|
1234
|
+
hydratedIslandIds: [],
|
|
1235
|
+
staticBoundaryIds: [],
|
|
1236
|
+
history: []
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
function registerIsland(session, island) {
|
|
1240
|
+
session.islands.push(island);
|
|
1241
|
+
session.state = "registered";
|
|
1242
|
+
return emit6(session, "islands.registered", {
|
|
1243
|
+
islandId: island.islandId,
|
|
1244
|
+
loadStrategy: island.loadStrategy,
|
|
1245
|
+
interactiveBoundary: island.interactiveBoundary
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
function beginIslandHydration(session, islandId) {
|
|
1249
|
+
const island = session.islands.find((i) => i.islandId === islandId);
|
|
1250
|
+
if (!island) {
|
|
1251
|
+
throw new Error(`beginIslandHydration: island ${islandId} not registered`);
|
|
1252
|
+
}
|
|
1253
|
+
if (session.state !== "registered" && session.state !== "hydrating") {
|
|
1254
|
+
throw new Error(`beginIslandHydration: session is ${session.state}`);
|
|
1255
|
+
}
|
|
1256
|
+
session.state = "hydrating";
|
|
1257
|
+
return emit6(session, "islands.hydration_started", {
|
|
1258
|
+
islandId,
|
|
1259
|
+
loadStrategy: island.loadStrategy
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
function markIslandInteractive(session, islandId) {
|
|
1263
|
+
if (session.state !== "hydrating") {
|
|
1264
|
+
throw new Error(`markIslandInteractive: session is ${session.state}`);
|
|
1265
|
+
}
|
|
1266
|
+
if (session.hydratedIslandIds.includes(islandId)) {
|
|
1267
|
+
throw new Error(`markIslandInteractive: island ${islandId} already interactive`);
|
|
1268
|
+
}
|
|
1269
|
+
session.hydratedIslandIds.push(islandId);
|
|
1270
|
+
const allHydrated = session.hydratedIslandIds.length === session.islands.filter((i) => i.interactiveBoundary).length;
|
|
1271
|
+
if (allHydrated) {
|
|
1272
|
+
session.state = "interactive";
|
|
1273
|
+
}
|
|
1274
|
+
return emit6(session, "islands.interactive_ready", {
|
|
1275
|
+
islandId,
|
|
1276
|
+
hydratedCount: session.hydratedIslandIds.length,
|
|
1277
|
+
allInteractiveReady: allHydrated
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
function assertStaticBoundary(session, boundaryId) {
|
|
1281
|
+
if (session.staticBoundaryIds.includes(boundaryId)) {
|
|
1282
|
+
throw new Error(`assertStaticBoundary: boundary ${boundaryId} already asserted`);
|
|
1283
|
+
}
|
|
1284
|
+
session.staticBoundaryIds.push(boundaryId);
|
|
1285
|
+
if (session.state === "interactive") {
|
|
1286
|
+
session.state = "static-verified";
|
|
1287
|
+
}
|
|
1288
|
+
return emit6(session, "islands.static_boundary_asserted", {
|
|
1289
|
+
boundaryId,
|
|
1290
|
+
staticBoundaryCount: session.staticBoundaryIds.length
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1140
1294
|
// src/real-driver.ts
|
|
1141
1295
|
var TARGET_KEY_ENV = {
|
|
1142
1296
|
storybook8: "STORYBOOK_URL",
|
|
@@ -1174,9 +1328,14 @@ export {
|
|
|
1174
1328
|
addHandler,
|
|
1175
1329
|
appendChild,
|
|
1176
1330
|
applyOptimisticUpdate,
|
|
1331
|
+
applyOptimisticUpdate2 as applyReactActionOptimistic,
|
|
1177
1332
|
assertAnimation,
|
|
1178
1333
|
assertMode,
|
|
1334
|
+
assertStaticBoundary,
|
|
1335
|
+
beginActionTransition,
|
|
1336
|
+
beginIslandHydration,
|
|
1179
1337
|
beginRscRender,
|
|
1338
|
+
bootstrapIslandsRoute,
|
|
1180
1339
|
buildButton,
|
|
1181
1340
|
buildCard,
|
|
1182
1341
|
buildForm,
|
|
@@ -1200,12 +1359,16 @@ export {
|
|
|
1200
1359
|
finishElementTransition,
|
|
1201
1360
|
fireEvent,
|
|
1202
1361
|
hashMarkup,
|
|
1362
|
+
initializeReactActions,
|
|
1203
1363
|
markFormStatusPending,
|
|
1364
|
+
markIslandInteractive,
|
|
1204
1365
|
markSuspensePending,
|
|
1205
1366
|
providerEventName,
|
|
1206
1367
|
query,
|
|
1368
|
+
registerIsland,
|
|
1207
1369
|
rejectFormAction,
|
|
1208
1370
|
renderMarkup,
|
|
1371
|
+
resolveAction,
|
|
1209
1372
|
resolveAllModes,
|
|
1210
1373
|
resolveFormAction,
|
|
1211
1374
|
resolveMode,
|