@noego/wood 0.4.8 → 0.4.10

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.
Files changed (149) hide show
  1. package/bin/axe.js +313 -98
  2. package/bin/wood.js +7 -1
  3. package/dist/automation/actions.cjs +17 -0
  4. package/dist/automation/actions.cjs.map +1 -0
  5. package/dist/automation/actions.d.cts +57 -0
  6. package/dist/automation/actions.d.ts +57 -0
  7. package/dist/automation/actions.js +1 -0
  8. package/dist/automation/actions.js.map +1 -0
  9. package/dist/automation/actions_executor.cjs +101 -0
  10. package/dist/automation/actions_executor.cjs.map +1 -0
  11. package/dist/automation/actions_executor.d.cts +16 -0
  12. package/dist/automation/actions_executor.d.ts +16 -0
  13. package/dist/automation/actions_executor.js +76 -0
  14. package/dist/automation/actions_executor.js.map +1 -0
  15. package/dist/automation/connection.cjs +86 -0
  16. package/dist/automation/connection.cjs.map +1 -0
  17. package/dist/automation/connection.d.cts +18 -0
  18. package/dist/automation/connection.d.ts +18 -0
  19. package/dist/automation/connection.js +51 -0
  20. package/dist/automation/connection.js.map +1 -0
  21. package/dist/automation/errors.cjs +50 -0
  22. package/dist/automation/errors.cjs.map +1 -0
  23. package/dist/automation/errors.d.cts +31 -0
  24. package/dist/automation/errors.d.ts +31 -0
  25. package/dist/automation/errors.js +24 -0
  26. package/dist/automation/errors.js.map +1 -0
  27. package/dist/automation/index.cjs +49 -0
  28. package/dist/automation/index.cjs.map +1 -0
  29. package/dist/automation/index.d.cts +16 -0
  30. package/dist/automation/index.d.ts +16 -0
  31. package/dist/automation/index.js +15 -0
  32. package/dist/automation/index.js.map +1 -0
  33. package/dist/automation/introspection_reader.cjs +75 -0
  34. package/dist/automation/introspection_reader.cjs.map +1 -0
  35. package/dist/automation/introspection_reader.d.cts +20 -0
  36. package/dist/automation/introspection_reader.d.ts +20 -0
  37. package/dist/automation/introspection_reader.js +48 -0
  38. package/dist/automation/introspection_reader.js.map +1 -0
  39. package/dist/automation/locator.cjs +102 -0
  40. package/dist/automation/locator.cjs.map +1 -0
  41. package/dist/automation/locator.d.cts +51 -0
  42. package/dist/automation/locator.d.ts +51 -0
  43. package/dist/automation/locator.js +75 -0
  44. package/dist/automation/locator.js.map +1 -0
  45. package/dist/automation/observation.cjs +17 -0
  46. package/dist/automation/observation.cjs.map +1 -0
  47. package/dist/automation/observation.d.cts +44 -0
  48. package/dist/automation/observation.d.ts +44 -0
  49. package/dist/automation/observation.js +1 -0
  50. package/dist/automation/observation.js.map +1 -0
  51. package/dist/automation/receipts.cjs +17 -0
  52. package/dist/automation/receipts.cjs.map +1 -0
  53. package/dist/automation/receipts.d.cts +27 -0
  54. package/dist/automation/receipts.d.ts +27 -0
  55. package/dist/automation/receipts.js +1 -0
  56. package/dist/automation/receipts.js.map +1 -0
  57. package/dist/automation/scenario.cjs +696 -0
  58. package/dist/automation/scenario.cjs.map +1 -0
  59. package/dist/automation/scenario.d.cts +89 -0
  60. package/dist/automation/scenario.d.ts +89 -0
  61. package/dist/automation/scenario.js +660 -0
  62. package/dist/automation/scenario.js.map +1 -0
  63. package/dist/automation/scrolling.cjs +17 -0
  64. package/dist/automation/scrolling.cjs.map +1 -0
  65. package/dist/automation/scrolling.d.cts +51 -0
  66. package/dist/automation/scrolling.d.ts +51 -0
  67. package/dist/automation/scrolling.js +1 -0
  68. package/dist/automation/scrolling.js.map +1 -0
  69. package/dist/automation/scrolling_executor.cjs +109 -0
  70. package/dist/automation/scrolling_executor.cjs.map +1 -0
  71. package/dist/automation/scrolling_executor.d.cts +13 -0
  72. package/dist/automation/scrolling_executor.d.ts +13 -0
  73. package/dist/automation/scrolling_executor.js +84 -0
  74. package/dist/automation/scrolling_executor.js.map +1 -0
  75. package/dist/automation/target_identity.cjs +17 -0
  76. package/dist/automation/target_identity.cjs.map +1 -0
  77. package/dist/automation/target_identity.d.cts +28 -0
  78. package/dist/automation/target_identity.d.ts +28 -0
  79. package/dist/automation/target_identity.js +1 -0
  80. package/dist/automation/target_identity.js.map +1 -0
  81. package/dist/automation/target_registry.cjs +148 -0
  82. package/dist/automation/target_registry.cjs.map +1 -0
  83. package/dist/automation/target_registry.d.cts +32 -0
  84. package/dist/automation/target_registry.d.ts +32 -0
  85. package/dist/automation/target_registry.js +122 -0
  86. package/dist/automation/target_registry.js.map +1 -0
  87. package/dist/automation/waits.cjs +17 -0
  88. package/dist/automation/waits.cjs.map +1 -0
  89. package/dist/automation/waits.d.cts +44 -0
  90. package/dist/automation/waits.d.ts +44 -0
  91. package/dist/automation/waits.js +1 -0
  92. package/dist/automation/waits.js.map +1 -0
  93. package/dist/automation/waits_executor.cjs +104 -0
  94. package/dist/automation/waits_executor.cjs.map +1 -0
  95. package/dist/automation/waits_executor.d.cts +14 -0
  96. package/dist/automation/waits_executor.d.ts +14 -0
  97. package/dist/automation/waits_executor.js +79 -0
  98. package/dist/automation/waits_executor.js.map +1 -0
  99. package/dist/client/index.d.cts +1 -0
  100. package/dist/client/index.d.ts +1 -0
  101. package/dist/codegen/renderer_app_generator.cjs +16 -1
  102. package/dist/codegen/renderer_app_generator.cjs.map +1 -1
  103. package/dist/codegen/renderer_app_generator.js +16 -1
  104. package/dist/codegen/renderer_app_generator.js.map +1 -1
  105. package/dist/index.d.cts +1 -0
  106. package/dist/index.d.ts +1 -0
  107. package/dist/navigation/automation_introspection.cjs +110 -0
  108. package/dist/navigation/automation_introspection.cjs.map +1 -0
  109. package/dist/navigation/automation_introspection.d.cts +60 -0
  110. package/dist/navigation/automation_introspection.d.ts +60 -0
  111. package/dist/navigation/automation_introspection.js +85 -0
  112. package/dist/navigation/automation_introspection.js.map +1 -0
  113. package/dist/navigation/index.cjs +7 -2
  114. package/dist/navigation/index.cjs.map +1 -1
  115. package/dist/navigation/index.d.cts +2 -0
  116. package/dist/navigation/index.d.ts +2 -0
  117. package/dist/navigation/index.js +4 -1
  118. package/dist/navigation/index.js.map +1 -1
  119. package/dist/testing/automation_assertions.cjs +417 -0
  120. package/dist/testing/automation_assertions.cjs.map +1 -0
  121. package/dist/testing/automation_assertions.d.cts +44 -0
  122. package/dist/testing/automation_assertions.d.ts +44 -0
  123. package/dist/testing/automation_assertions.js +385 -0
  124. package/dist/testing/automation_assertions.js.map +1 -0
  125. package/dist/testing/browser.cjs +26 -34
  126. package/dist/testing/browser.cjs.map +1 -1
  127. package/dist/testing/browser.d.cts +2 -1
  128. package/dist/testing/browser.d.ts +2 -1
  129. package/dist/testing/browser.js +30 -31
  130. package/dist/testing/browser.js.map +1 -1
  131. package/dist/testing/create_controller_harness.d.cts +1 -0
  132. package/dist/testing/create_controller_harness.d.ts +1 -0
  133. package/dist/testing/geometry.cjs +109 -0
  134. package/dist/testing/geometry.cjs.map +1 -0
  135. package/dist/testing/geometry.d.cts +45 -0
  136. package/dist/testing/geometry.d.ts +45 -0
  137. package/dist/testing/geometry.js +79 -0
  138. package/dist/testing/geometry.js.map +1 -0
  139. package/dist/testing/index.cjs +31 -2
  140. package/dist/testing/index.cjs.map +1 -1
  141. package/dist/testing/index.d.cts +4 -0
  142. package/dist/testing/index.d.ts +4 -0
  143. package/dist/testing/index.js +31 -1
  144. package/dist/testing/index.js.map +1 -1
  145. package/dist/tracing/trace_hub.cjs +3 -0
  146. package/dist/tracing/trace_hub.cjs.map +1 -1
  147. package/dist/tracing/trace_hub.js +3 -0
  148. package/dist/tracing/trace_hub.js.map +1 -1
  149. package/package.json +7 -1
