@openclaw/diffs 2026.7.2-beta.7 → 2026.7.33
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 +9 -2
- package/dist/assets/viewer-runtime.js +31 -31
- package/dist/index.js +307 -290
- package/node_modules/@pierre/diffs/node_modules/@shikijs/core/package.json +3 -3
- package/node_modules/@pierre/diffs/node_modules/@shikijs/engine-javascript/package.json +2 -2
- package/node_modules/@pierre/diffs/node_modules/@shikijs/engine-oniguruma/package.json +2 -2
- package/node_modules/@pierre/diffs/node_modules/@shikijs/primitive/dist/index.mjs +5 -6
- package/node_modules/@pierre/diffs/node_modules/@shikijs/primitive/package.json +2 -2
- package/node_modules/@pierre/diffs/node_modules/@shikijs/themes/package.json +2 -2
- package/node_modules/@pierre/diffs/node_modules/@shikijs/transformers/package.json +3 -3
- package/node_modules/@pierre/diffs/node_modules/@shikijs/types/dist/index.d.mts +1 -9
- package/node_modules/@pierre/diffs/node_modules/@shikijs/types/package.json +1 -1
- package/node_modules/@pierre/diffs/node_modules/@types/hast/README.md +2 -2
- package/node_modules/@pierre/diffs/node_modules/@types/hast/index.d.ts +0 -642
- package/node_modules/@pierre/diffs/node_modules/@types/hast/package.json +3 -9
- package/node_modules/@pierre/diffs/node_modules/@ungap/structured-clone/cjs/deserialize.js +1 -6
- package/node_modules/@pierre/diffs/node_modules/@ungap/structured-clone/cjs/serialize.js +2 -2
- package/node_modules/@pierre/diffs/node_modules/@ungap/structured-clone/esm/deserialize.js +1 -6
- package/node_modules/@pierre/diffs/node_modules/@ungap/structured-clone/esm/serialize.js +2 -2
- package/node_modules/@pierre/diffs/node_modules/@ungap/structured-clone/package.json +1 -1
- package/node_modules/@pierre/diffs/node_modules/@ungap/structured-clone/structured-json.js +1 -1
- package/node_modules/@pierre/diffs/node_modules/shiki/package.json +7 -7
- package/node_modules/@shikijs/langs/node_modules/@shikijs/types/dist/index.d.mts +1 -9
- package/node_modules/@shikijs/langs/node_modules/@shikijs/types/package.json +1 -1
- package/node_modules/@shikijs/langs/node_modules/@types/hast/README.md +2 -2
- package/node_modules/@shikijs/langs/node_modules/@types/hast/index.d.ts +0 -642
- package/node_modules/@shikijs/langs/node_modules/@types/hast/package.json +3 -9
- package/node_modules/@shikijs/langs/package.json +2 -2
- package/node_modules/playwright-core/browsers.json +18 -12
- package/node_modules/playwright-core/lib/bootstrap.js +1 -1
- package/node_modules/playwright-core/lib/coreBundle.js +12247 -13691
- package/node_modules/playwright-core/lib/server/deviceDescriptorsSource.json +2739 -0
- package/node_modules/playwright-core/lib/server/electron/loader.js +2 -5
- package/node_modules/playwright-core/lib/serverRegistry.js +1 -5
- package/node_modules/playwright-core/lib/tools/cli-client/help.json +6 -21
- package/node_modules/playwright-core/lib/tools/cli-client/program.js +1 -1
- package/node_modules/playwright-core/lib/tools/cli-client/session.js +0 -4
- package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/SKILL.md +5 -21
- package/node_modules/playwright-core/lib/tools/{skills/playwright-cli/references/test-generation.md → cli-client/skill/references/spec-driven-testing.md} +7 -135
- package/node_modules/playwright-core/lib/tools/cli-client/skill/references/test-generation.md +134 -0
- package/node_modules/playwright-core/lib/tools/utils/extension.js +8 -31
- package/node_modules/playwright-core/lib/utilsBundle.js +48599 -52627
- package/node_modules/playwright-core/lib/utilsBundle.js.LICENSE +268 -391
- package/node_modules/playwright-core/lib/vite/dashboard/assets/index-BY2S1tHT.css +1 -0
- package/node_modules/playwright-core/lib/vite/dashboard/assets/index-C_5TMfeg.js +52 -0
- package/node_modules/playwright-core/lib/vite/dashboard/index.html +2 -2
- package/node_modules/playwright-core/lib/vite/htmlReport/report.css +1 -2
- package/node_modules/playwright-core/lib/vite/htmlReport/report.js +55 -15
- package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-DYBRYzYX.css +1 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-DeBYQozu.js +32 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/index-4ZiSSCmn.css +1 -0
- package/node_modules/playwright-core/lib/vite/recorder/assets/index-Bq-mQf8S.js +193 -0
- package/node_modules/playwright-core/lib/vite/recorder/index.html +2 -2
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-LEHpjmcn.js +32 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-BNmKHKpQ.js +264 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-BYQrIQwR.js +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-CsJ4vdCR.js +9 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.DYBRYzYX.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.CjdS-WJx.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/index.CzXZzn5A.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/index.DMMX1gXU.js +2 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/index.html +5 -5
- package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.html +2 -2
- package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.v8KI4P3m.js +2 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/sw.bundle.js +4 -3
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.BZQ54Kgt.css +1 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.Ut8wwJNp.js +6 -0
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +5 -5
- package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.DYP7pi_n.css +32 -0
- package/node_modules/playwright-core/lib/xdg-open +137 -338
- package/node_modules/playwright-core/package.json +2 -2
- package/node_modules/playwright-core/types/protocol.d.ts +36 -249
- package/node_modules/playwright-core/types/structs.d.ts +1 -3
- package/node_modules/playwright-core/types/types.d.ts +268 -2011
- package/node_modules/typebox/build/compile/validator.d.mts +4 -1
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +2 -5
- package/node_modules/typebox/build/guard/string.mjs +4 -16
- package/node_modules/typebox/build/schema/engine/_functions.mjs +15 -34
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +0 -5
- package/node_modules/typebox/build/type/action/readonly_object.mjs +0 -8
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +32 -29
- package/openclaw.plugin.json +0 -1
- package/package.json +7 -7
- package/skills/diffs/SKILL.md +2 -2
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/SKILL.md +0 -143
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +0 -144
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/migration.md +0 -85
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/react.md +0 -67
- package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/vue.md +0 -75
- package/node_modules/playwright-core/lib/vite/dashboard/assets/index-CyWAfh-p.js +0 -11
- package/node_modules/playwright-core/lib/vite/dashboard/assets/index-DhC616m4.css +0 -1
- package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +0 -1
- package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-CwYYHbcZ.js +0 -32
- package/node_modules/playwright-core/lib/vite/recorder/assets/index-DYjdXIbE.js +0 -129
- package/node_modules/playwright-core/lib/vite/recorder/assets/index-l_lX622x.css +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-By56iMx7.js +0 -32
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-B34OrIms.js +0 -181
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-COQkjINf.js +0 -7
- package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.BLFoOugd.css +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/index.B_TqY17P.css +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/index.Dl36UVQT.js +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.C7UW1sC9.css +0 -1
- package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.D962mr9b.js +0 -5
- package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +0 -1
- package/node_modules/playwright-core/lib/webp_codec.LICENSE +0 -173
- package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/element-attributes.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/playwright-tests.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/request-mocking.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/running-code.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/session-management.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/storage-state.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/tracing.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-cli → cli-client/skill}/references/video-recording.md +0 -0
- /package/node_modules/playwright-core/lib/tools/{skills/playwright-trace → trace}/SKILL.md +0 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { type TLocalizedValidationError } from '../error/index.mjs';
|
|
2
2
|
import { type StaticDecode, type StaticEncode, type TProperties, type TSchema } from '../type/index.mjs';
|
|
3
|
+
import { BuildResult, EvaluateResult } from '../schema/index.mjs';
|
|
3
4
|
export declare class Validator<Context extends TProperties = TProperties, Type extends TSchema = TSchema, Encode extends unknown = StaticEncode<Type, Context>, Decode extends unknown = StaticDecode<Type, Context>> {
|
|
4
5
|
private readonly hasCodec;
|
|
5
6
|
private readonly buildResult;
|
|
6
7
|
private readonly evaluateResult;
|
|
7
|
-
/** Constructs a Validator. */
|
|
8
|
+
/** Constructs a Validator with the given Context and Type. */
|
|
8
9
|
constructor(context: Context, type: Type);
|
|
10
|
+
/** Constructs a Validator with the given arguments. */
|
|
11
|
+
constructor(hasCodec: boolean, buildResult: BuildResult, evaluateResult: EvaluateResult);
|
|
9
12
|
/** Returns true if this Validator is using JIT acceleration. */
|
|
10
13
|
IsAccelerated(): boolean;
|
|
11
14
|
/** Returns the Context for this validator. */
|
|
@@ -61,5 +61,5 @@ export declare function Keys(value: Record<PropertyKey, unknown>): string[];
|
|
|
61
61
|
export declare function Symbols(value: Record<PropertyKey, unknown>): symbol[];
|
|
62
62
|
/** Returns the property values for the given object via `Object.values()` */
|
|
63
63
|
export declare function Values(value: Record<PropertyKey, unknown>): unknown[];
|
|
64
|
-
/**
|
|
64
|
+
/** Tests values for deep equality */
|
|
65
65
|
export declare function IsDeepEqual(left: unknown, right: unknown): boolean;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// deno-fmt-ignore-file
|
|
2
1
|
import * as String from './string.mjs';
|
|
3
2
|
// --------------------------------------------------------------------------
|
|
4
3
|
// Guards
|
|
@@ -204,9 +203,7 @@ function DeepEqualArray(left, right) {
|
|
|
204
203
|
return IsArray(right) && IsEqual(left.length, right.length) &&
|
|
205
204
|
left.every((_, index) => IsDeepEqual(left[index], right[index]));
|
|
206
205
|
}
|
|
207
|
-
/**
|
|
206
|
+
/** Tests values for deep equality */
|
|
208
207
|
export function IsDeepEqual(left, right) {
|
|
209
|
-
return (IsArray(left) ? DeepEqualArray(left, right) :
|
|
210
|
-
IsObject(left) ? DeepEqualObject(left, right) :
|
|
211
|
-
IsEqual(left, right));
|
|
208
|
+
return (IsArray(left) ? DeepEqualArray(left, right) : IsObject(left) ? DeepEqualObject(left, right) : IsEqual(left, right));
|
|
212
209
|
}
|
|
@@ -5,18 +5,6 @@ function IsBetween(value, min, max) {
|
|
|
5
5
|
return value >= min && value <= max;
|
|
6
6
|
}
|
|
7
7
|
// --------------------------------------------------------------------------
|
|
8
|
-
// IsZeroWidthJoiner
|
|
9
|
-
// --------------------------------------------------------------------------
|
|
10
|
-
function IsZeroWidthJoiner(value) {
|
|
11
|
-
return (value === 0x200D);
|
|
12
|
-
}
|
|
13
|
-
// --------------------------------------------------------------------------
|
|
14
|
-
// IsHighSurrogate
|
|
15
|
-
// --------------------------------------------------------------------------
|
|
16
|
-
function IsHighSurrogate(value) {
|
|
17
|
-
return IsBetween(value, 0xD800, 0xDBFF);
|
|
18
|
-
}
|
|
19
|
-
// --------------------------------------------------------------------------
|
|
20
8
|
// IsRegionalIndicator
|
|
21
9
|
// --------------------------------------------------------------------------
|
|
22
10
|
function IsRegionalIndicator(value) {
|
|
@@ -84,10 +72,10 @@ function NextGraphemeClusterIndex(value, clusterStart) {
|
|
|
84
72
|
// IsGraphemeCodePoint
|
|
85
73
|
// --------------------------------------------------------------------------
|
|
86
74
|
function IsGraphemeCodePoint(value) {
|
|
87
|
-
return (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
return (IsBetween(value, 0xD800, 0xDBFF) || // High surrogate
|
|
76
|
+
IsBetween(value, 0x0300, 0x036F) || // Combining diacritical marks
|
|
77
|
+
(value === 0x200D) // Zero-width joiner
|
|
78
|
+
);
|
|
91
79
|
}
|
|
92
80
|
// --------------------------------------------------------------------------
|
|
93
81
|
// GraphemeCount
|
|
@@ -1,66 +1,47 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
+
import * as Schema from '../types/index.mjs';
|
|
2
3
|
import { Hashing } from '../../system/hashing/index.mjs';
|
|
3
4
|
import { EmitGuard as E } from '../../guard/index.mjs';
|
|
4
5
|
import { BuildSchema } from './schema.mjs';
|
|
5
|
-
const
|
|
6
|
-
const names = new Map;
|
|
7
|
-
const funcs = new Map();
|
|
8
|
-
// ------------------------------------------------------------------
|
|
9
|
-
// CreateName
|
|
10
|
-
// ------------------------------------------------------------------
|
|
11
|
-
function NextName() {
|
|
12
|
-
return Hashing.Hash(index[0]++);
|
|
13
|
-
}
|
|
14
|
-
function CreateName(schema, href) {
|
|
15
|
-
if (!names.has(schema))
|
|
16
|
-
names.set(schema, new Map());
|
|
17
|
-
const hrefs = names.get(schema);
|
|
18
|
-
if (hrefs.has(href))
|
|
19
|
-
return hrefs.get(href);
|
|
20
|
-
const name = NextName();
|
|
21
|
-
hrefs.set(href, name);
|
|
22
|
-
return name;
|
|
23
|
-
}
|
|
6
|
+
const functions = new Map();
|
|
24
7
|
// ------------------------------------------------------------------
|
|
25
8
|
// CreateCallExpression
|
|
26
9
|
// ------------------------------------------------------------------
|
|
27
|
-
function CreateCallExpression(context, _schema,
|
|
10
|
+
function CreateCallExpression(context, _schema, hash, value) {
|
|
28
11
|
return context.UseUnevaluated()
|
|
29
|
-
? E.Call(`check_${
|
|
30
|
-
: E.Call(`check_${
|
|
12
|
+
? E.Call(`check_${hash}`, ['context', value])
|
|
13
|
+
: E.Call(`check_${hash}`, [value]);
|
|
31
14
|
}
|
|
32
15
|
// ------------------------------------------------------------------
|
|
33
16
|
// CreateFunctionExpression
|
|
34
17
|
// ------------------------------------------------------------------
|
|
35
|
-
function CreateFunctionExpression(stack, context, schema,
|
|
18
|
+
function CreateFunctionExpression(stack, context, schema, hash) {
|
|
36
19
|
const expression = BuildSchema(stack, context, schema, 'value');
|
|
37
20
|
return context.UseUnevaluated()
|
|
38
|
-
? E.ConstDeclaration(`check_${
|
|
39
|
-
: E.ConstDeclaration(`check_${
|
|
21
|
+
? E.ConstDeclaration(`check_${hash}`, E.ArrowFunction(['context', 'value'], expression))
|
|
22
|
+
: E.ConstDeclaration(`check_${hash}`, E.ArrowFunction(['value'], expression));
|
|
40
23
|
}
|
|
41
24
|
// ------------------------------------------------------------------
|
|
42
25
|
// ResetFunctions
|
|
43
26
|
// ------------------------------------------------------------------
|
|
44
27
|
export function ResetFunctions() {
|
|
45
|
-
|
|
46
|
-
names.clear();
|
|
47
|
-
funcs.clear();
|
|
28
|
+
functions.clear();
|
|
48
29
|
}
|
|
49
30
|
// ------------------------------------------------------------------
|
|
50
31
|
// GetFunctions
|
|
51
32
|
// ------------------------------------------------------------------
|
|
52
33
|
export function GetFunctions() {
|
|
53
|
-
return [...
|
|
34
|
+
return [...functions.values()];
|
|
54
35
|
}
|
|
55
36
|
// ------------------------------------------------------------------
|
|
56
37
|
// CreateFunction
|
|
57
38
|
// ------------------------------------------------------------------
|
|
58
39
|
export function CreateFunction(stack, context, schema, value) {
|
|
59
|
-
const
|
|
60
|
-
const call = CreateCallExpression(context, schema,
|
|
61
|
-
if (
|
|
40
|
+
const hash = Schema.IsSchemaObject(schema) ? Hashing.Hash({ __baseURL: stack.BaseURL().href, ...schema }) : Hashing.Hash(schema);
|
|
41
|
+
const call = CreateCallExpression(context, schema, hash, value);
|
|
42
|
+
if (functions.has(hash))
|
|
62
43
|
return call;
|
|
63
|
-
|
|
64
|
-
|
|
44
|
+
functions.set(hash, '');
|
|
45
|
+
functions.set(hash, CreateFunctionExpression(stack, context, schema, hash));
|
|
65
46
|
return call;
|
|
66
47
|
}
|
|
@@ -9,8 +9,3 @@ export declare function ReadonlyObjectDeferred<Type extends TSchema>(type: Type,
|
|
|
9
9
|
export type TReadonlyObject<Type extends TSchema> = (TReadonlyObjectAction<Type>);
|
|
10
10
|
/** This type is an alias for TypeScript's `Readonly<T>` utility type. It will make all properties of a TObject readonly or marks an TArray or TTuple as immutable `readonly T[]`. */
|
|
11
11
|
export declare function ReadonlyObject<Type extends TSchema>(type: Type, options?: TSchemaOptions): TReadonlyObject<Type>;
|
|
12
|
-
/**
|
|
13
|
-
* This type has been renamed to ReadonlyObject.
|
|
14
|
-
* @deprecated
|
|
15
|
-
*/
|
|
16
|
-
export declare const ReadonlyType: typeof ReadonlyObject;
|
|
@@ -9,11 +9,3 @@ export function ReadonlyObjectDeferred(type, options = {}) {
|
|
|
9
9
|
export function ReadonlyObject(type, options = {}) {
|
|
10
10
|
return ReadonlyObjectAction(type, options);
|
|
11
11
|
}
|
|
12
|
-
// ------------------------------------------------------------------
|
|
13
|
-
// Alias
|
|
14
|
-
// ------------------------------------------------------------------
|
|
15
|
-
/**
|
|
16
|
-
* This type has been renamed to ReadonlyObject.
|
|
17
|
-
* @deprecated
|
|
18
|
-
*/
|
|
19
|
-
export const ReadonlyType = ReadonlyObject;
|
|
@@ -19,7 +19,7 @@ export { Omit, type TOmit, type TOmitDeferred } from './type/action/omit.mjs';
|
|
|
19
19
|
export { Parameters, type TParameters, type TParametersDeferred } from './type/action/parameters.mjs';
|
|
20
20
|
export { Partial, type TPartial, type TPartialDeferred } from './type/action/partial.mjs';
|
|
21
21
|
export { Pick, type TPick, type TPickDeferred } from './type/action/pick.mjs';
|
|
22
|
-
export { ReadonlyObject,
|
|
22
|
+
export { ReadonlyObject, type TReadonlyObject, type TReadonlyObjectDeferred } from './type/action/readonly_object.mjs';
|
|
23
23
|
export { Required, type TRequired, type TRequiredDeferred } from './type/action/required.mjs';
|
|
24
24
|
export { ReturnType, type TReturnType, type TReturnTypeDeferred } from './type/action/return_type.mjs';
|
|
25
25
|
export { type TUncapitalize, type TUncapitalizeDeferred, Uncapitalize } from './type/action/uncapitalize.mjs';
|
|
@@ -31,7 +31,7 @@ export { Omit } from './type/action/omit.mjs';
|
|
|
31
31
|
export { Parameters } from './type/action/parameters.mjs';
|
|
32
32
|
export { Partial } from './type/action/partial.mjs';
|
|
33
33
|
export { Pick } from './type/action/pick.mjs';
|
|
34
|
-
export { ReadonlyObject
|
|
34
|
+
export { ReadonlyObject } from './type/action/readonly_object.mjs';
|
|
35
35
|
export { Required } from './type/action/required.mjs';
|
|
36
36
|
export { ReturnType } from './type/action/return_type.mjs';
|
|
37
37
|
export { Uncapitalize } from './type/action/uncapitalize.mjs';
|
|
@@ -111,24 +111,27 @@ type User = Type.Static<typeof User> // type User = {
|
|
|
111
111
|
|
|
112
112
|
## Script
|
|
113
113
|
|
|
114
|
-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/
|
|
114
|
+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFonmXW32POv3b7k0AdAGUAxlGBgYACjwC5eAJS9G3VWvXdqdOADkAhiFQBnMHpGpKIiADsj8ALJ6YACzgBeREWFiJ0gAaUcHCEaHAAaqgiMNAATO5wAN5wZABccNYAriDEqFAANHBIaZnZuXAAvoHBROGR0VAAzPEAogBuegA2GU6oADwRUbFwAGSJcABexVk5UBUAfFUh6AP1ACwt7V09-XXQTaNJAO5TpbPlC35KygAiqGjWACao1vD6hiZmFla28En2xq5yvF+KhvOJJFIknIBI4XBUCn4gosahFYKgyPEElUgpAjMAYMAbGkVtBVnlseloCBOsTdo1yUEghlWrTBlAYlVKkElnAAOKoHCoGBQJCYimtXIE8xGWlosgAbQAugzGcBHsBpScZkrOcjQrDcsBOmLGXADMRgM8YKy1iqgg9gBgMBkjKgbaS7XATJEMh09FB3VBVrruTV-kZXB4saaAOYCwzCop8+NCkWe6kwQ00uAG8SdXWXLT0ABKGReoHQxdQGA6dUJ1ko4ecAjA2DQsEtRgEccFiZbbclnYEEo70oE+NQIC7rYg7YJxhbEDxBJs-dng4XZEbALXc6HPYTIt3G67I6lC4nU+PHYX1ipnWv867W6bj-3Kb7M73C7PGovmavL8TwEZk303bcIzArsMyzDooIEB0nRdUEgJvZ8IObVCnwEGC8zgrCh3NS0Xngl8dwIhdcKNfCBzQgRvREX1-VIos4CEGAnA1OAAElrAwXJnnMShnWsKJ6zgKBnieKApHeZw0hBYQOKlXolggDAcwBOYFESKo5O7D8j1-aV5QABkVRdl3rAQtyCfSD1TJBh0HEzzIEO8oGpODbLgezDKc4zjDMizQJ8-SqIfRDnVdGy9J3CK4KIq1Yrs+Kejw+i0EYv0oFi8ogA) | [Example 2](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFonmXW32POv3b7k0AdACpejbuImTu1OnAByAQxCoAzmAUBjVJQB2S1eq1wAsgpgALOAG9KcOKjKRYcDRB0r4ANVQaY0AExwALyIRAIA8sQAVj4wABRWcGQAXKGCcgCuIMSoUHEAlAA0cEip-KgCmdm5BXAAvvm29o7Q8K7uXrHQAMzBaRUAogBuCgA2GWaoceUCAJI6MLkqsXEA2t6+AcUzkTG+CXAAXmVhVTl5+fX5ALr5jXYOTm1uHnAbflAALH0zw2MTi2mYXmiygy326y6UG62zCuxWiQA7id0llzrUGrdGnUZPQACKoNA6AAmqAW8n0ak02nar28sAcPzh0QRTUgKmAMGAblSpgsAne0E+hSaOmgIDGvLM5gFUJhTQyQyl-MFUH8lAalFp8AA4qgcKgYFAkEzBPD9jY7ENclytCoURUAIJQKAKJBxemLMhFJrAEnAO0OgTO13umZnGp3DWNbUmSZQYBjU0Vc3xS1wJTEYBkmDKmWq4VNYnADAYDLLPOyzZfEV2NQ+DKjBRQSsF6Nal7wYyqSwhHYsi1NADm+uURtKcD1BvHtbgEtBidGytyi-bogAShkFqB0OvUBhRrFuTpKN2VDKwNg0LBsyoBCPp8aBJeINeuaoBNab3aBJzUCA7xfN9b2fCAOS5NxnyvG0QLIU8eyg18YI-B8xyfIDkLvL9bQ-P8AMQ4CPzFKAJVGAjMIEOCzwvaCbxQ0dDXQ2j3ywmCfzwwDmJAxVyLou8qIQjC+IEecVzGXiWIEYtS3LCohMkgTzwkkDRITcT5JAzNswWZSP0UmikOE1TF10u96w0Rtm1MyjcTgABlGAzADOB5gwXIyS0Sgyx0XxjzgKAyVJPJlHPIMHKcjQAB5CDQCAMBMHsAD5LnTEKZVQxikE-NjVFWAAGa5QPA48bLsNL7wY8dsu-XKCoEYjSNKucEIyqrsIDWrCp4uCyoQ4zxOkstlia8r+rIrScxGvr4xM8zLKgGy6iAA) | [Challenge](test/typescript/readme.md)
|
|
115
|
+
|
|
116
|
+
TypeBox includes a syntax engine that can transform TypeScript declarations into JSON Schema. The engine is a full syntactic frontend to Type.* and supports many advanced type-level constructs such as Conditional, Mapped, Indexed, Infer, Generics, Distributed types and more. This feature is implemented symmetrically at runtime and statically via TypeScript Template Literal types.
|
|
117
|
+
|
|
118
|
+
Syntax highlighting is available via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=sinclairzx81.typebox-script)
|
|
115
119
|
|
|
116
|
-
TypeBox includes a runtime scripting engine that can transform TypeScript definitions into JSON Schema. The engine is implemented symmetrically at runtime and inside TypeScript's type system. It supports many programmable type-level constructs such as Conditional, Mapped, Indexed, Generic, Distributive Conditional, and more. The engine is designed for TypeScript 7 but is supported in TypeScript 5 and above.
|
|
117
120
|
|
|
118
121
|
### Example
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
The following uses Script to parse TypeScript declarations into JSON Schema.
|
|
121
124
|
|
|
122
125
|
```typescript
|
|
123
126
|
// Module
|
|
124
127
|
const Math = Type.Script(`
|
|
125
128
|
type Vector2 = { x: number, y: number }
|
|
126
|
-
type Vector3 =
|
|
127
|
-
type Vector4 =
|
|
129
|
+
type Vector3 = Evaluate<Vector2 & { z: number }>
|
|
130
|
+
type Vector4 = Evaluate<Vector3 & { w: number }>
|
|
128
131
|
`)
|
|
129
132
|
|
|
130
133
|
// Dependent Module
|
|
131
|
-
const { Mesh } = Type.Script(Math, `
|
|
134
|
+
const { Mesh } = Type.Script({ ...Math }, `
|
|
132
135
|
type Vertex = {
|
|
133
136
|
position: Vector4,
|
|
134
137
|
normal: Vector3,
|
|
@@ -295,29 +298,29 @@ The following table shows compile performance for various JSON Schema structures
|
|
|
295
298
|
┌──────────────────────┬─────────────┬─────────────┐
|
|
296
299
|
│ Compile │ TB1X │ AJV8 │
|
|
297
300
|
├──────────────────────┼─────────────┼─────────────┤
|
|
298
|
-
│ Boolean │
|
|
299
|
-
│ Number │
|
|
300
|
-
│ String │
|
|
301
|
-
│ Null │
|
|
302
|
-
│ Literal_String │
|
|
303
|
-
│ Literal_Number │
|
|
304
|
-
│ Literal_Boolean │
|
|
305
|
-
│ Pattern │
|
|
306
|
-
│ Object_Open │
|
|
307
|
-
│ Object_Close │
|
|
308
|
-
│ Object_Vector3 │
|
|
309
|
-
│ Object_Basis3 │
|
|
310
|
-
│ Intersect_And │
|
|
311
|
-
│ Intersect_Structural │
|
|
312
|
-
│ Union_Or │
|
|
313
|
-
│ Union_Structural │
|
|
314
|
-
│ Tuple_Values │
|
|
315
|
-
│ Tuple_Objects │
|
|
316
|
-
│ Array_Numbers_4 │
|
|
317
|
-
│ Array_Numbers_8 │
|
|
318
|
-
│ Array_Numbers_16 │
|
|
319
|
-
│ Array_Objects_Open │
|
|
320
|
-
│ Array_Objects_Close │
|
|
301
|
+
│ Boolean │ 29.2K ops/s │ 7.1K ops/s │
|
|
302
|
+
│ Number │ 34.5K ops/s │ 7.6K ops/s │
|
|
303
|
+
│ String │ 48.9K ops/s │ 8.7K ops/s │
|
|
304
|
+
│ Null │ 39.6K ops/s │ 7.6K ops/s │
|
|
305
|
+
│ Literal_String │ 46.8K ops/s │ 6.8K ops/s │
|
|
306
|
+
│ Literal_Number │ 48.3K ops/s │ 7.4K ops/s │
|
|
307
|
+
│ Literal_Boolean │ 48.8K ops/s │ 7.3K ops/s │
|
|
308
|
+
│ Pattern │ 32.5K ops/s │ 6.1K ops/s │
|
|
309
|
+
│ Object_Open │ 6.6K ops/s │ 1.4K ops/s │
|
|
310
|
+
│ Object_Close │ 7.6K ops/s │ 1K ops/s │
|
|
311
|
+
│ Object_Vector3 │ 20.8K ops/s │ 2.8K ops/s │
|
|
312
|
+
│ Object_Basis3 │ 7.5K ops/s │ 1K ops/s │
|
|
313
|
+
│ Intersect_And │ 23K ops/s │ 3.9K ops/s │
|
|
314
|
+
│ Intersect_Structural │ 8.7K ops/s │ 1.2K ops/s │
|
|
315
|
+
│ Union_Or │ 17.9K ops/s │ 3.4K ops/s │
|
|
316
|
+
│ Union_Structural │ 11.3K ops/s │ 2.1K ops/s │
|
|
317
|
+
│ Tuple_Values │ 9.6K ops/s │ 2.1K ops/s │
|
|
318
|
+
│ Tuple_Objects │ 2.1K ops/s │ 350 ops/s │
|
|
319
|
+
│ Array_Numbers_4 │ 33.6K ops/s │ 4.2K ops/s │
|
|
320
|
+
│ Array_Numbers_8 │ 39K ops/s │ 3.7K ops/s │
|
|
321
|
+
│ Array_Numbers_16 │ 29.6K ops/s │ 3.8K ops/s │
|
|
322
|
+
│ Array_Objects_Open │ 7.7K ops/s │ 833 ops/s │
|
|
323
|
+
│ Array_Objects_Close │ 7.6K ops/s │ 860 ops/s │
|
|
321
324
|
└──────────────────────┴─────────────┴─────────────┘
|
|
322
325
|
```
|
|
323
326
|
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/diffs",
|
|
3
|
-
"version": "2026.7.
|
|
3
|
+
"version": "2026.7.33",
|
|
4
4
|
"description": "OpenClaw read-only diff viewer plugin and file renderer for agents.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@pierre/diffs": "1.2.12",
|
|
12
|
-
"@shikijs/langs": "4.3.
|
|
13
|
-
"playwright-core": "1.
|
|
14
|
-
"typebox": "1.3.
|
|
12
|
+
"@shikijs/langs": "4.3.0",
|
|
13
|
+
"playwright-core": "1.61.1",
|
|
14
|
+
"typebox": "1.3.3",
|
|
15
15
|
"zod": "4.4.3"
|
|
16
16
|
},
|
|
17
17
|
"openclaw": {
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
"minHostVersion": ">=2026.4.30"
|
|
26
26
|
},
|
|
27
27
|
"compat": {
|
|
28
|
-
"pluginApi": ">=2026.7.
|
|
28
|
+
"pluginApi": ">=2026.7.33"
|
|
29
29
|
},
|
|
30
30
|
"assetScripts": {
|
|
31
31
|
"build": "node ../../scripts/build-diffs-viewer-runtime.mjs curated"
|
|
32
32
|
},
|
|
33
33
|
"build": {
|
|
34
|
-
"openclawVersion": "2026.7.
|
|
34
|
+
"openclawVersion": "2026.7.33",
|
|
35
35
|
"staticAssets": [
|
|
36
36
|
{
|
|
37
37
|
"source": "./assets/viewer-runtime.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"skills/**"
|
|
55
55
|
],
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"openclaw": ">=2026.7.
|
|
57
|
+
"openclaw": ">=2026.7.33"
|
|
58
58
|
},
|
|
59
59
|
"peerDependenciesMeta": {
|
|
60
60
|
"openclaw": {
|
package/skills/diffs/SKILL.md
CHANGED
|
@@ -9,14 +9,14 @@ The `diffs` tool accepts either `before` + `after` text, or a unified `patch` st
|
|
|
9
9
|
|
|
10
10
|
Check `details.changed`: identical before/after input returns `false` without creating an artifact; rendered results return `true`.
|
|
11
11
|
|
|
12
|
-
Use `mode=view` when you want an interactive gateway-hosted viewer. After the tool returns,
|
|
12
|
+
Use `mode=view` when you want an interactive gateway-hosted viewer. After the tool returns, use `details.viewerUrl` with the canvas tool via `canvas present` or `canvas navigate`.
|
|
13
13
|
If the deployment uses a loopback trusted proxy (for example Tailscale Serve with `gateway.trustedProxies` including `127.0.0.1`), raw loopback viewer requests can fail closed without forwarded client-IP headers. In that topology, prefer `mode=file` / `mode=both`, or use a configured `viewerBaseUrl` / explicit proxy/public `baseUrl` when you need a shareable viewer URL.
|
|
14
14
|
|
|
15
15
|
Use `mode=file` when you need a rendered file artifact. Set `fileFormat=png` (default) or `fileFormat=pdf`. The tool result includes `details.filePath`.
|
|
16
16
|
|
|
17
17
|
For large or high-fidelity files, use `fileQuality` (`standard`|`hq`|`print`) and optionally override `fileScale`/`fileMaxWidth`.
|
|
18
18
|
|
|
19
|
-
When you need to deliver the rendered file to a user or channel, do not rely on the raw tool-result renderer. Instead,
|
|
19
|
+
When you need to deliver the rendered file to a user or channel, do not rely on the raw tool-result renderer. Instead, call the `message` tool and pass `details.filePath` through `path` or `filePath`.
|
|
20
20
|
|
|
21
21
|
Use `mode=both` when you want both the gateway viewer URL and the rendered artifact.
|
|
22
22
|
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: playwright-component-testing
|
|
3
|
-
description: Set up component testing with Playwright using a story gallery — scaffold stories and a gallery dev page driven by the built-in mount fixture, no dedicated component-testing runtime. Use when asked to test React or Vue components in isolation with Playwright, or to migrate off @playwright/experimental-ct-react / -vue.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Component Testing with Playwright
|
|
7
|
-
|
|
8
|
-
Test components with regular Playwright e2e tests against a small **story gallery** page hosted by the app's own dev server. No extra test runner, bundler integration or npm packages are required.
|
|
9
|
-
|
|
10
|
-
## Concept
|
|
11
|
-
|
|
12
|
-
- A **story** is a tiny wrapper component that embeds the component under test in one specific scenario: hard-coded props, mock data, providers, recorded callbacks. Stories live next to the component in `*.story.tsx` (or `.ts`/`.jsx`/`.js`/`.vue`) files; each named export is one story.
|
|
13
|
-
- The **gallery** is a single page you implement to `references/gallery-spec.md`: it exposes `window.mount(params)` / `window.unmount()` that render a story — resolved from your story files (e.g. with `import.meta.glob`) — into `#root`. It is framework-specific and yours to own — there is no template to copy for it.
|
|
14
|
-
- Tests are plain Playwright tests. The built-in **`mount(storyId, props?)` fixture** (from `@playwright/test`) drives the gallery's `window.mount` and returns a `Locator` for the gallery root (`#root`). Scope the queries from there — `component.getByRole('button').click()`, not `component.click()`. Nothing to scaffold for it.
|
|
15
|
-
|
|
16
|
-
Everything the component needs must be set up *inside the story* (it runs in the browser); everything the test asserts must be observable *through the page* (DOM, URL, network). Where the component takes callbacks, the story creates the state, provides the callbacks and records the state into a hidden form for the test to assert on. `mount(id, props)` passes plain serializable `props` to the story.
|
|
17
|
-
|
|
18
|
-
## Setup workflow
|
|
19
|
-
|
|
20
|
-
1. **Detect the framework and bundler.** React vs Vue decides the framework notes and example story to follow. Then:
|
|
21
|
-
- **App runs on Vite** (has `vite.config.*`): the gallery is served by the existing dev server at `/playwright/gallery/index.html` — Vite serves any `.html` file under the project root, the app's plugins/aliases/CSS apply automatically, and `vite build` ignores it. No extra server needed.
|
|
22
|
-
- **Anything else** (Next.js, webpack, no dev server): run a small standalone dev server (e.g. Vite) that serves the gallery page, and point `baseURL` at it. Requires `vite` and the framework plugin as devDependencies.
|
|
23
|
-
2. **Implement the gallery** to `references/gallery-spec.md`: a page at `<project>/playwright/gallery/` that renders the requested story into `#root`. Start from the worked example in the spec and the framework notes in `references/react.md` / `references/vue.md`. Keep story discovery (`import.meta.glob`) and the framework mount here — this is the only framework-specific glue, so keep it small. Import the app's global CSS the same way the app's own entry does.
|
|
24
|
-
3. **Configure Playwright** — add to `playwright.config.ts`:
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
projects: [
|
|
28
|
-
{
|
|
29
|
-
name: 'components',
|
|
30
|
-
testDir: './tests/components',
|
|
31
|
-
use: { ...devices['Desktop Chrome'], baseURL: 'http://localhost:5173/playwright/gallery/index.html', serviceWorkers: 'block', reuseContext: true },
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
webServer: {
|
|
35
|
-
command: 'npm run dev', // or: npx vite --config playwright/vite.config.ts
|
|
36
|
-
url: 'http://localhost:5173/playwright/gallery/index.html', // standalone server: http://localhost:3100/playwright/gallery/index.html
|
|
37
|
-
reuseExistingServer: !process.env.CI,
|
|
38
|
-
},
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Match the port to the dev server. `mount` navigates to `baseURL`, so set `baseURL` to the gallery's URL. `serviceWorkers: 'block'` keeps the app's own service worker from serving cached responses that would shadow your `page.route()` mocks. `reuseContext: true` reuses the browser context across tests in a worker (as the old component-testing runtime did) — a large speedup for component suites. If the config already has projects/webServer, merge instead of replacing.
|
|
42
|
-
4. **Write a first story** next to an existing component, modeled on `templates/<react|vue>/Button.story.*`.
|
|
43
|
-
5. **Write a first spec**, modeled on `templates/react/button.spec.ts`, importing `test`/`expect` from `@playwright/test`.
|
|
44
|
-
6. **Run**: `npx playwright test --project=components`. Open `http://localhost:5173/playwright/gallery/index.html` in a browser to eyeball all stories.
|
|
45
|
-
|
|
46
|
-
## Conventions
|
|
47
|
-
|
|
48
|
-
- Story id: path under `src/` without the `.story.*` extension, plus the export name — `src/components/Button.story.tsx` export `Primary` → `components/Button/Primary`. Any unique suffix works too: `mount('Button/Primary')`. A `.story.vue` single-file component is one story, addressable by its path alone (its `default` export).
|
|
49
|
-
- One export per scenario. Prefer a new story export over parameterizing an existing one — stories are greppable, reviewable documentation of component states.
|
|
50
|
-
|
|
51
|
-
## Testing patterns
|
|
52
|
-
|
|
53
|
-
Examples are React; the Vue equivalents differ only in story syntax.
|
|
54
|
-
|
|
55
|
-
### Callbacks and events
|
|
56
|
-
|
|
57
|
-
**The story owns the state and provides the callbacks.** Where the component takes callbacks, create the state inside the story, wire the callbacks to it, and record the state into a hidden form next to the component. Tests perform operations and assert on the recorded values:
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
export const Stateful = () => {
|
|
61
|
-
const [expanded, setExpanded] = useState(false);
|
|
62
|
-
return <>
|
|
63
|
-
<Expandable expanded={expanded} setExpanded={setExpanded} title="Title">Details</Expandable>
|
|
64
|
-
<form hidden><input data-testid="expanded" readOnly value={String(expanded)} /></form>
|
|
65
|
-
</>;
|
|
66
|
-
};
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
test('click should expand', async ({ mount }) => {
|
|
71
|
-
const component = await mount('components/Expandable/Stateful');
|
|
72
|
-
await component.locator('.codicon-chevron-right').click();
|
|
73
|
-
await expect(component.getByTestId('expanded')).toHaveValue('true');
|
|
74
|
-
});
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
This keeps the whole scenario in the browser: no callback marshalling, the story doubles as documentation, and the recorded state is visible when eyeballing the gallery. Record each observed value in its own `data-testid` input (`String(...)` or `JSON.stringify(...)` for payloads) and assert with `toHaveValue()` — a web-first assertion that retries until the state lands. The negative direction works the same way: perform the operation, then assert the value did **not** change.
|
|
78
|
-
|
|
79
|
-
### Per-test props
|
|
80
|
-
|
|
81
|
-
When a scenario is genuinely parametric (e.g. a boundary-value sweep), pass props as the second argument to `mount`; the gallery hands them to the story as its props. Keep props to plain serializable data — callbacks belong inside the story.
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
export const WithTitle = ({ title = 'Default' }: { title?: string }) =>
|
|
85
|
-
<Button title={title} />;
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
const component = await mount('components/Button/WithTitle', { title: 'Hello' });
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
`mount` is generic over the story: pass the story type as a template argument to type-check the props (and `update()`):
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
import type { WithTitle } from './Button.story';
|
|
96
|
-
|
|
97
|
-
const component = await mount<typeof WithTitle>('components/Button/WithTitle', { title: 'Hello' });
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
This works for React and Vue stories alike; Vue stories must additionally declare the props at runtime — see the `Typed props` sections in `references/react.md` / `references/vue.md`.
|
|
101
|
-
|
|
102
|
-
### Prop transitions with `update()`
|
|
103
|
-
|
|
104
|
-
To test how a component reacts to a prop change **without remounting** (state preserved), call `component.update(newProps)` — it re-renders the same story with new props on the existing root:
|
|
105
|
-
|
|
106
|
-
```ts
|
|
107
|
-
const component = await mount('components/Counter/Default', { value: 1 });
|
|
108
|
-
await expect(component.getByTestId('value')).toHaveText('1');
|
|
109
|
-
await component.update({ value: 2 });
|
|
110
|
-
await expect(component.getByTestId('value')).toHaveText('2');
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
This requires the gallery to reuse its root/instance (`references/gallery-spec.md`); state survives as long as the story stays the same.
|
|
114
|
-
|
|
115
|
-
### Multiple states in one test
|
|
116
|
-
|
|
117
|
-
Each `mount()` navigates fresh, so tests are fully isolated and mounting several stories in one test is cheap:
|
|
118
|
-
|
|
119
|
-
```ts
|
|
120
|
-
await expect(await mount('Button/Primary')).toHaveScreenshot('primary.png');
|
|
121
|
-
await expect(await mount('Button/Disabled')).toHaveScreenshot('disabled.png');
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
For visual comparison, screenshot the returned root locator (as above), not the page, to avoid asserting on browser chrome.
|
|
125
|
-
|
|
126
|
-
### Network mocking
|
|
127
|
-
|
|
128
|
-
Use `page.route()` as usual — register routes before `mount()`, since mounting navigates. `serviceWorkers: 'block'` (set in the config above) keeps the app's own service worker from serving cached responses that shadow the routes. Teams with MSW handler libraries can start the worker inside a story or decorator instead.
|
|
129
|
-
|
|
130
|
-
### Debugging stories
|
|
131
|
-
|
|
132
|
-
Open your gallery URL (`baseURL`) in a browser and call `await window.mount({ story: 'components/Button/Primary' })` from the devtools console — that is exactly what the `mount` fixture does. An unknown story rejects `window.mount`, which surfaces as the test's `mount()` throwing with a real stack. To browse without the console, give your gallery an optional index page.
|
|
133
|
-
|
|
134
|
-
## Decision points
|
|
135
|
-
|
|
136
|
-
- **Monorepos / non-`src` layouts**: change the glob and the id derivation in your gallery (`references/gallery-spec.md`) to match.
|
|
137
|
-
- **Global providers** (theme, i18n, store, router): create a shared `decorator` helper next to the gallery and wrap components in stories; see `references/react.md` / `references/vue.md`.
|
|
138
|
-
## References
|
|
139
|
-
|
|
140
|
-
- `references/gallery-spec.md` — the gallery endpoint contract to implement (**start here**).
|
|
141
|
-
- `references/react.md` — React walkthrough: providers, StrictMode, CSS.
|
|
142
|
-
- `references/vue.md` — Vue walkthrough: `.story.ts` and `.story.vue` stories, plugins.
|
|
143
|
-
- `references/migration.md` — migrating off `@playwright/experimental-ct-react` / `-vue`.
|