@mechris3/glassbox 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/README.md +213 -0
  2. package/dist/bin/glassbox.d.ts +14 -0
  3. package/dist/bin/glassbox.d.ts.map +1 -0
  4. package/dist/bin/glassbox.js +140 -0
  5. package/dist/bin/glassbox.js.map +1 -0
  6. package/dist/src/adapters/base-adapter.d.ts +70 -0
  7. package/dist/src/adapters/base-adapter.d.ts.map +1 -0
  8. package/dist/src/adapters/base-adapter.js +155 -0
  9. package/dist/src/adapters/base-adapter.js.map +1 -0
  10. package/dist/src/adapters/browser-adapter.interface.d.ts +41 -0
  11. package/dist/src/adapters/browser-adapter.interface.d.ts.map +1 -0
  12. package/dist/src/adapters/browser-adapter.interface.js +7 -0
  13. package/dist/src/adapters/browser-adapter.interface.js.map +1 -0
  14. package/dist/src/adapters/cdp-adapter.d.ts +63 -0
  15. package/dist/src/adapters/cdp-adapter.d.ts.map +1 -0
  16. package/dist/src/adapters/cdp-adapter.js +231 -0
  17. package/dist/src/adapters/cdp-adapter.js.map +1 -0
  18. package/dist/src/ai/collectors.d.ts +35 -0
  19. package/dist/src/ai/collectors.d.ts.map +1 -0
  20. package/dist/src/ai/collectors.js +170 -0
  21. package/dist/src/ai/collectors.js.map +1 -0
  22. package/dist/src/ai/queries.d.ts +21 -0
  23. package/dist/src/ai/queries.d.ts.map +1 -0
  24. package/dist/src/ai/queries.js +59 -0
  25. package/dist/src/ai/queries.js.map +1 -0
  26. package/dist/src/ai/types.d.ts +55 -0
  27. package/dist/src/ai/types.d.ts.map +1 -0
  28. package/dist/src/ai/types.js +6 -0
  29. package/dist/src/ai/types.js.map +1 -0
  30. package/dist/src/cdp/connection.d.ts +37 -0
  31. package/dist/src/cdp/connection.d.ts.map +1 -0
  32. package/dist/src/cdp/connection.js +86 -0
  33. package/dist/src/cdp/connection.js.map +1 -0
  34. package/dist/src/cdp/connection.test.d.ts +6 -0
  35. package/dist/src/cdp/connection.test.d.ts.map +1 -0
  36. package/dist/src/cdp/connection.test.js +93 -0
  37. package/dist/src/cdp/connection.test.js.map +1 -0
  38. package/dist/src/cdp/domains.d.ts +116 -0
  39. package/dist/src/cdp/domains.d.ts.map +1 -0
  40. package/dist/src/cdp/domains.js +153 -0
  41. package/dist/src/cdp/domains.js.map +1 -0
  42. package/dist/src/cdp/launcher.d.ts +26 -0
  43. package/dist/src/cdp/launcher.d.ts.map +1 -0
  44. package/dist/src/cdp/launcher.js +175 -0
  45. package/dist/src/cdp/launcher.js.map +1 -0
  46. package/dist/src/config.d.ts +28 -0
  47. package/dist/src/config.d.ts.map +1 -0
  48. package/dist/src/config.js +72 -0
  49. package/dist/src/config.js.map +1 -0
  50. package/dist/src/config.test.d.ts +5 -0
  51. package/dist/src/config.test.d.ts.map +1 -0
  52. package/dist/src/config.test.js +46 -0
  53. package/dist/src/config.test.js.map +1 -0
  54. package/dist/src/errors.d.ts +26 -0
  55. package/dist/src/errors.d.ts.map +1 -0
  56. package/dist/src/errors.js +27 -0
  57. package/dist/src/errors.js.map +1 -0
  58. package/dist/src/index.d.ts +18 -0
  59. package/dist/src/index.d.ts.map +1 -0
  60. package/dist/src/index.js +28 -0
  61. package/dist/src/index.js.map +1 -0
  62. package/dist/src/journey.d.ts +35 -0
  63. package/dist/src/journey.d.ts.map +1 -0
  64. package/dist/src/journey.js +39 -0
  65. package/dist/src/journey.js.map +1 -0
  66. package/dist/src/mcp/server.d.ts +22 -0
  67. package/dist/src/mcp/server.d.ts.map +1 -0
  68. package/dist/src/mcp/server.js +229 -0
  69. package/dist/src/mcp/server.js.map +1 -0
  70. package/dist/src/page-objects/base.page.d.ts +28 -0
  71. package/dist/src/page-objects/base.page.d.ts.map +1 -0
  72. package/dist/src/page-objects/base.page.js +51 -0
  73. package/dist/src/page-objects/base.page.js.map +1 -0
  74. package/dist/src/page-objects/browser-context.page.d.ts +14 -0
  75. package/dist/src/page-objects/browser-context.page.d.ts.map +1 -0
  76. package/dist/src/page-objects/browser-context.page.js +28 -0
  77. package/dist/src/page-objects/browser-context.page.js.map +1 -0
  78. package/dist/src/runner/lifecycle-hooks.d.ts +43 -0
  79. package/dist/src/runner/lifecycle-hooks.d.ts.map +1 -0
  80. package/dist/src/runner/lifecycle-hooks.js +70 -0
  81. package/dist/src/runner/lifecycle-hooks.js.map +1 -0
  82. package/dist/src/runner/run-all-journeys.d.ts +35 -0
  83. package/dist/src/runner/run-all-journeys.d.ts.map +1 -0
  84. package/dist/src/runner/run-all-journeys.js +167 -0
  85. package/dist/src/runner/run-all-journeys.js.map +1 -0
  86. package/dist/src/runner/run-journey.d.ts +17 -0
  87. package/dist/src/runner/run-journey.d.ts.map +1 -0
  88. package/dist/src/runner/run-journey.js +179 -0
  89. package/dist/src/runner/run-journey.js.map +1 -0
  90. package/dist/src/runner/spawn-journey.d.ts +36 -0
  91. package/dist/src/runner/spawn-journey.d.ts.map +1 -0
  92. package/dist/src/runner/spawn-journey.js +40 -0
  93. package/dist/src/runner/spawn-journey.js.map +1 -0
  94. package/dist/src/server/diagnostic-service.d.ts +69 -0
  95. package/dist/src/server/diagnostic-service.d.ts.map +1 -0
  96. package/dist/src/server/diagnostic-service.js +165 -0
  97. package/dist/src/server/diagnostic-service.js.map +1 -0
  98. package/dist/src/server/diagnostic-service.test.d.ts +5 -0
  99. package/dist/src/server/diagnostic-service.test.d.ts.map +1 -0
  100. package/dist/src/server/diagnostic-service.test.js +82 -0
  101. package/dist/src/server/diagnostic-service.test.js.map +1 -0
  102. package/dist/src/server/index.d.ts +11 -0
  103. package/dist/src/server/index.d.ts.map +1 -0
  104. package/dist/src/server/index.js +167 -0
  105. package/dist/src/server/index.js.map +1 -0
  106. package/dist/src/server/journey-discovery.d.ts +16 -0
  107. package/dist/src/server/journey-discovery.d.ts.map +1 -0
  108. package/dist/src/server/journey-discovery.js +38 -0
  109. package/dist/src/server/journey-discovery.js.map +1 -0
  110. package/dist/src/server/settings-storage.d.ts +27 -0
  111. package/dist/src/server/settings-storage.d.ts.map +1 -0
  112. package/dist/src/server/settings-storage.js +27 -0
  113. package/dist/src/server/settings-storage.js.map +1 -0
  114. package/dist/src/server/test-executor.d.ts +64 -0
  115. package/dist/src/server/test-executor.d.ts.map +1 -0
  116. package/dist/src/server/test-executor.js +279 -0
  117. package/dist/src/server/test-executor.js.map +1 -0
  118. package/dist/src/server/websocket.d.ts +51 -0
  119. package/dist/src/server/websocket.d.ts.map +1 -0
  120. package/dist/src/server/websocket.js +28 -0
  121. package/dist/src/server/websocket.js.map +1 -0
  122. package/dist/src/utils/browser-discovery.d.ts +11 -0
  123. package/dist/src/utils/browser-discovery.d.ts.map +1 -0
  124. package/dist/src/utils/browser-discovery.js +102 -0
  125. package/dist/src/utils/browser-discovery.js.map +1 -0
  126. package/dist/src/utils/error-formatter.d.ts +13 -0
  127. package/dist/src/utils/error-formatter.d.ts.map +1 -0
  128. package/dist/src/utils/error-formatter.js +29 -0
  129. package/dist/src/utils/error-formatter.js.map +1 -0
  130. package/dist/src/utils/escape.d.ts +10 -0
  131. package/dist/src/utils/escape.d.ts.map +1 -0
  132. package/dist/src/utils/escape.js +22 -0
  133. package/dist/src/utils/escape.js.map +1 -0
  134. package/dist/src/utils/escape.test.d.ts +5 -0
  135. package/dist/src/utils/escape.test.d.ts.map +1 -0
  136. package/dist/src/utils/escape.test.js +49 -0
  137. package/dist/src/utils/escape.test.js.map +1 -0
  138. package/dist/src/utils/page-object-error.d.ts +5 -0
  139. package/dist/src/utils/page-object-error.d.ts.map +1 -0
  140. package/dist/src/utils/page-object-error.js +22 -0
  141. package/dist/src/utils/page-object-error.js.map +1 -0
  142. package/dist/src/utils/profile-discovery.d.ts +20 -0
  143. package/dist/src/utils/profile-discovery.d.ts.map +1 -0
  144. package/dist/src/utils/profile-discovery.js +68 -0
  145. package/dist/src/utils/profile-discovery.js.map +1 -0
  146. package/dist/src/utils/wait-utils.d.ts +10 -0
  147. package/dist/src/utils/wait-utils.d.ts.map +1 -0
  148. package/dist/src/utils/wait-utils.js +20 -0
  149. package/dist/src/utils/wait-utils.js.map +1 -0
  150. package/dist/src/utils/wait-utils.test.d.ts +5 -0
  151. package/dist/src/utils/wait-utils.test.d.ts.map +1 -0
  152. package/dist/src/utils/wait-utils.test.js +30 -0
  153. package/dist/src/utils/wait-utils.test.js.map +1 -0
  154. package/package.json +60 -0
  155. package/src/server/static/index.html +541 -0
  156. package/ui/dist/3rdpartylicenses.txt +419 -0
  157. package/ui/dist/browser/assets/logo.svg +29 -0
  158. package/ui/dist/browser/index.html +13 -0
  159. package/ui/dist/browser/main-7OJWN7GZ.js +16 -0
  160. package/ui/dist/browser/polyfills-5CFQRCPP.js +2 -0
  161. package/ui/dist/browser/styles-HMZYQRBV.css +1 -0
  162. package/ui/dist/prerendered-routes.json +3 -0
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ /**
3
+ * Batch runner — headless CLI execution of journeys.
4
+ *
5
+ * Discovers journeys from the configured glob, launches a browser,
6
+ * runs each journey sequentially in an isolated browser context,
7
+ * prints results, and exits with code 0 (all pass) or 1 (any fail).
8
+ *
9
+ * Used by `glassbox run` CLI command.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.runAllJourneys = runAllJourneys;
13
+ const launcher_js_1 = require("../cdp/launcher.js");
14
+ const browser_discovery_js_1 = require("../utils/browser-discovery.js");
15
+ const journey_discovery_js_1 = require("../server/journey-discovery.js");
16
+ const spawn_journey_js_1 = require("./spawn-journey.js");
17
+ const lifecycle_hooks_js_1 = require("./lifecycle-hooks.js");
18
+ /**
19
+ * Run journeys in batch mode. Returns results and an exit code.
20
+ */
21
+ async function runAllJourneys(config, options) {
22
+ const results = [];
23
+ // 1. Discover journeys
24
+ const discovery = new journey_discovery_js_1.JourneyDiscovery(config.journeys);
25
+ const allJourneys = await discovery.discover();
26
+ if (allJourneys.length === 0) {
27
+ console.log('No journeys found matching pattern:', config.journeys);
28
+ return { results, exitCode: 1 };
29
+ }
30
+ // Filter by name if specified
31
+ const journeysToRun = options.journeyFilter.length > 0
32
+ ? allJourneys.filter((j) => options.journeyFilter.some((f) => j.id.includes(f) || j.name.toLowerCase().includes(f.toLowerCase())))
33
+ : allJourneys;
34
+ if (journeysToRun.length === 0) {
35
+ console.log('No journeys match filter:', options.journeyFilter.join(', '));
36
+ return { results, exitCode: 1 };
37
+ }
38
+ // 2. Find a browser
39
+ const browserPath = config.browser.executablePath ?? autoDetectBrowser();
40
+ if (!browserPath) {
41
+ console.error('No Chromium browser found. Set browser.executablePath in config.');
42
+ return { results, exitCode: 1 };
43
+ }
44
+ // 3. Launch browser
45
+ let browser;
46
+ try {
47
+ browser = await (0, launcher_js_1.launchBrowser)({
48
+ browserPath,
49
+ headless: !options.headed,
50
+ viewport: config.browser.defaultViewport,
51
+ });
52
+ }
53
+ catch (err) {
54
+ console.error('Failed to launch browser:', err instanceof Error ? err.message : err);
55
+ return { results, exitCode: 1 };
56
+ }
57
+ console.log(`\n 🚀 Running ${journeysToRun.length} journey(s)\n`);
58
+ // 4. Run globalSetup (abort entire run if it fails)
59
+ const hookContext = { targetUrl: options.targetUrl };
60
+ const setupOk = await (0, lifecycle_hooks_js_1.runGlobalSetup)(config.testData, hookContext);
61
+ if (!setupOk) {
62
+ console.error(' ❌ globalSetup failed — aborting run\n');
63
+ browser.process.kill();
64
+ return { results, exitCode: 1 };
65
+ }
66
+ // 5. Run each journey sequentially with beforeEach/afterEach
67
+ let failed = false;
68
+ for (const journey of journeysToRun) {
69
+ if (failed && !options.noFailFast) {
70
+ results.push({ journey: journey.path, name: journey.name, status: 'skipped', duration: '-' });
71
+ continue;
72
+ }
73
+ // beforeEach
74
+ const beforeCtx = { targetUrl: options.targetUrl, journeyName: journey.name, journeyPath: journey.path };
75
+ const beforeOk = await (0, lifecycle_hooks_js_1.runBeforeEach)(config.testData, beforeCtx);
76
+ if (!beforeOk) {
77
+ results.push({ journey: journey.path, name: journey.name, status: 'failed', duration: '0s', error: 'beforeEach hook failed' });
78
+ failed = true;
79
+ console.log(` ❌ ${journey.name} (beforeEach failed)`);
80
+ continue;
81
+ }
82
+ // Run the journey
83
+ const result = await runSingleJourney(journey, browser.wsEndpoint, config, options);
84
+ results.push(result);
85
+ const icon = result.status === 'passed' ? '✅' : '❌';
86
+ console.log(` ${icon} ${result.name} (${result.duration})`);
87
+ if (result.status === 'failed') {
88
+ failed = true;
89
+ if (result.error) {
90
+ console.log(` ${result.error}\n`);
91
+ }
92
+ }
93
+ // afterEach (runs even if journey failed)
94
+ const afterCtx = { ...beforeCtx, journeyStatus: result.status };
95
+ await (0, lifecycle_hooks_js_1.runAfterEach)(config.testData, afterCtx);
96
+ }
97
+ // 6. Run globalTeardown (always runs)
98
+ await (0, lifecycle_hooks_js_1.runGlobalTeardown)(config.testData, hookContext);
99
+ // 7. Cleanup
100
+ browser.process.kill();
101
+ // 6. Print summary
102
+ printSummary(results);
103
+ return { results, exitCode: failed ? 1 : 0 };
104
+ }
105
+ /**
106
+ * Run a single journey as a child process. Returns its result.
107
+ */
108
+ async function runSingleJourney(journey, wsEndpoint, config, options) {
109
+ const start = Date.now();
110
+ const spawned = (0, spawn_journey_js_1.spawnJourney)({
111
+ journeyPath: journey.path,
112
+ wsEndpoint,
113
+ targetUrl: options.targetUrl,
114
+ viewportWidth: config.browser.defaultViewport.width,
115
+ viewportHeight: config.browser.defaultViewport.height,
116
+ actionDelay: 0,
117
+ breakpoints: [],
118
+ });
119
+ let lastError = '';
120
+ spawned.process.stderr?.on('data', (chunk) => {
121
+ const lines = chunk.toString().split('\n');
122
+ for (const line of lines) {
123
+ if (line.startsWith('[JSON]')) {
124
+ try {
125
+ const json = JSON.parse(line.slice(6));
126
+ if (json.type === 'error')
127
+ lastError = json.message;
128
+ }
129
+ catch { /* ignore */ }
130
+ }
131
+ else if (line.trim() && !line.includes('[JSON]')) {
132
+ lastError = line.trim();
133
+ }
134
+ }
135
+ });
136
+ const code = await spawned.exitCode;
137
+ const duration = `${((Date.now() - start) / 1000).toFixed(2)}s`;
138
+ return {
139
+ journey: journey.path,
140
+ name: journey.name,
141
+ status: code === 0 ? 'passed' : 'failed',
142
+ duration,
143
+ error: code !== 0 ? lastError : undefined,
144
+ };
145
+ }
146
+ /** Print a formatted results summary. */
147
+ function printSummary(results) {
148
+ const passed = results.filter((r) => r.status === 'passed').length;
149
+ const failed = results.filter((r) => r.status === 'failed').length;
150
+ const skipped = results.filter((r) => r.status === 'skipped').length;
151
+ console.log('\n ════════════════════════════════════════');
152
+ console.log(' 📊 Results');
153
+ console.log(' ════════════════════════════════════════');
154
+ for (const r of results) {
155
+ const icon = r.status === 'passed' ? '✅' : r.status === 'failed' ? '❌' : '⏭️';
156
+ console.log(` ${icon} ${r.name} ${r.status !== 'skipped' ? `(${r.duration})` : ''}`);
157
+ }
158
+ console.log(' ────────────────────────────────────────');
159
+ console.log(` Passed: ${passed} Failed: ${failed} Skipped: ${skipped}`);
160
+ console.log(' ════════════════════════════════════════\n');
161
+ }
162
+ /** Auto-detect the first available Chromium browser. */
163
+ function autoDetectBrowser() {
164
+ const browsers = (0, browser_discovery_js_1.discoverBrowsers)();
165
+ return browsers[0]?.executablePath;
166
+ }
167
+ //# sourceMappingURL=run-all-journeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-all-journeys.js","sourceRoot":"","sources":["../../../src/runner/run-all-journeys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Journey runner — child process entry point.
3
+ *
4
+ * Spawned by TestExecutor (one process per journey). Connects to Chrome via CDP,
5
+ * creates an isolated browser context, loads the journey module, executes it,
6
+ * and reports results via stderr JSON.
7
+ *
8
+ * Expected environment variables:
9
+ * - GLASSBOX_JOURNEY_PATH: absolute path to the journey file
10
+ * - GLASSBOX_WS_ENDPOINT: Chrome DevTools WebSocket URL
11
+ * - TEST_DOMAIN: base URL of the app under test
12
+ * - VIEWPORT_WIDTH, VIEWPORT_HEIGHT: browser content area dimensions
13
+ * - ACTION_DELAY: slow mode delay in ms
14
+ * - TEST_BREAKPOINTS: JSON array of action indices
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=run-journey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-journey.d.ts","sourceRoot":"","sources":["../../../src/runner/run-journey.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ /**
3
+ * Journey runner — child process entry point.
4
+ *
5
+ * Spawned by TestExecutor (one process per journey). Connects to Chrome via CDP,
6
+ * creates an isolated browser context, loads the journey module, executes it,
7
+ * and reports results via stderr JSON.
8
+ *
9
+ * Expected environment variables:
10
+ * - GLASSBOX_JOURNEY_PATH: absolute path to the journey file
11
+ * - GLASSBOX_WS_ENDPOINT: Chrome DevTools WebSocket URL
12
+ * - TEST_DOMAIN: base URL of the app under test
13
+ * - VIEWPORT_WIDTH, VIEWPORT_HEIGHT: browser content area dimensions
14
+ * - ACTION_DELAY: slow mode delay in ms
15
+ * - TEST_BREAKPOINTS: JSON array of action indices
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const connection_js_1 = require("../cdp/connection.js");
19
+ const domains_js_1 = require("../cdp/domains.js");
20
+ const cdp_adapter_js_1 = require("../adapters/cdp-adapter.js");
21
+ const collectors_js_1 = require("../ai/collectors.js");
22
+ async function main() {
23
+ const journeyPath = process.env.GLASSBOX_JOURNEY_PATH;
24
+ const wsEndpoint = process.env.GLASSBOX_WS_ENDPOINT;
25
+ if (!journeyPath) {
26
+ emitError('GLASSBOX_JOURNEY_PATH environment variable is required');
27
+ process.exit(1);
28
+ }
29
+ if (!wsEndpoint) {
30
+ emitError('GLASSBOX_WS_ENDPOINT environment variable is required');
31
+ process.exit(1);
32
+ }
33
+ let connection = null;
34
+ try {
35
+ // 1. Connect to browser-level CDP endpoint
36
+ connection = await connection_js_1.CDPConnection.connect(wsEndpoint);
37
+ const targets = new domains_js_1.TargetDomain(connection);
38
+ // 2. Close any existing tabs from previous runs (keep only one window)
39
+ const existingTargets = await connection.send('Target.getTargets');
40
+ const existingPages = existingTargets.targetInfos.filter((t) => t.type === 'page');
41
+ let targetId;
42
+ if (existingPages.length > 0) {
43
+ // Reuse the first existing page tab — navigate it rather than creating a new one
44
+ targetId = existingPages[0].targetId;
45
+ // Close any extra tabs
46
+ for (const t of existingPages.slice(1)) {
47
+ await targets.closeTarget(t.targetId).catch(() => { });
48
+ }
49
+ }
50
+ else {
51
+ // No existing tabs — create one in the default context
52
+ const targetResult = await targets.createTarget('about:blank');
53
+ targetId = targetResult.targetId;
54
+ }
55
+ // 3. Attach to the target with flattened session
56
+ const attachResult = await targets.attachToTarget(targetId, true);
57
+ const sessionId = attachResult.sessionId;
58
+ // 5. Enable CDP domains
59
+ const page = new domains_js_1.PageDomain(connection, sessionId);
60
+ const runtime = new domains_js_1.RuntimeDomain(connection, sessionId);
61
+ const network = new domains_js_1.NetworkDomain(connection, sessionId);
62
+ const dom = new domains_js_1.DOMDomain(connection, sessionId);
63
+ const performance = new domains_js_1.PerformanceDomain(connection, sessionId);
64
+ await page.enable();
65
+ await runtime.enable();
66
+ await network.enable();
67
+ await dom.enable();
68
+ await performance.enable();
69
+ // 5b. Set viewport dimensions if specified
70
+ const viewportWidth = parseInt(process.env.VIEWPORT_WIDTH ?? '1280', 10);
71
+ const viewportHeight = parseInt(process.env.VIEWPORT_HEIGHT ?? '720', 10);
72
+ await connection.send('Emulation.setDeviceMetricsOverride', {
73
+ width: viewportWidth,
74
+ height: viewportHeight,
75
+ deviceScaleFactor: 1,
76
+ mobile: false,
77
+ }, sessionId);
78
+ // 6. Start diagnostic collector
79
+ const diagnostics = new collectors_js_1.DiagnosticCollector(connection, sessionId);
80
+ // 7. Create the adapter
81
+ const adapter = new cdp_adapter_js_1.CDPAdapter(connection, sessionId);
82
+ // 8. Load the journey module
83
+ const journeyModule = await importJourney(journeyPath);
84
+ // 9. Execute the journey
85
+ await executeJourney(journeyModule, adapter);
86
+ // 10. Capture final metrics
87
+ await diagnostics.captureMetricsSnapshot('journey-complete');
88
+ // 11. Output diagnostic data for the server to collect
89
+ const diagnosticData = {
90
+ consoleErrors: diagnostics.getConsoleErrors(),
91
+ exceptions: diagnostics.getExceptions(),
92
+ networkLog: diagnostics.getNetworkLog(),
93
+ networkFailures: diagnostics.getNetworkFailures(),
94
+ metrics: diagnostics.getMetricsReport(),
95
+ timeline: diagnostics.getTimeline(),
96
+ };
97
+ process.stdout.write(JSON.stringify({ type: 'diagnostics', data: diagnosticData }) + '\n');
98
+ // 12. Clean up
99
+ diagnostics.dispose();
100
+ await connection.send('Network.clearBrowserCookies', undefined, sessionId);
101
+ connection.close();
102
+ process.exit(0);
103
+ }
104
+ catch (error) {
105
+ const message = error instanceof Error ? error.message : String(error);
106
+ const stack = error instanceof Error ? error.stack : undefined;
107
+ emitError(message);
108
+ if (stack) {
109
+ process.stderr.write(stack + '\n');
110
+ }
111
+ // Attempt cleanup
112
+ if (connection) {
113
+ connection.close();
114
+ }
115
+ process.exit(1);
116
+ }
117
+ }
118
+ /**
119
+ * Dynamically import a journey file and detect its export shape.
120
+ */
121
+ async function importJourney(journeyPath) {
122
+ const module = await import(journeyPath);
123
+ return module;
124
+ }
125
+ /**
126
+ * Execute a journey module — supports class-based and function-based journeys.
127
+ *
128
+ * Class-based: exports a class with constructor(adapter) and execute() method.
129
+ * Function-based: exports a function that receives the adapter.
130
+ */
131
+ async function executeJourney(module, adapter) {
132
+ // Find the journey export — check default first, then named exports
133
+ const journeyExport = module.default ?? findJourneyExport(module);
134
+ if (!journeyExport) {
135
+ throw new Error('Journey file must export a class with execute() method or a function');
136
+ }
137
+ // Class-based journey (has prototype with execute method)
138
+ if (isJourneyClass(journeyExport)) {
139
+ const instance = new journeyExport(adapter);
140
+ await instance.execute();
141
+ return;
142
+ }
143
+ // Function-based journey
144
+ if (typeof journeyExport === 'function') {
145
+ await journeyExport(adapter);
146
+ return;
147
+ }
148
+ throw new Error('Journey export must be a class with execute() method or a function');
149
+ }
150
+ /**
151
+ * Find a journey export from named exports (first class or function found).
152
+ */
153
+ function findJourneyExport(module) {
154
+ const candidates = Object.values(module).filter((v) => v !== undefined);
155
+ // Prefer class with execute method
156
+ const classExport = candidates.find(isJourneyClass);
157
+ if (classExport)
158
+ return classExport;
159
+ // Fall back to function
160
+ const fnExport = candidates.find((v) => typeof v === 'function');
161
+ return fnExport;
162
+ }
163
+ /**
164
+ * Type guard: checks if a value is a class constructor with an execute() method on its prototype.
165
+ */
166
+ function isJourneyClass(value) {
167
+ if (typeof value !== 'function')
168
+ return false;
169
+ const proto = value.prototype;
170
+ return proto !== undefined && typeof proto.execute === 'function';
171
+ }
172
+ /**
173
+ * Emit a structured JSON error to stderr.
174
+ */
175
+ function emitError(message) {
176
+ process.stderr.write(`[JSON]${JSON.stringify({ type: 'error', message })}\n`);
177
+ }
178
+ main();
179
+ //# sourceMappingURL=run-journey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-journey.js","sourceRoot":"","sources":["../../../src/runner/run-journey.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Shared journey spawning logic.
3
+ *
4
+ * Both the server-driven TestExecutor and the CLI batch runner need to spawn
5
+ * a child process per journey with identical environment setup. This module
6
+ * is the single source of truth for that logic.
7
+ */
8
+ import { type ChildProcess } from 'child_process';
9
+ export interface SpawnJourneyOptions {
10
+ /** Absolute path to the journey file. */
11
+ journeyPath: string;
12
+ /** Chrome DevTools WebSocket endpoint URL. */
13
+ wsEndpoint: string;
14
+ /** Target URL of the app under test. */
15
+ targetUrl: string;
16
+ /** Viewport width in pixels. */
17
+ viewportWidth: number;
18
+ /** Viewport height in pixels. */
19
+ viewportHeight: number;
20
+ /** Delay between actions in milliseconds. */
21
+ actionDelay: number;
22
+ /** Action indices where the runner should pause. */
23
+ breakpoints: number[];
24
+ }
25
+ export interface SpawnedJourney {
26
+ /** The child process handle. */
27
+ process: ChildProcess;
28
+ /** Promise that resolves with exit code when the process exits. */
29
+ exitCode: Promise<number>;
30
+ }
31
+ /**
32
+ * Spawn a journey runner child process with the correct environment.
33
+ * Returns the process handle and a promise for the exit code.
34
+ */
35
+ export declare function spawnJourney(options: SpawnJourneyOptions): SpawnedJourney;
36
+ //# sourceMappingURL=spawn-journey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-journey.d.ts","sourceRoot":"","sources":["../../../src/runner/spawn-journey.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAGzD,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,OAAO,EAAE,YAAY,CAAC;IACtB,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3B;AAKD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,cAAc,CAuBzE"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /**
3
+ * Shared journey spawning logic.
4
+ *
5
+ * Both the server-driven TestExecutor and the CLI batch runner need to spawn
6
+ * a child process per journey with identical environment setup. This module
7
+ * is the single source of truth for that logic.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.spawnJourney = spawnJourney;
11
+ const child_process_1 = require("child_process");
12
+ const path_1 = require("path");
13
+ /** Path to the runner entry point — resolved from this module's location. */
14
+ const RUNNER_ENTRY = (0, path_1.resolve)(__dirname, 'run-journey.js');
15
+ /**
16
+ * Spawn a journey runner child process with the correct environment.
17
+ * Returns the process handle and a promise for the exit code.
18
+ */
19
+ function spawnJourney(options) {
20
+ const env = {
21
+ ...process.env,
22
+ GLASSBOX_JOURNEY_PATH: options.journeyPath,
23
+ GLASSBOX_WS_ENDPOINT: options.wsEndpoint,
24
+ TEST_DOMAIN: options.targetUrl,
25
+ VIEWPORT_WIDTH: String(options.viewportWidth),
26
+ VIEWPORT_HEIGHT: String(options.viewportHeight),
27
+ ACTION_DELAY: String(options.actionDelay),
28
+ TEST_BREAKPOINTS: JSON.stringify(options.breakpoints),
29
+ };
30
+ const child = (0, child_process_1.spawn)(process.execPath, ['--import', 'tsx', RUNNER_ENTRY], {
31
+ env,
32
+ stdio: ['pipe', 'pipe', 'pipe'],
33
+ cwd: process.cwd(),
34
+ });
35
+ const exitCode = new Promise((resolve) => {
36
+ child.on('close', (code) => resolve(code ?? 1));
37
+ });
38
+ return { process: child, exitCode };
39
+ }
40
+ //# sourceMappingURL=spawn-journey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-journey.js","sourceRoot":"","sources":["../../../src/runner/spawn-journey.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAoCH,oCAuBC;AAzDD,iDAAyD;AACzD,+BAA+B;AA0B/B,6EAA6E;AAC7E,MAAM,YAAY,GAAG,IAAA,cAAO,EAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAE1D;;;GAGG;AACH,SAAgB,YAAY,CAAC,OAA4B;IACvD,MAAM,GAAG,GAA2B;QAClC,GAAG,OAAO,CAAC,GAA6B;QACxC,qBAAqB,EAAE,OAAO,CAAC,WAAW;QAC1C,oBAAoB,EAAE,OAAO,CAAC,UAAU;QACxC,WAAW,EAAE,OAAO,CAAC,SAAS;QAC9B,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;QAC7C,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC;QAC/C,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;QACzC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC;KACtD,CAAC;IAEF,MAAM,KAAK,GAAG,IAAA,qBAAK,EAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE;QACvE,GAAG;QACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QAC/B,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;KACnB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QAC/C,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * DiagnosticService — server-side diagnostic data store.
3
+ *
4
+ * Accumulates diagnostic data streamed from runner child processes
5
+ * and exposes it via REST API endpoints for the AI bridge to consume.
6
+ *
7
+ * Data flow:
8
+ * 1. Runner collects diagnostics via CDP during journey execution
9
+ * 2. At journey end, runner outputs the data as JSON to stdout
10
+ * 3. TestExecutor catches it and calls ingestRunnerData()
11
+ * 4. REST API serves the accumulated data on demand
12
+ */
13
+ import type { ConsoleError, ExceptionDetail, NetworkRequest, NetworkFailure, MetricsSnapshot, TimelineEntry } from '../ai/types.js';
14
+ interface CollectedData {
15
+ consoleErrors: ConsoleError[];
16
+ exceptions: ExceptionDetail[];
17
+ networkLog: NetworkRequest[];
18
+ networkFailures: NetworkFailure[];
19
+ metrics: MetricsSnapshot[];
20
+ timeline: TimelineEntry[];
21
+ }
22
+ export declare class DiagnosticService {
23
+ private collectedData;
24
+ private liveSession;
25
+ /**
26
+ * Ingest diagnostic data streamed from a runner child process.
27
+ * Caps each category at MAX_ENTRIES to prevent memory issues on chatty apps.
28
+ */
29
+ ingestRunnerData(data: Partial<CollectedData>): void;
30
+ /** Push items into an array, keeping only the most recent MAX_ENTRIES. */
31
+ private cappedPush;
32
+ /** Reset all collected data. */
33
+ reset(): void;
34
+ getConsoleErrors(): ConsoleError[];
35
+ getExceptions(): ExceptionDetail[];
36
+ getNetworkLog(): NetworkRequest[];
37
+ getNetworkFailures(): NetworkFailure[];
38
+ getMetrics(): MetricsSnapshot[];
39
+ getTimeline(lastN?: number): TimelineEntry[];
40
+ /**
41
+ * Summary of collected data — minimal response for the AI to decide
42
+ * which detailed endpoints to query next.
43
+ */
44
+ getSummary(): {
45
+ consoleErrors: number;
46
+ exceptions: number;
47
+ networkFailures: number;
48
+ totalRequests: number;
49
+ timelineEvents: number;
50
+ liveSessionAvailable: boolean;
51
+ };
52
+ /**
53
+ * Store a live browser session for post-failure queries.
54
+ * Called by TestExecutor when a journey fails and the browser stays alive.
55
+ */
56
+ setLiveSession(wsEndpoint: string): Promise<void>;
57
+ /** Close the live session (called before a new run or on reset). */
58
+ closeLiveSession(): void;
59
+ /** Whether a live session is available for DOM/screenshot queries. */
60
+ get hasLiveSession(): boolean;
61
+ /** Get the DOM snapshot (outerHTML) of an element or the full page. */
62
+ getDomSnapshot(selector?: string): Promise<string>;
63
+ /** Capture a screenshot of the current page state (base64 PNG). */
64
+ getScreenshot(): Promise<string>;
65
+ /** Get the accessibility tree of the current page. */
66
+ getAccessibilityTree(): Promise<unknown>;
67
+ }
68
+ export {};
69
+ //# sourceMappingURL=diagnostic-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-service.d.ts","sourceRoot":"","sources":["../../../src/server/diagnostic-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpI,UAAU,aAAa;IACrB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAYD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,aAAa,CAOnB;IAEF,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IASpD,0EAA0E;IAC1E,OAAO,CAAC,UAAU;IAOlB,gCAAgC;IAChC,KAAK,IAAI,IAAI;IAab,gBAAgB,IAAI,YAAY,EAAE;IAIlC,aAAa,IAAI,eAAe,EAAE;IAIlC,aAAa,IAAI,cAAc,EAAE;IAIjC,kBAAkB,IAAI,cAAc,EAAE;IAItC,UAAU,IAAI,eAAe,EAAE;IAI/B,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE;IAK5C;;;OAGG;IACH,UAAU,IAAI;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,oBAAoB,EAAE,OAAO,CAAC;KAC/B;IAaD;;;OAGG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBvD,oEAAoE;IACpE,gBAAgB,IAAI,IAAI;IAOxB,sEAAsE;IACtE,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,uEAAuE;IACjE,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBxD,mEAAmE;IAC7D,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAUtC,sDAAsD;IAChD,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;CAQ/C"}