@@ -2,6 +2,7 @@ import { Navigation } from '../navigation/index.cjs';
2
2
  import { TraceRecorder } from '../trace-testing/trace_recorder.cjs';
3
3
  import { RouterBridgeResult } from './create_router_bridge.cjs';
4
4
  import { createTestRouter } from './create_test_router.cjs';
5
+ import '../navigation/automation_introspection.cjs';
5
6
  import '@noego/trace/testing';
6
7
  import '../trace_hub-Cob54qRx.cjs';
7
8
  import 'rxjs';
@@ -2,6 +2,7 @@ import { Navigation } from '../navigation/index.js';
2
2
  import { TraceRecorder } from '../trace-testing/trace_recorder.js';
3
3
  import { RouterBridgeResult } from './create_router_bridge.js';
4
4
  import { createTestRouter } from './create_test_router.js';
5
+ import '../navigation/automation_introspection.js';
5
6
  import '@noego/trace/testing';
6
7
  import '../trace_hub-Cob54qRx.js';
7
8
  import 'rxjs';
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var geometry_exports = {};
20
+ __export(geometry_exports, {
21
+ axisEdges: () => axisEdges,
22
+ axisGap: () => axisGap,
23
+ evenSpacing: () => evenSpacing,
24
+ gaps: () => gaps,
25
+ rectsOverlap: () => rectsOverlap,
26
+ sharedEdges: () => sharedEdges,
27
+ snapshotRectsOverlap: () => snapshotRectsOverlap
28
+ });
29
+ module.exports = __toCommonJS(geometry_exports);
30
+ function axisEdges(rect, axis) {
31
+ return axis === "horizontal" ? { leading: rect.left, trailing: rect.right } : { leading: rect.top, trailing: rect.bottom };
32
+ }
33
+ function axisGap(first, second, axis) {
34
+ const a = axisEdges(first, axis);
35
+ const b = axisEdges(second, axis);
36
+ const [earlier, later] = a.leading <= b.leading ? [a, b] : [b, a];
37
+ return later.leading - earlier.trailing;
38
+ }
39
+ function rectsOverlap(a, b) {
40
+ return Boolean(
41
+ a && b && a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top
42
+ );
43
+ }
44
+ function snapshotRectsOverlap(a, b) {
45
+ return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
46
+ }
47
+ function sharedEdges(rects, edge, options = {}) {
48
+ const tolerance = options.tolerance ?? 1;
49
+ if (rects.length < 2) {
50
+ return {
51
+ pass: false,
52
+ message: "sharedEdges requires at least two rects.",
53
+ details: { count: rects.length, edge, tolerance }
54
+ };
55
+ }
56
+ const expected = rects[0][edge];
57
+ const deltas = rects.slice(1).map((rect) => Math.abs(rect[edge] - expected));
58
+ const maximumDelta = Math.max(...deltas);
59
+ const pass = maximumDelta <= tolerance;
60
+ return {
61
+ pass,
62
+ message: pass ? `All rects share the ${edge} edge within ${tolerance}px.` : `Rects do not share the ${edge} edge within ${tolerance}px (maximum delta ${maximumDelta.toFixed(2)}px).`,
63
+ details: { edge, tolerance, expected, deltas, maximumDelta }
64
+ };
65
+ }
66
+ function gaps(rects, axis) {
67
+ const sorted = [...rects].sort(
68
+ (a, b) => axisEdges(a, axis).leading - axisEdges(b, axis).leading
69
+ );
70
+ return sorted.slice(1).map((rect, index) => axisGap(sorted[index], rect, axis));
71
+ }
72
+ function evenSpacing(rects, axis, options = {}) {
73
+ const tolerance = options.tolerance ?? 1;
74
+ if (rects.length < 3) {
75
+ return {
76
+ pass: false,
77
+ message: `evenSpacing requires at least three rects, got ${rects.length}.`,
78
+ details: { count: rects.length, axis, tolerance }
79
+ };
80
+ }
81
+ const measuredGaps = gaps(rects, axis);
82
+ const widest = Math.max(...measuredGaps);
83
+ const narrowest = Math.min(...measuredGaps);
84
+ const spread = widest - narrowest;
85
+ const pass = spread <= tolerance;
86
+ return {
87
+ pass,
88
+ message: pass ? `Rects are evenly spaced along ${axis} within ${tolerance}px.` : `Rects are not evenly spaced along ${axis}: gap spread ${spread.toFixed(2)}px exceeds ${tolerance}px.`,
89
+ details: {
90
+ axis,
91
+ tolerance,
92
+ gaps: measuredGaps,
93
+ widest,
94
+ narrowest,
95
+ spread
96
+ }
97
+ };
98
+ }
99
+ // Annotate the CommonJS export names for ESM import in node:
100
+ 0 && (module.exports = {
101
+ axisEdges,
102
+ axisGap,
103
+ evenSpacing,
104
+ gaps,
105
+ rectsOverlap,
106
+ sharedEdges,
107
+ snapshotRectsOverlap
108
+ });
109
+ //# sourceMappingURL=geometry.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/testing/geometry.ts"],"sourcesContent":["export type RectAxis = 'horizontal' | 'vertical';\n\nexport interface RectBox {\n top: number;\n left: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n}\n\nexport interface SnapshotRect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface GeometryVerdict {\n pass: boolean;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport type RectEdge = 'left' | 'right' | 'top' | 'bottom';\n\nexport function axisEdges(\n rect: RectBox,\n axis: RectAxis,\n): { leading: number; trailing: number } {\n return axis === 'horizontal'\n ? { leading: rect.left, trailing: rect.right }\n : { leading: rect.top, trailing: rect.bottom };\n}\n\n/**\n * Edge-to-edge gap between two border boxes. The box with the smaller leading\n * edge is treated as the earlier box, so negative values mean overlap.\n */\nexport function axisGap(first: RectBox, second: RectBox, axis: RectAxis): number {\n const a = axisEdges(first, axis);\n const b = axisEdges(second, axis);\n const [earlier, later] = a.leading <= b.leading ? [a, b] : [b, a];\n return later.leading - earlier.trailing;\n}\n\nexport function rectsOverlap(\n a: RectBox | null | undefined,\n b: RectBox | null | undefined,\n): boolean {\n return Boolean(\n a && b\n && a.left < b.right && a.right > b.left\n && a.top < b.bottom && a.bottom > b.top,\n );\n}\n\n/** Two CDP snapshot `[x,y,w,h]` rects overlap on both axes. */\nexport function snapshotRectsOverlap(a: SnapshotRect, b: SnapshotRect): boolean {\n return a.x < b.x + b.w\n && a.x + a.w > b.x\n && a.y < b.y + b.h\n && a.y + a.h > b.y;\n}\n\n/** Assert that every rect shares one named edge with the first rect. */\nexport function sharedEdges(\n rects: readonly RectBox[],\n edge: RectEdge,\n options: { tolerance?: number } = {},\n): GeometryVerdict {\n const tolerance = options.tolerance ?? 1;\n if (rects.length < 2) {\n return {\n pass: false,\n message: 'sharedEdges requires at least two rects.',\n details: { count: rects.length, edge, tolerance },\n };\n }\n\n const expected = rects[0][edge];\n const deltas = rects.slice(1).map((rect) => Math.abs(rect[edge] - expected));\n const maximumDelta = Math.max(...deltas);\n const pass = maximumDelta <= tolerance;\n return {\n pass,\n message: pass\n ? `All rects share the ${edge} edge within ${tolerance}px.`\n : `Rects do not share the ${edge} edge within ${tolerance}px (maximum delta ${maximumDelta.toFixed(2)}px).`,\n details: { edge, tolerance, expected, deltas, maximumDelta },\n };\n}\n\n/** Consecutive edge-to-edge gaps, after sorting rects along the requested axis. */\nexport function gaps(rects: readonly RectBox[], axis: RectAxis): number[] {\n const sorted = [...rects].sort(\n (a, b) => axisEdges(a, axis).leading - axisEdges(b, axis).leading,\n );\n return sorted.slice(1).map((rect, index) => axisGap(sorted[index], rect, axis));\n}\n\n/** Assert that consecutive rect gaps have no more than the requested spread. */\nexport function evenSpacing(\n rects: readonly RectBox[],\n axis: RectAxis,\n options: { tolerance?: number } = {},\n): GeometryVerdict {\n const tolerance = options.tolerance ?? 1;\n if (rects.length < 3) {\n return {\n pass: false,\n message: `evenSpacing requires at least three rects, got ${rects.length}.`,\n details: { count: rects.length, axis, tolerance },\n };\n }\n\n const measuredGaps = gaps(rects, axis);\n const widest = Math.max(...measuredGaps);\n const narrowest = Math.min(...measuredGaps);\n const spread = widest - narrowest;\n const pass = spread <= tolerance;\n return {\n pass,\n message: pass\n ? `Rects are evenly spaced along ${axis} within ${tolerance}px.`\n : `Rects are not evenly spaced along ${axis}: gap spread ${spread.toFixed(2)}px exceeds ${tolerance}px.`,\n details: {\n axis,\n tolerance,\n gaps: measuredGaps,\n widest,\n narrowest,\n spread,\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,45 @@
1
+ type RectAxis = 'horizontal' | 'vertical';
2
+ interface RectBox {
3
+ top: number;
4
+ left: number;
5
+ right: number;
6
+ bottom: number;
7
+ width: number;
8
+ height: number;
9
+ }
10
+ interface SnapshotRect {
11
+ x: number;
12
+ y: number;
13
+ w: number;
14
+ h: number;
15
+ }
16
+ interface GeometryVerdict {
17
+ pass: boolean;
18
+ message: string;
19
+ details?: Record<string, unknown>;
20
+ }
21
+ type RectEdge = 'left' | 'right' | 'top' | 'bottom';
22
+ declare function axisEdges(rect: RectBox, axis: RectAxis): {
23
+ leading: number;
24
+ trailing: number;
25
+ };
26
+ /**
27
+ * Edge-to-edge gap between two border boxes. The box with the smaller leading
28
+ * edge is treated as the earlier box, so negative values mean overlap.
29
+ */
30
+ declare function axisGap(first: RectBox, second: RectBox, axis: RectAxis): number;
31
+ declare function rectsOverlap(a: RectBox | null | undefined, b: RectBox | null | undefined): boolean;
32
+ /** Two CDP snapshot `[x,y,w,h]` rects overlap on both axes. */
33
+ declare function snapshotRectsOverlap(a: SnapshotRect, b: SnapshotRect): boolean;
34
+ /** Assert that every rect shares one named edge with the first rect. */
35
+ declare function sharedEdges(rects: readonly RectBox[], edge: RectEdge, options?: {
36
+ tolerance?: number;
37
+ }): GeometryVerdict;
38
+ /** Consecutive edge-to-edge gaps, after sorting rects along the requested axis. */
39
+ declare function gaps(rects: readonly RectBox[], axis: RectAxis): number[];
40
+ /** Assert that consecutive rect gaps have no more than the requested spread. */
41
+ declare function evenSpacing(rects: readonly RectBox[], axis: RectAxis, options?: {
42
+ tolerance?: number;
43
+ }): GeometryVerdict;
44
+
45
+ export { type GeometryVerdict, type RectAxis, type RectBox, type RectEdge, type SnapshotRect, axisEdges, axisGap, evenSpacing, gaps, rectsOverlap, sharedEdges, snapshotRectsOverlap };
@@ -0,0 +1,45 @@
1
+ type RectAxis = 'horizontal' | 'vertical';
2
+ interface RectBox {
3
+ top: number;
4
+ left: number;
5
+ right: number;
6
+ bottom: number;
7
+ width: number;
8
+ height: number;
9
+ }
10
+ interface SnapshotRect {
11
+ x: number;
12
+ y: number;
13
+ w: number;
14
+ h: number;
15
+ }
16
+ interface GeometryVerdict {
17
+ pass: boolean;
18
+ message: string;
19
+ details?: Record<string, unknown>;
20
+ }
21
+ type RectEdge = 'left' | 'right' | 'top' | 'bottom';
22
+ declare function axisEdges(rect: RectBox, axis: RectAxis): {
23
+ leading: number;
24
+ trailing: number;
25
+ };
26
+ /**
27
+ * Edge-to-edge gap between two border boxes. The box with the smaller leading
28
+ * edge is treated as the earlier box, so negative values mean overlap.
29
+ */
30
+ declare function axisGap(first: RectBox, second: RectBox, axis: RectAxis): number;
31
+ declare function rectsOverlap(a: RectBox | null | undefined, b: RectBox | null | undefined): boolean;
32
+ /** Two CDP snapshot `[x,y,w,h]` rects overlap on both axes. */
33
+ declare function snapshotRectsOverlap(a: SnapshotRect, b: SnapshotRect): boolean;
34
+ /** Assert that every rect shares one named edge with the first rect. */
35
+ declare function sharedEdges(rects: readonly RectBox[], edge: RectEdge, options?: {
36
+ tolerance?: number;
37
+ }): GeometryVerdict;
38
+ /** Consecutive edge-to-edge gaps, after sorting rects along the requested axis. */
39
+ declare function gaps(rects: readonly RectBox[], axis: RectAxis): number[];
40
+ /** Assert that consecutive rect gaps have no more than the requested spread. */
41
+ declare function evenSpacing(rects: readonly RectBox[], axis: RectAxis, options?: {
42
+ tolerance?: number;
43
+ }): GeometryVerdict;
44
+
45
+ export { type GeometryVerdict, type RectAxis, type RectBox, type RectEdge, type SnapshotRect, axisEdges, axisGap, evenSpacing, gaps, rectsOverlap, sharedEdges, snapshotRectsOverlap };
@@ -0,0 +1,79 @@
1
+ function axisEdges(rect, axis) {
2
+ return axis === "horizontal" ? { leading: rect.left, trailing: rect.right } : { leading: rect.top, trailing: rect.bottom };
3
+ }
4
+ function axisGap(first, second, axis) {
5
+ const a = axisEdges(first, axis);
6
+ const b = axisEdges(second, axis);
7
+ const [earlier, later] = a.leading <= b.leading ? [a, b] : [b, a];
8
+ return later.leading - earlier.trailing;
9
+ }
10
+ function rectsOverlap(a, b) {
11
+ return Boolean(
12
+ a && b && a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top
13
+ );
14
+ }
15
+ function snapshotRectsOverlap(a, b) {
16
+ return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
17
+ }
18
+ function sharedEdges(rects, edge, options = {}) {
19
+ const tolerance = options.tolerance ?? 1;
20
+ if (rects.length < 2) {
21
+ return {
22
+ pass: false,
23
+ message: "sharedEdges requires at least two rects.",
24
+ details: { count: rects.length, edge, tolerance }
25
+ };
26
+ }
27
+ const expected = rects[0][edge];
28
+ const deltas = rects.slice(1).map((rect) => Math.abs(rect[edge] - expected));
29
+ const maximumDelta = Math.max(...deltas);
30
+ const pass = maximumDelta <= tolerance;
31
+ return {
32
+ pass,
33
+ message: pass ? `All rects share the ${edge} edge within ${tolerance}px.` : `Rects do not share the ${edge} edge within ${tolerance}px (maximum delta ${maximumDelta.toFixed(2)}px).`,
34
+ details: { edge, tolerance, expected, deltas, maximumDelta }
35
+ };
36
+ }
37
+ function gaps(rects, axis) {
38
+ const sorted = [...rects].sort(
39
+ (a, b) => axisEdges(a, axis).leading - axisEdges(b, axis).leading
40
+ );
41
+ return sorted.slice(1).map((rect, index) => axisGap(sorted[index], rect, axis));
42
+ }
43
+ function evenSpacing(rects, axis, options = {}) {
44
+ const tolerance = options.tolerance ?? 1;
45
+ if (rects.length < 3) {
46
+ return {
47
+ pass: false,
48
+ message: `evenSpacing requires at least three rects, got ${rects.length}.`,
49
+ details: { count: rects.length, axis, tolerance }
50
+ };
51
+ }
52
+ const measuredGaps = gaps(rects, axis);
53
+ const widest = Math.max(...measuredGaps);
54
+ const narrowest = Math.min(...measuredGaps);
55
+ const spread = widest - narrowest;
56
+ const pass = spread <= tolerance;
57
+ return {
58
+ pass,
59
+ message: pass ? `Rects are evenly spaced along ${axis} within ${tolerance}px.` : `Rects are not evenly spaced along ${axis}: gap spread ${spread.toFixed(2)}px exceeds ${tolerance}px.`,
60
+ details: {
61
+ axis,
62
+ tolerance,
63
+ gaps: measuredGaps,
64
+ widest,
65
+ narrowest,
66
+ spread
67
+ }
68
+ };
69
+ }
70
+ export {
71
+ axisEdges,
72
+ axisGap,
73
+ evenSpacing,
74
+ gaps,
75
+ rectsOverlap,
76
+ sharedEdges,
77
+ snapshotRectsOverlap
78
+ };
79
+ //# sourceMappingURL=geometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/testing/geometry.ts"],"sourcesContent":["export type RectAxis = 'horizontal' | 'vertical';\n\nexport interface RectBox {\n top: number;\n left: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n}\n\nexport interface SnapshotRect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface GeometryVerdict {\n pass: boolean;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport type RectEdge = 'left' | 'right' | 'top' | 'bottom';\n\nexport function axisEdges(\n rect: RectBox,\n axis: RectAxis,\n): { leading: number; trailing: number } {\n return axis === 'horizontal'\n ? { leading: rect.left, trailing: rect.right }\n : { leading: rect.top, trailing: rect.bottom };\n}\n\n/**\n * Edge-to-edge gap between two border boxes. The box with the smaller leading\n * edge is treated as the earlier box, so negative values mean overlap.\n */\nexport function axisGap(first: RectBox, second: RectBox, axis: RectAxis): number {\n const a = axisEdges(first, axis);\n const b = axisEdges(second, axis);\n const [earlier, later] = a.leading <= b.leading ? [a, b] : [b, a];\n return later.leading - earlier.trailing;\n}\n\nexport function rectsOverlap(\n a: RectBox | null | undefined,\n b: RectBox | null | undefined,\n): boolean {\n return Boolean(\n a && b\n && a.left < b.right && a.right > b.left\n && a.top < b.bottom && a.bottom > b.top,\n );\n}\n\n/** Two CDP snapshot `[x,y,w,h]` rects overlap on both axes. */\nexport function snapshotRectsOverlap(a: SnapshotRect, b: SnapshotRect): boolean {\n return a.x < b.x + b.w\n && a.x + a.w > b.x\n && a.y < b.y + b.h\n && a.y + a.h > b.y;\n}\n\n/** Assert that every rect shares one named edge with the first rect. */\nexport function sharedEdges(\n rects: readonly RectBox[],\n edge: RectEdge,\n options: { tolerance?: number } = {},\n): GeometryVerdict {\n const tolerance = options.tolerance ?? 1;\n if (rects.length < 2) {\n return {\n pass: false,\n message: 'sharedEdges requires at least two rects.',\n details: { count: rects.length, edge, tolerance },\n };\n }\n\n const expected = rects[0][edge];\n const deltas = rects.slice(1).map((rect) => Math.abs(rect[edge] - expected));\n const maximumDelta = Math.max(...deltas);\n const pass = maximumDelta <= tolerance;\n return {\n pass,\n message: pass\n ? `All rects share the ${edge} edge within ${tolerance}px.`\n : `Rects do not share the ${edge} edge within ${tolerance}px (maximum delta ${maximumDelta.toFixed(2)}px).`,\n details: { edge, tolerance, expected, deltas, maximumDelta },\n };\n}\n\n/** Consecutive edge-to-edge gaps, after sorting rects along the requested axis. */\nexport function gaps(rects: readonly RectBox[], axis: RectAxis): number[] {\n const sorted = [...rects].sort(\n (a, b) => axisEdges(a, axis).leading - axisEdges(b, axis).leading,\n );\n return sorted.slice(1).map((rect, index) => axisGap(sorted[index], rect, axis));\n}\n\n/** Assert that consecutive rect gaps have no more than the requested spread. */\nexport function evenSpacing(\n rects: readonly RectBox[],\n axis: RectAxis,\n options: { tolerance?: number } = {},\n): GeometryVerdict {\n const tolerance = options.tolerance ?? 1;\n if (rects.length < 3) {\n return {\n pass: false,\n message: `evenSpacing requires at least three rects, got ${rects.length}.`,\n details: { count: rects.length, axis, tolerance },\n };\n }\n\n const measuredGaps = gaps(rects, axis);\n const widest = Math.max(...measuredGaps);\n const narrowest = Math.min(...measuredGaps);\n const spread = widest - narrowest;\n const pass = spread <= tolerance;\n return {\n pass,\n message: pass\n ? `Rects are evenly spaced along ${axis} within ${tolerance}px.`\n : `Rects are not evenly spaced along ${axis}: gap spread ${spread.toFixed(2)}px exceeds ${tolerance}px.`,\n details: {\n axis,\n tolerance,\n gaps: measuredGaps,\n widest,\n narrowest,\n spread,\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -25,6 +25,7 @@ __export(testing_exports, {
25
25
  RouterBridgeEvents: () => import_create_router_bridge.RouterBridgeEvents,
