waygraph 0.15.24 → 0.15.26
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/engine/blocks/effect.d.ts +41 -0
- package/dist/engine/blocks/effect.js +23 -0
- package/dist/engine/blocks/method.d.ts +90 -0
- package/dist/engine/blocks/method.js +70 -0
- package/dist/engine/blocks/nav.d.ts +138 -0
- package/dist/engine/blocks/nav.js +110 -0
- package/dist/engine/blocks/page.d.ts +59 -0
- package/dist/engine/blocks/page.js +91 -0
- package/dist/engine/compose.d.ts +75 -0
- package/dist/engine/compose.js +76 -0
- package/dist/engine/config.d.ts +55 -0
- package/dist/engine/config.js +17 -0
- package/dist/engine/core.d.ts +92 -0
- package/dist/engine/core.js +256 -0
- package/dist/engine/engine-class.d.ts +289 -0
- package/dist/engine/engine-class.js +257 -0
- package/dist/engine/flow.d.ts +266 -0
- package/dist/engine/flow.js +387 -0
- package/dist/engine/locate.d.ts +26 -0
- package/dist/engine/locate.js +62 -0
- package/dist/engine/run-graph.d.ts +147 -0
- package/dist/engine/run-graph.js +223 -0
- package/dist/engine.d.ts +11 -1224
- package/dist/engine.js +12 -1550
- package/dist/highlights/css.d.ts +14 -0
- package/dist/highlights/css.js +58 -0
- package/dist/highlights/demo-pace.d.ts +56 -0
- package/dist/highlights/demo-pace.js +184 -0
- package/dist/highlights/device.d.ts +29 -0
- package/dist/highlights/device.js +171 -0
- package/dist/highlights/merge.d.ts +8 -0
- package/dist/highlights/merge.js +173 -0
- package/dist/highlights/run-phase.d.ts +43 -0
- package/dist/highlights/run-phase.js +211 -0
- package/dist/highlights/stub-ctx.d.ts +10 -0
- package/dist/highlights/stub-ctx.js +281 -0
- package/dist/highlights/style.d.ts +27 -0
- package/dist/highlights/style.js +84 -0
- package/dist/highlights/todo-dock.d.ts +52 -0
- package/dist/highlights/todo-dock.js +248 -0
- package/dist/highlights/types.d.ts +536 -0
- package/dist/highlights/types.js +1 -0
- package/dist/highlights.d.ts +9 -734
- package/dist/highlights.js +10 -1416
- package/examples/saucedemo/.waygraph-auto/008f4e6e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/22fefa13.log +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Block, Checkpoint, DefinedBlock } from "../../types.js";
|
|
2
|
+
import type { MemKey } from "../../mem-page.js";
|
|
3
|
+
import type { Trait } from "../../trait.js";
|
|
4
|
+
import { defineBlock } from "../core.js";
|
|
5
|
+
/**
|
|
6
|
+
* TypeScript salt over {@link defineBlock}: same runtime Block, but the type
|
|
7
|
+
* forces `requires` + `instanceOptions` so `waygraph auto` can list one menu
|
|
8
|
+
* row per live instance (add/remove/toggle). Not a separate engine concept -
|
|
9
|
+
* everything is still a Block.
|
|
10
|
+
*/
|
|
11
|
+
export type EffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = Omit<DefinedBlock<In, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
12
|
+
readonly __wgFactory?: "effect";
|
|
13
|
+
requires: readonly MemKey<any>[];
|
|
14
|
+
instanceOptions: NonNullable<Block<In, Out>["instanceOptions"]>;
|
|
15
|
+
withVerify(verify: Trait[] | ((out: Out) => Trait[])): EffectBlock<In, Out>;
|
|
16
|
+
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): EffectBlock<In, Out>;
|
|
17
|
+
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): EffectBlock<In, Out>;
|
|
18
|
+
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
19
|
+
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
20
|
+
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
21
|
+
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
22
|
+
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
23
|
+
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
24
|
+
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
25
|
+
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
26
|
+
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
27
|
+
};
|
|
28
|
+
/** @deprecated Prefer {@link EffectBlock} - same type; Mem* was an early name. */
|
|
29
|
+
export type MemEffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = EffectBlock<In, Out>;
|
|
30
|
+
/**
|
|
31
|
+
* {@link defineBlock} constrained for effect-style instance menus: `requires` +
|
|
32
|
+
* `instanceOptions` are mandatory. Prefer this when the Block adds / removes /
|
|
33
|
+
* toggles a live instance rather than navigating. Runtime result is an ordinary
|
|
34
|
+
* Block - the helper is TypeScript salt only.
|
|
35
|
+
*/
|
|
36
|
+
export declare function defineEffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(base: Parameters<typeof defineBlock<In, Out>>[0] & {
|
|
37
|
+
requires: readonly MemKey<any>[];
|
|
38
|
+
instanceOptions: NonNullable<Block<In, Out>["instanceOptions"]>;
|
|
39
|
+
}): EffectBlock<In, Out>;
|
|
40
|
+
/** @deprecated Prefer {@link defineEffectBlock} - identical helper. */
|
|
41
|
+
export declare const defineMemEffectBlock: typeof defineEffectBlock;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineBlock } from "../core.js";
|
|
2
|
+
/**
|
|
3
|
+
* {@link defineBlock} constrained for effect-style instance menus: `requires` +
|
|
4
|
+
* `instanceOptions` are mandatory. Prefer this when the Block adds / removes /
|
|
5
|
+
* toggles a live instance rather than navigating. Runtime result is an ordinary
|
|
6
|
+
* Block - the helper is TypeScript salt only.
|
|
7
|
+
*/
|
|
8
|
+
export function defineEffectBlock(base) {
|
|
9
|
+
const built = defineBlock(base);
|
|
10
|
+
Object.defineProperty(built, "__waygraphMemKind", {
|
|
11
|
+
value: "effect",
|
|
12
|
+
enumerable: false,
|
|
13
|
+
configurable: false,
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(built, "__waygraphSalt", {
|
|
16
|
+
value: "effect",
|
|
17
|
+
enumerable: false,
|
|
18
|
+
configurable: false,
|
|
19
|
+
});
|
|
20
|
+
return built;
|
|
21
|
+
}
|
|
22
|
+
/** @deprecated Prefer {@link defineEffectBlock} - identical helper. */
|
|
23
|
+
export const defineMemEffectBlock = defineEffectBlock;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { Checkpoint, DefinedBlock } from "../../types.js";
|
|
2
|
+
import type { Trait } from "../../trait.js";
|
|
3
|
+
import { defineBlock } from "../core.js";
|
|
4
|
+
import type { MemKey } from "../../mem-page.js";
|
|
5
|
+
/**
|
|
6
|
+
* TypeScript salt over {@link defineBlock} for one-shot non-nav app steps
|
|
7
|
+
* (submit, upload, finish, logout) - **methods** on a page. Same runtime Block;
|
|
8
|
+
* marks `__waygraphSalt = "method"` so auto/docs can tell Method from bare
|
|
9
|
+
* {@link defineBlock}. Does not force `instanceOptions` - use
|
|
10
|
+
* {@link defineEffectBlock} when the auto menu should spawn one row per live
|
|
11
|
+
* DOM instance. Prefer hanging methods off a {@link definePageBlock} hub.
|
|
12
|
+
*/
|
|
13
|
+
export type MethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = Omit<DefinedBlock<In, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
14
|
+
readonly __wgFactory?: "method";
|
|
15
|
+
withVerify(verify: Trait[] | ((out: Out) => Trait[])): MethodBlock<In, Out>;
|
|
16
|
+
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): MethodBlock<In, Out>;
|
|
17
|
+
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): MethodBlock<In, Out>;
|
|
18
|
+
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
19
|
+
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
20
|
+
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
21
|
+
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
22
|
+
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
23
|
+
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
24
|
+
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
25
|
+
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
26
|
+
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
27
|
+
};
|
|
28
|
+
/** @deprecated Prefer {@link MethodBlock} - same type; Action was the 0.7 name. */
|
|
29
|
+
export type ActionBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = MethodBlock<In, Out>;
|
|
30
|
+
export declare function defineMethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(base: Parameters<typeof defineBlock<In, Out>>[0]): MethodBlock<In, Out>;
|
|
31
|
+
/** @deprecated Prefer {@link defineMethodBlock} - identical helper (0.7 name). */
|
|
32
|
+
export declare const defineActionBlock: typeof defineMethodBlock;
|
|
33
|
+
export interface AssertBlockOptions<Out extends Checkpoint<string> = Checkpoint<string>> {
|
|
34
|
+
name: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
/** Self-loop target - the Checkpoint this assertion runs on and returns to. */
|
|
37
|
+
checkpoint: Out["__state"];
|
|
38
|
+
/**
|
|
39
|
+
* Shorthand for the wait-then-assert shape found repeatedly in hand-written
|
|
40
|
+
* assertion Blocks: waits for a heading with this accessible name before
|
|
41
|
+
* `verify` runs. Omit for a pure "assert whatever is already on the page"
|
|
42
|
+
* check with no wait. Not a general `act()` override - a Block that needs
|
|
43
|
+
* more than this stays a plain `defineMethodBlock`.
|
|
44
|
+
*/
|
|
45
|
+
waitForHeading?: string;
|
|
46
|
+
verify: Trait[] | ((out: Out) => Trait[]);
|
|
47
|
+
/** Mem keys this assertion's `verify` reads (e.g. a mem-aware Trait) - checked by preflight before the flow runs. */
|
|
48
|
+
requires?: readonly MemKey<any>[];
|
|
49
|
+
stubBefore?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
50
|
+
stubAfter?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
51
|
+
stubOnError?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
52
|
+
/** Multi-step yap slides (demo only) - same field `Instruction.slides` exposes elsewhere. */
|
|
53
|
+
slides?: import("../../highlights.js").WaygraphSlidesOrFn<Out>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Sugar for a self-loop-only "pure assertion" Block: no hand-written
|
|
57
|
+
* `act`/`resolve`, just a name, a `checkpoint` tag, and a `verify` array.
|
|
58
|
+
* `resolve` is generated from the one `checkpoint` field given, closing the
|
|
59
|
+
* copy/rename footgun where a hand-restated checkpoint string can silently
|
|
60
|
+
* drift wrong across a copy/pasted file. Mirrors `definePageBlock`'s own
|
|
61
|
+
* construction pattern (flat options in, `defineBlock` built internally).
|
|
62
|
+
* See openspec/changes/waygraph-agent-skill-hardening/spec.md.
|
|
63
|
+
* @example
|
|
64
|
+
* defineAssertBlock({
|
|
65
|
+
* name: "assert-raw-materials-table",
|
|
66
|
+
* checkpoint: "RawMaterials",
|
|
67
|
+
* waitForHeading: "Raw Materials & Lead Times",
|
|
68
|
+
* verify: [Trait.visible(RawMaterialsSel.reorderBadge)],
|
|
69
|
+
* });
|
|
70
|
+
*/
|
|
71
|
+
export declare function defineAssertBlock<Out extends Checkpoint<string> = Checkpoint<string>>(options: AssertBlockOptions<Out>): AssertBlock<Out>;
|
|
72
|
+
/**
|
|
73
|
+
* Self-loop verify Block from {@link defineAssertBlock}. Branded for
|
|
74
|
+
* {@link MapBuilder.assert} (not accepted by `.method()`).
|
|
75
|
+
*/
|
|
76
|
+
export type AssertBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Out, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
77
|
+
readonly __wgFactory?: "assert";
|
|
78
|
+
withVerify(verify: Trait[] | ((out: Out) => Trait[])): AssertBlock<Out>;
|
|
79
|
+
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): AssertBlock<Out>;
|
|
80
|
+
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): AssertBlock<Out>;
|
|
81
|
+
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
82
|
+
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
83
|
+
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
84
|
+
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
85
|
+
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
86
|
+
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
87
|
+
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
88
|
+
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
89
|
+
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
90
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Split out of the former 2,900-line engine.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
|
+
import { checkpoint } from "../../types.js";
|
|
3
|
+
import { defineBlock } from "../core.js";
|
|
4
|
+
export function defineMethodBlock(base) {
|
|
5
|
+
const built = defineBlock(base);
|
|
6
|
+
Object.defineProperty(built, "__waygraphSalt", {
|
|
7
|
+
value: "method",
|
|
8
|
+
enumerable: false,
|
|
9
|
+
configurable: false,
|
|
10
|
+
});
|
|
11
|
+
return built;
|
|
12
|
+
}
|
|
13
|
+
/** @deprecated Prefer {@link defineMethodBlock} - identical helper (0.7 name). */
|
|
14
|
+
export const defineActionBlock = defineMethodBlock;
|
|
15
|
+
/**
|
|
16
|
+
* Sugar for a self-loop-only "pure assertion" Block: no hand-written
|
|
17
|
+
* `act`/`resolve`, just a name, a `checkpoint` tag, and a `verify` array.
|
|
18
|
+
* `resolve` is generated from the one `checkpoint` field given, closing the
|
|
19
|
+
* copy/rename footgun where a hand-restated checkpoint string can silently
|
|
20
|
+
* drift wrong across a copy/pasted file. Mirrors `definePageBlock`'s own
|
|
21
|
+
* construction pattern (flat options in, `defineBlock` built internally).
|
|
22
|
+
* See openspec/changes/waygraph-agent-skill-hardening/spec.md.
|
|
23
|
+
* @example
|
|
24
|
+
* defineAssertBlock({
|
|
25
|
+
* name: "assert-raw-materials-table",
|
|
26
|
+
* checkpoint: "RawMaterials",
|
|
27
|
+
* waitForHeading: "Raw Materials & Lead Times",
|
|
28
|
+
* verify: [Trait.visible(RawMaterialsSel.reorderBadge)],
|
|
29
|
+
* });
|
|
30
|
+
*/
|
|
31
|
+
export function defineAssertBlock(options) {
|
|
32
|
+
const built = defineMethodBlock({
|
|
33
|
+
name: options.name,
|
|
34
|
+
...(options.description ? { description: options.description } : {}),
|
|
35
|
+
...(options.requires ? { requires: options.requires } : {}),
|
|
36
|
+
instruction: {
|
|
37
|
+
async act(page) {
|
|
38
|
+
if (options.waitForHeading !== undefined) {
|
|
39
|
+
await page.getByRole("heading", { name: options.waitForHeading }).waitFor();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
resolve: () => checkpoint(options.checkpoint),
|
|
43
|
+
verify: options.verify,
|
|
44
|
+
...(options.stubBefore ? { stubBefore: options.stubBefore } : {}),
|
|
45
|
+
...(options.stubAfter ? { stubAfter: options.stubAfter } : {}),
|
|
46
|
+
...(options.stubOnError ? { stubOnError: options.stubOnError } : {}),
|
|
47
|
+
...(options.slides ? { slides: options.slides } : {}),
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
// Real bug this closes: `waygraph graph`'s static discovery only knows
|
|
51
|
+
// how to read a Block's Checkpoint tags from an EXPLICIT `<In, Out>`
|
|
52
|
+
// generic written in the source text (or, for Nav/Page Blocks, by calling
|
|
53
|
+
// their own input-independent `resolve()` directly). `defineAssertBlock`'s
|
|
54
|
+
// whole point is skipping that generic - called exactly as documented
|
|
55
|
+
// (`defineAssertBlock({ name, checkpoint, verify })`, no generics), it was
|
|
56
|
+
// silently invisible to both `waygraph graph` and the live Pilot menu
|
|
57
|
+
// ("2 Block(s) skipped (Out not resolvable)", confirmed live against a
|
|
58
|
+
// real veciro-waygraph session). `resolve()` here is ALSO input-
|
|
59
|
+
// independent (always `checkpoint(options.checkpoint)`), so the same
|
|
60
|
+
// resolve()-calling path Nav/Page Blocks already use is reused via this
|
|
61
|
+
// marker instead of requiring authors to write generics just to be found.
|
|
62
|
+
Object.defineProperty(built, "__waygraphKind", {
|
|
63
|
+
value: "assert",
|
|
64
|
+
enumerable: false,
|
|
65
|
+
configurable: false,
|
|
66
|
+
});
|
|
67
|
+
// Brand for map().assert() - distinct from MethodBlock so .method(assert)
|
|
68
|
+
// is a compile error even though runtime still carries method salt.
|
|
69
|
+
return built;
|
|
70
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { Block, Checkpoint, DefinedBlock, WaygraphHighlight } from "../../types.js";
|
|
2
|
+
import type { Trait } from "../../trait.js";
|
|
3
|
+
import { MemPage } from "../../mem-page.js";
|
|
4
|
+
import type { MemKey } from "../../mem-page.js";
|
|
5
|
+
/**
|
|
6
|
+
* A Block whose only possible action is navigating to a URL - built via
|
|
7
|
+
* {@link defineNavBlock}, never with a hand-authored `act()`. Extends `Block`
|
|
8
|
+
* (same shape `DefinedBlock`/`ComposedBlock` already use), so it drops into
|
|
9
|
+
* `defineFlow([...])`, `connect()`, `composeBlock()` exactly like any other
|
|
10
|
+
* Block - no special-casing needed anywhere that only expects a `Block`.
|
|
11
|
+
* See `openspec/specs/nav-block-and-check/spec.md` for why this exists.
|
|
12
|
+
*
|
|
13
|
+
* `__wgFactory` is a TypeScript-only brand so {@link MapBuilder.gotoPage} /
|
|
14
|
+
* {@link MapBuilder.gotoExternal} can reject Assert/Method Blocks at compile
|
|
15
|
+
* time (runtime still checks `__waygraphKind`). Decorate methods are re-stated
|
|
16
|
+
* (via Omit) so `.stubBefore()` / `.withVerify()` keep the brand.
|
|
17
|
+
*/
|
|
18
|
+
export type NavBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkpoint<string>, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
19
|
+
readonly __wgFactory?: "nav";
|
|
20
|
+
withVerify(verify: Trait[] | ((out: Out) => Trait[])): NavBlock<Out>;
|
|
21
|
+
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): NavBlock<Out>;
|
|
22
|
+
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): NavBlock<Out>;
|
|
23
|
+
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
24
|
+
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
25
|
+
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
26
|
+
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
27
|
+
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
28
|
+
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
29
|
+
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
30
|
+
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
31
|
+
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* `defineNavBlock`'s own options - exactly one of `url`/`click` required,
|
|
35
|
+
* enforced at compile time (giving both, or neither, is a type error - see
|
|
36
|
+
* `typecheck/nav-block.types.ts`). `checkpoint` is the tag this NavBlock
|
|
37
|
+
* resolves to once navigation completes - a NavBlock never branches on
|
|
38
|
+
* observed evidence the way a regular Block can, so there's no `resolve`
|
|
39
|
+
* logic to author; it always just declares "arrived."
|
|
40
|
+
*/
|
|
41
|
+
export type NavBlockOptions<Out extends Checkpoint<string>> = {
|
|
42
|
+
name: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
checkpoint: Out["__state"];
|
|
45
|
+
requires?: readonly MemKey<any>[];
|
|
46
|
+
verify?: Trait[] | ((out: Out) => Trait[]);
|
|
47
|
+
stubBefore?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
48
|
+
stubAfter?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
49
|
+
stubOnError?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
50
|
+
/** @deprecated Prefer stubAfter. */
|
|
51
|
+
highlights?: readonly WaygraphHighlight[] | ((out: Out) => readonly WaygraphHighlight[]);
|
|
52
|
+
/**
|
|
53
|
+
* Live per-instance menu rows for `waygraph auto` (see {@link Block.instanceOptions}).
|
|
54
|
+
* When set, the explore menu lists one row per option instead of a single
|
|
55
|
+
* generic nav edge - used by {@link defineMemNavBlock}.
|
|
56
|
+
*/
|
|
57
|
+
instanceOptions?: Block<Checkpoint<string>, Out>["instanceOptions"];
|
|
58
|
+
} & ({
|
|
59
|
+
/**
|
|
60
|
+
* Direct URL navigation. Accepts a plain string or a function
|
|
61
|
+
* `(mem) => string` for parameterized routes (e.g.
|
|
62
|
+
* `/dashboard/requests/:id` with a real id read from mem). The
|
|
63
|
+
* escape hatch for the few real cases with no click path to get
|
|
64
|
+
* there (a deep link from an email, a public share link) - not for
|
|
65
|
+
* skipping past navigation an agent didn't feel like finding. Prefer
|
|
66
|
+
* `click` whenever the target app actually has one.
|
|
67
|
+
*/
|
|
68
|
+
url: string | ((mem: MemPage) => string);
|
|
69
|
+
click?: never;
|
|
70
|
+
} | {
|
|
71
|
+
/**
|
|
72
|
+
* Navigates by clicking a real element already on the page (a nav
|
|
73
|
+
* link, a sidebar item) instead of teleporting straight to a URL -
|
|
74
|
+
* the opinionated default. Accepts a Playwright selector string, or
|
|
75
|
+
* a function `(mem) => selector` for a target that depends on mem
|
|
76
|
+
* (e.g. clicking the row for a specific id). Verifying arrival is
|
|
77
|
+
* `verify`'s job (typically `Trait.url(...)`), same as a `url`-based
|
|
78
|
+
* NavBlock - the click itself is only ever awaited for its own
|
|
79
|
+
* completion, not for whatever navigation it triggers.
|
|
80
|
+
*/
|
|
81
|
+
click: string | ((mem: MemPage) => string);
|
|
82
|
+
url?: never;
|
|
83
|
+
});
|
|
84
|
+
/**
|
|
85
|
+
* Builds a {@link NavBlock}. The generated `act()` is always exactly
|
|
86
|
+
* `page.goto(url)` or `page.locator(click).click()` - never anything else,
|
|
87
|
+
* never author-supplied. Callers get a real `Page` here internally (the one
|
|
88
|
+
* legitimate place navigation belongs); `defineBlock`'s own `ActionPage`
|
|
89
|
+
* narrowing is what discourages navigation everywhere else, and never
|
|
90
|
+
* applies to this generated function since no author ever writes it by
|
|
91
|
+
* hand.
|
|
92
|
+
* @example defineNavBlock({ name: "nav-web-login", checkpoint: "LoginForm", url: "/login" })
|
|
93
|
+
* @example defineNavBlock({ name: "nav-web-request-detail", checkpoint: "RequestDetail", url: (mem) => `/dashboard/requests/${mem.get(RequestId.key)}` })
|
|
94
|
+
* @example defineNavClickBlock({ name: "nav-web-documents", checkpoint: "DocumentsList", click: "nav >> text=Documents" })
|
|
95
|
+
* For click-nav in app code prefer {@link defineNavClickBlock} (url stays here).
|
|
96
|
+
*/
|
|
97
|
+
export declare function defineNavBlock<Out extends Checkpoint<string>>(options: NavBlockOptions<Out>): NavBlock<Out>;
|
|
98
|
+
/**
|
|
99
|
+
* Click-only {@link NavBlock}. Same runtime as {@link defineNavBlock} with
|
|
100
|
+
* `click` - use this in app code so you never wonder whether a Nav is url or
|
|
101
|
+
* click (no `__waygraphNavClick` sniffing at author time). Prefer
|
|
102
|
+
* {@link defineNavBlock} only for `url` / `goto` deep links.
|
|
103
|
+
*/
|
|
104
|
+
export type NavClickBlockOptions<Out extends Checkpoint<string>> = {
|
|
105
|
+
name: string;
|
|
106
|
+
description?: string;
|
|
107
|
+
checkpoint: Out["__state"];
|
|
108
|
+
click: string | ((mem: MemPage) => string);
|
|
109
|
+
requires?: readonly MemKey<any>[];
|
|
110
|
+
verify?: Trait[] | ((out: Out) => Trait[]);
|
|
111
|
+
stubBefore?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
112
|
+
stubAfter?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
113
|
+
stubOnError?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
114
|
+
/** @deprecated Prefer stubAfter. */
|
|
115
|
+
highlights?: readonly WaygraphHighlight[] | ((out: Out) => readonly WaygraphHighlight[]);
|
|
116
|
+
instanceOptions?: Block<Checkpoint<string>, Out>["instanceOptions"];
|
|
117
|
+
};
|
|
118
|
+
export type NavClickBlock<Out extends Checkpoint<string>> = NavBlock<Out>;
|
|
119
|
+
/** @see {@link NavClickBlockOptions} */
|
|
120
|
+
export declare function defineNavClickBlock<Out extends Checkpoint<string>>(options: NavClickBlockOptions<Out>): NavClickBlock<Out>;
|
|
121
|
+
/**
|
|
122
|
+
* TypeScript salt over {@link defineNavBlock}: mem-picked destination
|
|
123
|
+
* (which product row / which request id). Still a NavBlock / Block at runtime.
|
|
124
|
+
*/
|
|
125
|
+
export type MemNavBlock<Out extends Checkpoint<string>> = NavBlock<Out> & {
|
|
126
|
+
requires: readonly MemKey<any>[];
|
|
127
|
+
instanceOptions: NonNullable<Block<Checkpoint<string>, Out>["instanceOptions"]>;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* {@link defineNavBlock} constrained to mem-picked navigation: requires +
|
|
131
|
+
* instanceOptions mandatory, and `click`/`url` should depend on that mem
|
|
132
|
+
* (typically `click: (mem) => …`). Prefer this when the Block opens one of
|
|
133
|
+
* several live rows/items rather than a fixed nav target. Still a Block.
|
|
134
|
+
*/
|
|
135
|
+
export declare function defineMemNavBlock<Out extends Checkpoint<string>>(options: NavBlockOptions<Out> & {
|
|
136
|
+
requires: readonly MemKey<any>[];
|
|
137
|
+
instanceOptions: NonNullable<Block<Checkpoint<string>, Out>["instanceOptions"]>;
|
|
138
|
+
}): MemNavBlock<Out>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Split out of the former 2,900-line engine.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
|
+
import { checkpoint } from "../../types.js";
|
|
3
|
+
import { defineBlock } from "../core.js";
|
|
4
|
+
/**
|
|
5
|
+
* Builds a {@link NavBlock}. The generated `act()` is always exactly
|
|
6
|
+
* `page.goto(url)` or `page.locator(click).click()` - never anything else,
|
|
7
|
+
* never author-supplied. Callers get a real `Page` here internally (the one
|
|
8
|
+
* legitimate place navigation belongs); `defineBlock`'s own `ActionPage`
|
|
9
|
+
* narrowing is what discourages navigation everywhere else, and never
|
|
10
|
+
* applies to this generated function since no author ever writes it by
|
|
11
|
+
* hand.
|
|
12
|
+
* @example defineNavBlock({ name: "nav-web-login", checkpoint: "LoginForm", url: "/login" })
|
|
13
|
+
* @example defineNavBlock({ name: "nav-web-request-detail", checkpoint: "RequestDetail", url: (mem) => `/dashboard/requests/${mem.get(RequestId.key)}` })
|
|
14
|
+
* @example defineNavClickBlock({ name: "nav-web-documents", checkpoint: "DocumentsList", click: "nav >> text=Documents" })
|
|
15
|
+
* For click-nav in app code prefer {@link defineNavClickBlock} (url stays here).
|
|
16
|
+
*/
|
|
17
|
+
export function defineNavBlock(options) {
|
|
18
|
+
const built = defineBlock({
|
|
19
|
+
name: options.name,
|
|
20
|
+
...(options.description ? { description: options.description } : {}),
|
|
21
|
+
...(options.requires ? { requires: options.requires } : {}),
|
|
22
|
+
...(options.instanceOptions ? { instanceOptions: options.instanceOptions } : {}),
|
|
23
|
+
instruction: {
|
|
24
|
+
async act(page, _input, mem) {
|
|
25
|
+
if (options.url !== undefined) {
|
|
26
|
+
const url = typeof options.url === "function" ? options.url(mem) : options.url;
|
|
27
|
+
await page.goto(url);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// Always Locator.click() so step-mode's demo cursor/pulse patch
|
|
31
|
+
// (instrumentInteractionHighlighting) sees NavBlock click-nav -
|
|
32
|
+
// never page.click() / goto teleport.
|
|
33
|
+
const selector = typeof options.click === "function" ? options.click(mem) : options.click;
|
|
34
|
+
await page.locator(selector).click();
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
resolve: () => checkpoint(options.checkpoint),
|
|
38
|
+
...(options.verify ? { verify: options.verify } : {}),
|
|
39
|
+
...(options.stubBefore ? { stubBefore: options.stubBefore } : {}),
|
|
40
|
+
...(options.stubAfter ? { stubAfter: options.stubAfter } : {}),
|
|
41
|
+
...(options.stubOnError ? { stubOnError: options.stubOnError } : {}),
|
|
42
|
+
...(options.highlights ? { highlights: options.highlights } : {}),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
// Non-enumerable so it never shows up in Object.keys/JSON/autocomplete -
|
|
46
|
+
// purely a runtime marker `waygraph check` (or anything else walking a
|
|
47
|
+
// project's Blocks) can test for to tell a NavBlock apart from a regular
|
|
48
|
+
// one, since the TypeScript type alone (NavBlock = DefinedBlock) doesn't
|
|
49
|
+
// survive to runtime.
|
|
50
|
+
Object.defineProperty(built, "__waygraphKind", {
|
|
51
|
+
value: "nav",
|
|
52
|
+
enumerable: false,
|
|
53
|
+
configurable: false,
|
|
54
|
+
});
|
|
55
|
+
// Demo/step tooling: remember the click selector (or factory) so
|
|
56
|
+
// overlays can label "nav click" without re-parsing source.
|
|
57
|
+
if (options.click !== undefined) {
|
|
58
|
+
Object.defineProperty(built, "__waygraphNavClick", {
|
|
59
|
+
value: options.click,
|
|
60
|
+
enumerable: false,
|
|
61
|
+
configurable: false,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Same idea, for the url case - only when it's a plain string (a
|
|
65
|
+
// function URL is mem-dependent/dynamic, can't be compared statically
|
|
66
|
+
// without running it). Real, direct request this responds to: an agent
|
|
67
|
+
// driving Blind Pilot had no structured way to ask "which of the links
|
|
68
|
+
// on THIS page are already covered by a NavBlock" without re-parsing
|
|
69
|
+
// every nav.block.ts's own source - this is what `AutoSession` now reads
|
|
70
|
+
// to warn about real, unmapped nav links found live on the page.
|
|
71
|
+
if (typeof options.url === "string") {
|
|
72
|
+
Object.defineProperty(built, "__waygraphNavUrl", {
|
|
73
|
+
value: options.url,
|
|
74
|
+
enumerable: false,
|
|
75
|
+
configurable: false,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return built;
|
|
79
|
+
}
|
|
80
|
+
/** @see {@link NavClickBlockOptions} */
|
|
81
|
+
export function defineNavClickBlock(options) {
|
|
82
|
+
return defineNavBlock({
|
|
83
|
+
name: options.name,
|
|
84
|
+
checkpoint: options.checkpoint,
|
|
85
|
+
click: options.click,
|
|
86
|
+
...(options.description ? { description: options.description } : {}),
|
|
87
|
+
...(options.requires ? { requires: options.requires } : {}),
|
|
88
|
+
...(options.verify ? { verify: options.verify } : {}),
|
|
89
|
+
...(options.stubBefore ? { stubBefore: options.stubBefore } : {}),
|
|
90
|
+
...(options.stubAfter ? { stubAfter: options.stubAfter } : {}),
|
|
91
|
+
...(options.stubOnError ? { stubOnError: options.stubOnError } : {}),
|
|
92
|
+
...(options.highlights ? { highlights: options.highlights } : {}),
|
|
93
|
+
...(options.instanceOptions ? { instanceOptions: options.instanceOptions } : {}),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* {@link defineNavBlock} constrained to mem-picked navigation: requires +
|
|
98
|
+
* instanceOptions mandatory, and `click`/`url` should depend on that mem
|
|
99
|
+
* (typically `click: (mem) => …`). Prefer this when the Block opens one of
|
|
100
|
+
* several live rows/items rather than a fixed nav target. Still a Block.
|
|
101
|
+
*/
|
|
102
|
+
export function defineMemNavBlock(options) {
|
|
103
|
+
const built = defineNavBlock(options);
|
|
104
|
+
Object.defineProperty(built, "__waygraphMemKind", {
|
|
105
|
+
value: "nav",
|
|
106
|
+
enumerable: false,
|
|
107
|
+
configurable: false,
|
|
108
|
+
});
|
|
109
|
+
return built;
|
|
110
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Block, Checkpoint, DefinedBlock, WaygraphHighlight } from "../../types.js";
|
|
2
|
+
import type { Trait } from "../../trait.js";
|
|
3
|
+
import { MemPage } from "../../mem-page.js";
|
|
4
|
+
import type { MemKey } from "../../mem-page.js";
|
|
5
|
+
/** One Block (or lazy factory) registered on a {@link PageBlock}. */
|
|
6
|
+
export type PageMethodEntry = DefinedBlock<any, any> | (() => DefinedBlock<any, any>);
|
|
7
|
+
export type PageBlockOptions<Out extends Checkpoint<string>> = {
|
|
8
|
+
name: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
/** Checkpoint tag for this screen (hub). */
|
|
11
|
+
checkpoint: Out["__state"];
|
|
12
|
+
verify?: Trait[] | ((out: Out) => Trait[]);
|
|
13
|
+
stubBefore?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
14
|
+
stubAfter?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
15
|
+
stubOnError?: import("../../highlights.js").HighlightStubPhaseOrFn<Out>;
|
|
16
|
+
/** @deprecated Prefer stubAfter. */
|
|
17
|
+
highlights?: readonly WaygraphHighlight[] | ((out: Out) => readonly WaygraphHighlight[]);
|
|
18
|
+
requires?: readonly MemKey<any>[];
|
|
19
|
+
/**
|
|
20
|
+
* Methods available on this page. Array, or a record of Blocks / `() => Block`
|
|
21
|
+
* factories (lazy so the page object can colocate method definitions).
|
|
22
|
+
*/
|
|
23
|
+
methods?: readonly PageMethodEntry[] | Record<string, PageMethodEntry>;
|
|
24
|
+
/**
|
|
25
|
+
* Optional deep-link onto this page (`goto`). XOR with `click`. Omit when the
|
|
26
|
+
* hub is arrival-only (previous Block already resolved here).
|
|
27
|
+
*/
|
|
28
|
+
url?: string | ((mem: MemPage) => string);
|
|
29
|
+
/** Optional click-nav onto this page. XOR with `url`. */
|
|
30
|
+
click?: string | ((mem: MemPage) => string);
|
|
31
|
+
instanceOptions?: Block<Checkpoint<string>, Out>["instanceOptions"];
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Page hub Block: one Checkpoint = this screen; methods hang off the hub for
|
|
35
|
+
* readability / auto grouping. Runtime is still a Block (`__waygraphKind = "page"`).
|
|
36
|
+
* `act` is goto/click when `url`/`click` is set, otherwise a no-op (already here).
|
|
37
|
+
* Child methods stay ordinary Blocks for graph edges - the page only registers them.
|
|
38
|
+
* Branded `__wgFactory: "page"` (not `"nav"`) - both are accepted by
|
|
39
|
+
* {@link MapBuilder.gotoPage} / {@link MapBuilder.gotoExternal}.
|
|
40
|
+
*/
|
|
41
|
+
export type PageBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkpoint<string>, Out>, "withVerify" | "modVerify" | "modVerifyAll" | "stubBefore" | "stubAfter" | "stubOnError"> & {
|
|
42
|
+
readonly __wgFactory?: "page";
|
|
43
|
+
/** Resolved method Blocks registered at define time. */
|
|
44
|
+
readonly methods: readonly DefinedBlock<any, any>[];
|
|
45
|
+
withVerify(verify: Trait[] | ((out: Out) => Trait[])): PageBlock<Out>;
|
|
46
|
+
modVerify(nameOrIndex: string | number, newCheck: Trait["check"] | Trait): PageBlock<Out>;
|
|
47
|
+
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): PageBlock<Out>;
|
|
48
|
+
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
49
|
+
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
50
|
+
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
51
|
+
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
52
|
+
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
53
|
+
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
54
|
+
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
55
|
+
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
56
|
+
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
57
|
+
};
|
|
58
|
+
/** @see {@link PageBlockOptions} */
|
|
59
|
+
export declare function definePageBlock<Out extends Checkpoint<string>>(options: PageBlockOptions<Out>): PageBlock<Out>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Split out of the former 2,900-line engine.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
|
+
import { checkpoint } from "../../types.js";
|
|
3
|
+
import { defineBlock } from "../core.js";
|
|
4
|
+
function resolvePageMethods(methods) {
|
|
5
|
+
if (!methods)
|
|
6
|
+
return [];
|
|
7
|
+
const entries = Array.isArray(methods) ? methods : Object.values(methods);
|
|
8
|
+
return entries.map((entry) => (typeof entry === "function" ? entry() : entry));
|
|
9
|
+
}
|
|
10
|
+
/** @see {@link PageBlockOptions} */
|
|
11
|
+
export function definePageBlock(options) {
|
|
12
|
+
if (options.url !== undefined && options.click !== undefined) {
|
|
13
|
+
throw new Error(`definePageBlock("${options.name}"): pass url XOR click (or neither for arrival-only hub)`);
|
|
14
|
+
}
|
|
15
|
+
const methodList = resolvePageMethods(options.methods);
|
|
16
|
+
const built = defineBlock({
|
|
17
|
+
name: options.name,
|
|
18
|
+
...(options.description ? { description: options.description } : {}),
|
|
19
|
+
...(options.requires ? { requires: options.requires } : {}),
|
|
20
|
+
...(options.instanceOptions ? { instanceOptions: options.instanceOptions } : {}),
|
|
21
|
+
instruction: {
|
|
22
|
+
async act(page, _input, mem) {
|
|
23
|
+
if (options.url !== undefined) {
|
|
24
|
+
const url = typeof options.url === "function" ? options.url(mem) : options.url;
|
|
25
|
+
await page.goto(url);
|
|
26
|
+
}
|
|
27
|
+
else if (options.click !== undefined) {
|
|
28
|
+
const selector = typeof options.click === "function" ? options.click(mem) : options.click;
|
|
29
|
+
await page.locator(selector).click();
|
|
30
|
+
}
|
|
31
|
+
// else: arrival-only hub — previous Block already landed here
|
|
32
|
+
},
|
|
33
|
+
resolve: () => checkpoint(options.checkpoint),
|
|
34
|
+
...(options.verify ? { verify: options.verify } : {}),
|
|
35
|
+
...(options.stubBefore ? { stubBefore: options.stubBefore } : {}),
|
|
36
|
+
...(options.stubAfter ? { stubAfter: options.stubAfter } : {}),
|
|
37
|
+
...(options.stubOnError ? { stubOnError: options.stubOnError } : {}),
|
|
38
|
+
...(options.highlights ? { highlights: options.highlights } : {}),
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
Object.defineProperty(built, "__waygraphKind", {
|
|
42
|
+
value: "page",
|
|
43
|
+
enumerable: false,
|
|
44
|
+
configurable: false,
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(built, "__waygraphSalt", {
|
|
47
|
+
value: "page",
|
|
48
|
+
enumerable: false,
|
|
49
|
+
configurable: false,
|
|
50
|
+
});
|
|
51
|
+
Object.defineProperty(built, "methods", {
|
|
52
|
+
value: Object.freeze([...methodList]),
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: false,
|
|
55
|
+
writable: false,
|
|
56
|
+
});
|
|
57
|
+
Object.defineProperty(built, "__waygraphMethods", {
|
|
58
|
+
value: methodList.map((m) => m.name),
|
|
59
|
+
enumerable: false,
|
|
60
|
+
configurable: false,
|
|
61
|
+
});
|
|
62
|
+
// Same marker `defineNavBlock` sets, same reason - a page hub with a
|
|
63
|
+
// `url` (deep-link) is exactly as "known, coverable" as a plain
|
|
64
|
+
// `defineNavBlock`, and in practice most real projects' own nav Blocks
|
|
65
|
+
// ARE page hubs (methods hanging off them), not bare NavBlocks - the real
|
|
66
|
+
// saucedemo fixture this whole package tests against uses definePageBlock
|
|
67
|
+
// for every one of its own nav-* Blocks. Missing this here meant the
|
|
68
|
+
// marker existed but was never actually set on any real project's Blocks.
|
|
69
|
+
if (typeof options.url === "string") {
|
|
70
|
+
Object.defineProperty(built, "__waygraphNavUrl", {
|
|
71
|
+
value: options.url,
|
|
72
|
+
enumerable: false,
|
|
73
|
+
configurable: false,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (options.url !== undefined || options.click !== undefined) {
|
|
77
|
+
Object.defineProperty(built, "__waygraphPageDeepLink", {
|
|
78
|
+
value: true,
|
|
79
|
+
enumerable: false,
|
|
80
|
+
configurable: false,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (options.click !== undefined) {
|
|
84
|
+
Object.defineProperty(built, "__waygraphNavClick", {
|
|
85
|
+
value: options.click,
|
|
86
|
+
enumerable: false,
|
|
87
|
+
configurable: false,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return built;
|
|
91
|
+
}
|