26
26
  TraceRecorder: () => import_trace_testing.TraceRecorder,
27
27
  assertLoopbackSerializable: () => import_transport.assertLoopbackSerializable,
28
+ automationAssertions: () => import_automation_assertions.automationAssertions,
28
29
  browser: () => import_browser.browser,
29
30
  buildTransportBridge: () => import_transport.buildTransportBridge,
30
31
  createBrowserBridgeFixture: () => import_browser.createBrowserBridgeFixture,
@@ -32,8 +33,21 @@ __export(testing_exports, {
32
33
  createRouterBridge: () => import_create_router_bridge.createRouterBridge,
33
34
  createTestContainer: () => import_create_test_container.createTestContainer,
34
35
  createTestRouter: () => import_create_test_router.createTestRouter,
36
+ evenSpacing: () => import_automation_assertions.evenSpacing,
37
+ evenSpacingRects: () => import_automation_assertions.evenSpacingRects,
38
+ gaps: () => import_automation_assertions.gaps,
35
39
  getElectronMockFactory: () => import_mock_electron.getElectronMockFactory,
36
- mockElectron: () => import_mock_electron.mockElectron
40
+ hidden: () => import_automation_assertions.hidden,
41
+ hitTestReachable: () => import_automation_assertions.hitTestReachable,
42
+ insideViewport: () => import_automation_assertions.insideViewport,
43
+ mockElectron: () => import_mock_electron.mockElectron,
44
+ notClipped: () => import_automation_assertions.notClipped,
45
+ notOverlapping: () => import_automation_assertions.notOverlapping,
46
+ rectsOverlap: () => import_automation_assertions.rectsOverlap,
47
+ sharedEdges: () => import_automation_assertions.sharedEdges,
48
+ sharedRectEdges: () => import_automation_assertions.sharedRectEdges,
49
+ stableAfterAnimation: () => import_automation_assertions.stableAfterAnimation,
50
+ visible: () => import_automation_assertions.visible
37
51
  });
38
52
  module.exports = __toCommonJS(testing_exports);
39
53
  var import_create_test_container = require("./create_test_container.js");
@@ -42,6 +56,7 @@ var import_create_test_router = require("./create_test_router.js");
42
56
  var import_mock_electron = require("./mock_electron.js");
43
57
  var import_create_router_bridge = require("./create_router_bridge.js");
44
58
  var import_browser = require("./browser.js");
59
+ var import_automation_assertions = require("./automation_assertions.js");
45
60
  var import_transport = require("../transport/index.js");
46
61
  var import_trace_testing = require("../trace-testing/index.js");
47
62
  // Annotate the CommonJS export names for ESM import in node:
@@ -53,6 +68,7 @@ var import_trace_testing = require("../trace-testing/index.js");
53
68
  RouterBridgeEvents,
54
69
  TraceRecorder,
55
70
  assertLoopbackSerializable,
71
+ automationAssertions,
56
72
  browser,
57
73
  buildTransportBridge,
58
74
  createBrowserBridgeFixture,
@@ -60,7 +76,20 @@ var import_trace_testing = require("../trace-testing/index.js");
60
76
  createRouterBridge,
61
77
  createTestContainer,
62
78
  createTestRouter,
79
+ evenSpacing,
80
+ evenSpacingRects,
81
+ gaps,
63
82
  getElectronMockFactory,
64
- mockElectron
83
+ hidden,
84
+ hitTestReachable,
85
+ insideViewport,
86
+ mockElectron,
87
+ notClipped,
88
+ notOverlapping,
89
+ rectsOverlap,
90
+ sharedEdges,
91
+ sharedRectEdges,
92
+ stableAfterAnimation,
93
+ visible
65
94
  });
66
95
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/testing/index.ts"],"sourcesContent":["export { createTestContainer } from './create_test_container.js';\nexport {\n createControllerHarness,\n type ControllerHarnessResult,\n type CreateControllerHarnessOptions,\n} from './create_controller_harness.js';\nexport { createTestRouter, type TestRouterResult } from './create_test_router.js';\nexport { mockElectron, getElectronMockFactory } from './mock_electron.js';\nexport {\n createRouterBridge,\n RouterBridgeEvents,\n type RouterBridgeResult,\n} from './create_router_bridge.js';\nexport {\n browser,\n createBrowserBridgeFixture,\n type MountedWoodBridge,\n type MountedWoodComponent,\n type MountedWoodNavigation,\n type MountedWoodRoute,\n type MountedWoodSurface,\n type MountedWoodTree,\n type MountComponentOptions,\n type MountRouteOptions,\n type MountTreeOptions,\n type WoodBridgeFixtureContext,\n type WoodBridgeFixtureInput,\n type WoodBridgeRecordedCall,\n type WoodBridgeRecordedEvent,\n type WoodRpcManifestEntryInput,\n type WoodBrowserExpect,\n type WoodHitTestResult,\n type WoodRectSnapshot,\n type WoodBrowserHarness,\n type WoodBrowserHarnessConfig,\n type WoodBrowserPageContext,\n type WoodBrowserTraceConfig,\n type WoodViewport,\n} from './browser.js';\nexport {\n InProcessRouterTransport,\n LoopbackRemoteTransport,\n LoopbackRemoteTransportServer,\n assertLoopbackSerializable,\n LoopbackSerializationError,\n buildTransportBridge,\n type WoodRpcTransport,\n type WoodChannelContract,\n type WoodChannelMapLike,\n type WoodChannelInput,\n type WoodChannelOutput,\n type TypedCall,\n type TransportBridgeResult,\n} from '../transport/index.js';\nexport { TraceRecorder } from '../trace-testing/index.js';\nexport type {\n TraceDispatchResult,\n TraceEvent,\n TraceInput,\n TraceWaitOptions,\n} from '../tracing/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAAoC;AACpC,uCAIO;AACP,gCAAwD;AACxD,2BAAqD;AACrD,kCAIO;AACP,qBAyBO;AACP,uBAcO;AACP,2BAA8B;","names":[]}
1
+ {"version":3,"sources":["../../src/testing/index.ts"],"sourcesContent":["export { createTestContainer } from './create_test_container.js';\nexport {\n createControllerHarness,\n type ControllerHarnessResult,\n type CreateControllerHarnessOptions,\n} from './create_controller_harness.js';\nexport { createTestRouter, type TestRouterResult } from './create_test_router.js';\nexport { mockElectron, getElectronMockFactory } from './mock_electron.js';\nexport {\n createRouterBridge,\n RouterBridgeEvents,\n type RouterBridgeResult,\n} from './create_router_bridge.js';\nexport {\n browser,\n createBrowserBridgeFixture,\n type MountedWoodBridge,\n type MountedWoodComponent,\n type MountedWoodNavigation,\n type MountedWoodRoute,\n type MountedWoodSurface,\n type MountedWoodTree,\n type MountComponentOptions,\n type MountRouteOptions,\n type MountTreeOptions,\n type WoodBridgeFixtureContext,\n type WoodBridgeFixtureInput,\n type WoodBridgeRecordedCall,\n type WoodBridgeRecordedEvent,\n type WoodRpcManifestEntryInput,\n type WoodBrowserExpect,\n type WoodHitTestResult,\n type WoodRectSnapshot,\n type WoodBrowserHarness,\n type WoodBrowserHarnessConfig,\n type WoodBrowserPageContext,\n type WoodBrowserTraceConfig,\n type WoodViewport,\n} from './browser.js';\nexport {\n automationAssertions,\n visible,\n hidden,\n insideViewport,\n notClipped,\n notOverlapping,\n hitTestReachable,\n sharedEdges,\n evenSpacing,\n stableAfterAnimation,\n rectsOverlap,\n gaps,\n sharedRectEdges,\n evenSpacingRects,\n type AssertionVerdict,\n type AutomationTarget,\n type AutomationRectTarget,\n type GeometryVerdict,\n type RectAxis,\n type RectBox,\n type RectEdge,\n} from './automation_assertions.js';\nexport {\n InProcessRouterTransport,\n LoopbackRemoteTransport,\n LoopbackRemoteTransportServer,\n assertLoopbackSerializable,\n LoopbackSerializationError,\n buildTransportBridge,\n type WoodRpcTransport,\n type WoodChannelContract,\n type WoodChannelMapLike,\n type WoodChannelInput,\n type WoodChannelOutput,\n type TypedCall,\n type TransportBridgeResult,\n} from '../transport/index.js';\nexport { TraceRecorder } from '../trace-testing/index.js';\nexport type {\n TraceDispatchResult,\n TraceEvent,\n TraceInput,\n TraceWaitOptions,\n} from '../tracing/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAAoC;AACpC,uCAIO;AACP,gCAAwD;AACxD,2BAAqD;AACrD,kCAIO;AACP,qBAyBO;AACP,mCAsBO;AACP,uBAcO;AACP,2BAA8B;","names":[]}
@@ -4,6 +4,7 @@ export { TestRouterResult, createTestRouter } from './create_test_router.cjs';
4
4
  export { getElectronMockFactory, mockElectron } from './mock_electron.cjs';
5
5
  export { RouterBridgeEvents, RouterBridgeResult, createRouterBridge } from './create_router_bridge.cjs';
6
6
  export { MountComponentOptions, MountRouteOptions, MountTreeOptions, MountedWoodBridge, MountedWoodComponent, MountedWoodNavigation, MountedWoodRoute, MountedWoodSurface, MountedWoodTree, WoodBridgeFixtureContext, WoodBridgeFixtureInput, WoodBridgeRecordedCall, WoodBridgeRecordedEvent, WoodBrowserExpect, WoodBrowserHarness, WoodBrowserHarnessConfig, WoodBrowserPageContext, WoodBrowserTraceConfig, WoodHitTestResult, WoodRectSnapshot, WoodRpcManifestEntryInput, WoodViewport, browser, createBrowserBridgeFixture } from './browser.cjs';
7
+ export { AssertionVerdict, AutomationRectTarget, AutomationTarget, automationAssertions, evenSpacing, hidden, hitTestReachable, insideViewport, notClipped, notOverlapping, sharedEdges, stableAfterAnimation, visible } from './automation_assertions.cjs';
7
8
  export { TypedCall, WoodChannelContract, WoodChannelInput, WoodChannelMapLike, WoodChannelOutput, WoodRpcTransport } from '../transport/wood_rpc_transport.cjs';
8
9
  export { InProcessRouterTransport } from '../transport/in_process_router_transport.cjs';
9
10
  export { LoopbackRemoteTransport, LoopbackRemoteTransportServer } from '../transport/loopback_remote_transport.cjs';
@@ -11,9 +12,12 @@ export { LoopbackSerializationError, assertLoopbackSerializable } from '../trans
11
12
  export { TransportBridgeResult, buildTransportBridge } from '../transport/build_transport_bridge.cjs';
12
13
  export { TraceRecorder } from '../trace-testing/trace_recorder.cjs';
13
14
  export { T as TraceDispatchResult, a as TraceEvent, b as TraceInput, f as TraceWaitOptions } from '../trace_hub-Cob54qRx.cjs';
15
+ export { GeometryVerdict, RectAxis, RectBox, RectEdge, evenSpacing as evenSpacingRects, gaps, rectsOverlap, sharedEdges as sharedRectEdges } from './geometry.cjs';
14
16
  import '../navigation/index.cjs';
17
+ import '../navigation/automation_introspection.cjs';
15
18
  import '../router/wood_router.cjs';
16
19
  import '../types/operations.cjs';
20
+ import 'playwright';
17
21
  import '@noego/trace/testing';
18
22
  import '../tracing/trace_provider.cjs';
19
23
  import '@noego/ioc';
@@ -4,6 +4,7 @@ export { TestRouterResult, createTestRouter } from './create_test_router.js';
4
4
  export { getElectronMockFactory, mockElectron } from './mock_electron.js';
5
5
  export { RouterBridgeEvents, RouterBridgeResult, createRouterBridge } from './create_router_bridge.js';
6
6
  export { MountComponentOptions, MountRouteOptions, MountTreeOptions, MountedWoodBridge, MountedWoodComponent, MountedWoodNavigation, MountedWoodRoute, MountedWoodSurface, MountedWoodTree, WoodBridgeFixtureContext, WoodBridgeFixtureInput, WoodBridgeRecordedCall, WoodBridgeRecordedEvent, WoodBrowserExpect, WoodBrowserHarness, WoodBrowserHarnessConfig, WoodBrowserPageContext, WoodBrowserTraceConfig, WoodHitTestResult, WoodRectSnapshot, WoodRpcManifestEntryInput, WoodViewport, browser, createBrowserBridgeFixture } from './browser.js';
7
+ export { AssertionVerdict, AutomationRectTarget, AutomationTarget, automationAssertions, evenSpacing, hidden, hitTestReachable, insideViewport, notClipped, notOverlapping, sharedEdges, stableAfterAnimation, visible } from './automation_assertions.js';
7
8
  export { TypedCall, WoodChannelContract, WoodChannelInput, WoodChannelMapLike, WoodChannelOutput, WoodRpcTransport } from '../transport/wood_rpc_transport.js';
8
9
  export { InProcessRouterTransport } from '../transport/in_process_router_transport.js';
9
10
  export { LoopbackRemoteTransport, LoopbackRemoteTransportServer } from '../transport/loopback_remote_transport.js';
@@ -11,9 +12,12 @@ export { LoopbackSerializationError, assertLoopbackSerializable } from '../trans
11
12
  export { TransportBridgeResult, buildTransportBridge } from '../transport/build_transport_bridge.js';
12
13
  export { TraceRecorder } from '../trace-testing/trace_recorder.js';
13
14
  export { T as TraceDispatchResult, a as TraceEvent, b as TraceInput, f as TraceWaitOptions } from '../trace_hub-Cob54qRx.js';
15
+ export { GeometryVerdict, RectAxis, RectBox, RectEdge, evenSpacing as evenSpacingRects, gaps, rectsOverlap, sharedEdges as sharedRectEdges } from './geometry.js';
14
16
  import '../navigation/index.js';
17
+ import '../navigation/automation_introspection.js';
15
18
  import '../router/wood_router.js';
16
19
  import '../types/operations.js';
20
+ import 'playwright';
17
21
  import '@noego/trace/testing';
18
22
  import '../tracing/trace_provider.js';
19
23
  import '@noego/ioc';
@@ -12,6 +12,22 @@ import {
12
12
  browser,
13
13
  createBrowserBridgeFixture
14
14
  } from "./browser.js";
15
+ import {
16
+ automationAssertions,
17
+ visible,
18
+ hidden,
19
+ insideViewport,
20
+ notClipped,
21
+ notOverlapping,
22
+ hitTestReachable,
23
+ sharedEdges,
24
+ evenSpacing,
25
+ stableAfterAnimation,
26
+ rectsOverlap,
27
+ gaps,
28
+ sharedRectEdges,
29
+ evenSpacingRects
30
+ } from "./automation_assertions.js";
15
31
  import {
16
32
  InProcessRouterTransport,
17
33
  LoopbackRemoteTransport,
@@ -29,6 +45,7 @@ export {
29
45
  RouterBridgeEvents,
30
46
  TraceRecorder,
31
47
  assertLoopbackSerializable,
48
+ automationAssertions,
32
49
  browser,
33
50
  buildTransportBridge,
34
51
  createBrowserBridgeFixture,
@@ -36,7 +53,20 @@ export {
36
53
  createRouterBridge,
37
54
  createTestContainer,
38
55
  createTestRouter,
56
+ evenSpacing,
57
+ evenSpacingRects,
58
+ gaps,
39
59
  getElectronMockFactory,
40
- mockElectron
60
+ hidden,
61
+ hitTestReachable,
62
+ insideViewport,
63
+ mockElectron,
64
+ notClipped,
65
+ notOverlapping,
66
+ rectsOverlap,
67
+ sharedEdges,
68
+ sharedRectEdges,
69
+ stableAfterAnimation,
70
+ visible
41
71
  };
42
72
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/testing/index.ts"],"sourcesContent":["export { createTestContainer } from './create_test_container.js';\nexport {\n createControllerHarness,\n type ControllerHarnessResult,\n type CreateControllerHarnessOptions,\n} from './create_controller_harness.js';\nexport { createTestRouter, type TestRouterResult } from './create_test_router.js';\nexport { mockElectron, getElectronMockFactory } from './mock_electron.js';\nexport {\n createRouterBridge,\n RouterBridgeEvents,\n type RouterBridgeResult,\n} from './create_router_bridge.js';\nexport {\n browser,\n createBrowserBridgeFixture,\n type MountedWoodBridge,\n type MountedWoodComponent,\n type MountedWoodNavigation,\n type MountedWoodRoute,\n type MountedWoodSurface,\n type MountedWoodTree,\n type MountComponentOptions,\n type MountRouteOptions,\n type MountTreeOptions,\n type WoodBridgeFixtureContext,\n type WoodBridgeFixtureInput,\n type WoodBridgeRecordedCall,\n type WoodBridgeRecordedEvent,\n type WoodRpcManifestEntryInput,\n type WoodBrowserExpect,\n type WoodHitTestResult,\n type WoodRectSnapshot,\n type WoodBrowserHarness,\n type WoodBrowserHarnessConfig,\n type WoodBrowserPageContext,\n type WoodBrowserTraceConfig,\n type WoodViewport,\n} from './browser.js';\nexport {\n InProcessRouterTransport,\n LoopbackRemoteTransport,\n LoopbackRemoteTransportServer,\n assertLoopbackSerializable,\n LoopbackSerializationError,\n buildTransportBridge,\n type WoodRpcTransport,\n type WoodChannelContract,\n type WoodChannelMapLike,\n type WoodChannelInput,\n type WoodChannelOutput,\n type TypedCall,\n type TransportBridgeResult,\n} from '../transport/index.js';\nexport { TraceRecorder } from '../trace-testing/index.js';\nexport type {\n TraceDispatchResult,\n TraceEvent,\n TraceInput,\n TraceWaitOptions,\n} from '../tracing/index.js';\n"],"mappings":"AAAA,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,OAGK;AACP,SAAS,wBAA+C;AACxD,SAAS,cAAc,8BAA8B;AACrD;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAuBK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AACP,SAAS,qBAAqB;","names":[]}
1
+ {"version":3,"sources":["../../src/testing/index.ts"],"sourcesContent":["export { createTestContainer } from './create_test_container.js';\nexport {\n createControllerHarness,\n type ControllerHarnessResult,\n type CreateControllerHarnessOptions,\n} from './create_controller_harness.js';\nexport { createTestRouter, type TestRouterResult } from './create_test_router.js';\nexport { mockElectron, getElectronMockFactory } from './mock_electron.js';\nexport {\n createRouterBridge,\n RouterBridgeEvents,\n type RouterBridgeResult,\n} from './create_router_bridge.js';\nexport {\n browser,\n createBrowserBridgeFixture,\n type MountedWoodBridge,\n type MountedWoodComponent,\n type MountedWoodNavigation,\n type MountedWoodRoute,\n type MountedWoodSurface,\n type MountedWoodTree,\n type MountComponentOptions,\n type MountRouteOptions,\n type MountTreeOptions,\n type WoodBridgeFixtureContext,\n type WoodBridgeFixtureInput,\n type WoodBridgeRecordedCall,\n type WoodBridgeRecordedEvent,\n type WoodRpcManifestEntryInput,\n type WoodBrowserExpect,\n type WoodHitTestResult,\n type WoodRectSnapshot,\n type WoodBrowserHarness,\n type WoodBrowserHarnessConfig,\n type WoodBrowserPageContext,\n type WoodBrowserTraceConfig,\n type WoodViewport,\n} from './browser.js';\nexport {\n automationAssertions,\n visible,\n hidden,\n insideViewport,\n notClipped,\n notOverlapping,\n hitTestReachable,\n sharedEdges,\n evenSpacing,\n stableAfterAnimation,\n rectsOverlap,\n gaps,\n sharedRectEdges,\n evenSpacingRects,\n type AssertionVerdict,\n type AutomationTarget,\n type AutomationRectTarget,\n type GeometryVerdict,\n type RectAxis,\n type RectBox,\n type RectEdge,\n} from './automation_assertions.js';\nexport {\n InProcessRouterTransport,\n LoopbackRemoteTransport,\n LoopbackRemoteTransportServer,\n assertLoopbackSerializable,\n LoopbackSerializationError,\n buildTransportBridge,\n type WoodRpcTransport,\n type WoodChannelContract,\n type WoodChannelMapLike,\n type WoodChannelInput,\n type WoodChannelOutput,\n type TypedCall,\n type TransportBridgeResult,\n} from '../transport/index.js';\nexport { TraceRecorder } from '../trace-testing/index.js';\nexport type {\n TraceDispatchResult,\n TraceEvent,\n TraceInput,\n TraceWaitOptions,\n} from '../tracing/index.js';\n"],"mappings":"AAAA,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,OAGK;AACP,SAAS,wBAA+C;AACxD,SAAS,cAAc,8BAA8B;AACrD;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAuBK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AACP,SAAS,qBAAqB;","names":[]}
@@ -141,6 +141,9 @@ class TraceHub {
141
141
  if (this.sinks.size === 0) {
142
142
  return;
143
143
  }
144
+ if (traceLevelOrder(level) < traceLevelOrder(this.minLevels.renderer)) {
145
+ return;
146
+ }
144
147
  const event = {
145
148
  ...input,
146
149
  level,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject } from 'rxjs';\nimport { share } from 'rxjs/operators';\nimport type {\n WoodTraceEventSink,\n WoodTraceEventSnapshot,\n WoodTraceSinkDisposer,\n} from './types/wood_trace_sink.types.js';\n\nexport type StandardTraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceLevel = StandardTraceLevel | (string & {});\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceRuntimeContext = {\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<StandardTraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\nconst CUSTOM_LEVEL_ORDER = LEVEL_ORDER.info;\n\nexport function normalizeTraceLevel(level: unknown, fallback: TraceLevel = 'info'): TraceLevel {\n if (typeof level !== 'string') {\n return fallback;\n }\n\n const normalized = level.trim().toLowerCase();\n return normalized.length > 0 ? normalized : fallback;\n}\n\nfunction traceLevelOrder(level: TraceLevel): number {\n return LEVEL_ORDER[level as StandardTraceLevel] ?? CUSTOM_LEVEL_ORDER;\n}\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet rendererEnabled = false;\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const windowId = typeof input.windowId === 'string' && input.windowId.trim().length > 0\n ? input.windowId\n : undefined;\n const webContentsId = typeof input.webContentsId === 'number' && Number.isFinite(input.webContentsId)\n ? input.webContentsId\n : undefined;\n const routeKey = typeof input.routeKey === 'string' && input.routeKey.trim().length > 0\n ? input.routeKey\n : undefined;\n const harnessId = typeof input.harnessId === 'string' && input.harnessId.trim().length > 0\n ? input.harnessId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(windowId !== undefined ? { windowId } : {}),\n ...(webContentsId !== undefined ? { webContentsId } : {}),\n ...(routeKey !== undefined ? { routeKey } : {}),\n ...(harnessId !== undefined ? { harnessId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction mergeTraceRuntimeContext(input: unknown, context: TraceRuntimeContext | undefined): TraceInput {\n if (!context) {\n return normalizeTraceInput(input);\n }\n return normalizeTraceInput({\n ...(isRecord(input) ? input : {}),\n ...context,\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private readonly sinks = new Set<WoodTraceEventSink>();\n private nextTraceSeq = 1;\n private minLevels: Record<TraceProcess, TraceLevel> = {\n main: 'debug',\n renderer: 'debug',\n test: 'debug',\n };\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(process: TraceProcess, level: TraceLevel): void {\n this.minLevels[process] = level;\n }\n\n registerSink(sink: WoodTraceEventSink): WoodTraceSinkDisposer {\n this.sinks.add(sink);\n return () => {\n this.sinks.delete(sink);\n };\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (traceLevelOrder(level) >= traceLevelOrder(this.minLevels[process])) {\n this.publishToSinks(event);\n this.subject.next(event);\n }\n return event;\n }\n\n publishRendererToSinks(level: TraceLevel, input: TraceInput): void {\n if (this.sinks.size === 0) {\n return;\n }\n const event: TraceEvent = {\n ...input,\n level,\n process: 'renderer',\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n this.publishToSinks(event);\n }\n\n private publishToSinks(event: TraceEvent): void {\n if (this.sinks.size === 0) {\n return;\n }\n const snapshot: WoodTraceEventSnapshot = Object.freeze({\n ...event,\n ...(event.payload ? { payload: Object.freeze({ ...event.payload }) } : {}),\n });\n for (const sink of this.sinks) {\n try {\n sink(snapshot);\n } catch {\n // Trace sinks are observational and cannot fail trace callers or peers.\n }\n }\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function registerTraceSink(sink: WoodTraceEventSink): WoodTraceSinkDisposer {\n return getGlobalTraceHub().registerSink(sink);\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel('main', level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n getGlobalTraceHub().setMinLevel('renderer', level);\n}\n\nexport function setRendererTraceEnabled(enabled: boolean): void {\n rendererEnabled = enabled;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(\n rawPayload: unknown,\n context?: TraceRuntimeContext,\n): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: unknown };\n const level = normalizeTraceLevel(payload.level);\n getGlobalTraceHub().publish('renderer', level, mergeTraceRuntimeContext(payload, context));\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (!rendererEnabled) {\n return;\n }\n if (traceLevelOrder(level) < traceLevelOrder(rendererMinLevel)) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n getGlobalTraceHub().publishRendererToSinks(level, normalized);\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n rendererEnabled = false;\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject } from 'rxjs';\nimport { share } from 'rxjs/operators';\nimport type {\n WoodTraceEventSink,\n WoodTraceEventSnapshot,\n WoodTraceSinkDisposer,\n} from './types/wood_trace_sink.types.js';\n\nexport type StandardTraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceLevel = StandardTraceLevel | (string & {});\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceRuntimeContext = {\n windowId?: string;\n webContentsId?: number;\n routeKey?: string;\n harnessId?: string;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<StandardTraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\nconst CUSTOM_LEVEL_ORDER = LEVEL_ORDER.info;\n\nexport function normalizeTraceLevel(level: unknown, fallback: TraceLevel = 'info'): TraceLevel {\n if (typeof level !== 'string') {\n return fallback;\n }\n\n const normalized = level.trim().toLowerCase();\n return normalized.length > 0 ? normalized : fallback;\n}\n\nfunction traceLevelOrder(level: TraceLevel): number {\n return LEVEL_ORDER[level as StandardTraceLevel] ?? CUSTOM_LEVEL_ORDER;\n}\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet rendererEnabled = false;\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const windowId = typeof input.windowId === 'string' && input.windowId.trim().length > 0\n ? input.windowId\n : undefined;\n const webContentsId = typeof input.webContentsId === 'number' && Number.isFinite(input.webContentsId)\n ? input.webContentsId\n : undefined;\n const routeKey = typeof input.routeKey === 'string' && input.routeKey.trim().length > 0\n ? input.routeKey\n : undefined;\n const harnessId = typeof input.harnessId === 'string' && input.harnessId.trim().length > 0\n ? input.harnessId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(windowId !== undefined ? { windowId } : {}),\n ...(webContentsId !== undefined ? { webContentsId } : {}),\n ...(routeKey !== undefined ? { routeKey } : {}),\n ...(harnessId !== undefined ? { harnessId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction mergeTraceRuntimeContext(input: unknown, context: TraceRuntimeContext | undefined): TraceInput {\n if (!context) {\n return normalizeTraceInput(input);\n }\n return normalizeTraceInput({\n ...(isRecord(input) ? input : {}),\n ...context,\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private readonly sinks = new Set<WoodTraceEventSink>();\n private nextTraceSeq = 1;\n private minLevels: Record<TraceProcess, TraceLevel> = {\n main: 'debug',\n renderer: 'debug',\n test: 'debug',\n };\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(process: TraceProcess, level: TraceLevel): void {\n this.minLevels[process] = level;\n }\n\n registerSink(sink: WoodTraceEventSink): WoodTraceSinkDisposer {\n this.sinks.add(sink);\n return () => {\n this.sinks.delete(sink);\n };\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (traceLevelOrder(level) >= traceLevelOrder(this.minLevels[process])) {\n this.publishToSinks(event);\n this.subject.next(event);\n }\n return event;\n }\n\n publishRendererToSinks(level: TraceLevel, input: TraceInput): void {\n if (this.sinks.size === 0) {\n return;\n }\n if (traceLevelOrder(level) < traceLevelOrder(this.minLevels.renderer)) {\n return;\n }\n const event: TraceEvent = {\n ...input,\n level,\n process: 'renderer',\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n this.publishToSinks(event);\n }\n\n private publishToSinks(event: TraceEvent): void {\n if (this.sinks.size === 0) {\n return;\n }\n const snapshot: WoodTraceEventSnapshot = Object.freeze({\n ...event,\n ...(event.payload ? { payload: Object.freeze({ ...event.payload }) } : {}),\n });\n for (const sink of this.sinks) {\n try {\n sink(snapshot);\n } catch {\n // Trace sinks are observational and cannot fail trace callers or peers.\n }\n }\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function registerTraceSink(sink: WoodTraceEventSink): WoodTraceSinkDisposer {\n return getGlobalTraceHub().registerSink(sink);\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel('main', level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n getGlobalTraceHub().setMinLevel('renderer', level);\n}\n\nexport function setRendererTraceEnabled(enabled: boolean): void {\n rendererEnabled = enabled;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(\n rawPayload: unknown,\n context?: TraceRuntimeContext,\n): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: unknown };\n const level = normalizeTraceLevel(payload.level);\n getGlobalTraceHub().publish('renderer', level, mergeTraceRuntimeContext(payload, context));\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (!rendererEnabled) {\n return;\n }\n if (traceLevelOrder(level) < traceLevelOrder(rendererMinLevel)) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n getGlobalTraceHub().publishRendererToSinks(level, normalized);\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n rendererEnabled = false;\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
@@ -107,6 +107,9 @@ class TraceHub {
107
107
  if (this.sinks.size === 0) {
108
108
  return;
109
109
  }
110
+ if (traceLevelOrder(level) < traceLevelOrder(this.minLevels.renderer)) {
111
+ return;
112
+ }
110
113
  const event = {
111
114
  ...input,
112
115
  level,