@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.
- package/README.md +213 -0
- package/dist/bin/glassbox.d.ts +14 -0
- package/dist/bin/glassbox.d.ts.map +1 -0
- package/dist/bin/glassbox.js +140 -0
- package/dist/bin/glassbox.js.map +1 -0
- package/dist/src/adapters/base-adapter.d.ts +70 -0
- package/dist/src/adapters/base-adapter.d.ts.map +1 -0
- package/dist/src/adapters/base-adapter.js +155 -0
- package/dist/src/adapters/base-adapter.js.map +1 -0
- package/dist/src/adapters/browser-adapter.interface.d.ts +41 -0
- package/dist/src/adapters/browser-adapter.interface.d.ts.map +1 -0
- package/dist/src/adapters/browser-adapter.interface.js +7 -0
- package/dist/src/adapters/browser-adapter.interface.js.map +1 -0
- package/dist/src/adapters/cdp-adapter.d.ts +63 -0
- package/dist/src/adapters/cdp-adapter.d.ts.map +1 -0
- package/dist/src/adapters/cdp-adapter.js +231 -0
- package/dist/src/adapters/cdp-adapter.js.map +1 -0
- package/dist/src/ai/collectors.d.ts +35 -0
- package/dist/src/ai/collectors.d.ts.map +1 -0
- package/dist/src/ai/collectors.js +170 -0
- package/dist/src/ai/collectors.js.map +1 -0
- package/dist/src/ai/queries.d.ts +21 -0
- package/dist/src/ai/queries.d.ts.map +1 -0
- package/dist/src/ai/queries.js +59 -0
- package/dist/src/ai/queries.js.map +1 -0
- package/dist/src/ai/types.d.ts +55 -0
- package/dist/src/ai/types.d.ts.map +1 -0
- package/dist/src/ai/types.js +6 -0
- package/dist/src/ai/types.js.map +1 -0
- package/dist/src/cdp/connection.d.ts +37 -0
- package/dist/src/cdp/connection.d.ts.map +1 -0
- package/dist/src/cdp/connection.js +86 -0
- package/dist/src/cdp/connection.js.map +1 -0
- package/dist/src/cdp/connection.test.d.ts +6 -0
- package/dist/src/cdp/connection.test.d.ts.map +1 -0
- package/dist/src/cdp/connection.test.js +93 -0
- package/dist/src/cdp/connection.test.js.map +1 -0
- package/dist/src/cdp/domains.d.ts +116 -0
- package/dist/src/cdp/domains.d.ts.map +1 -0
- package/dist/src/cdp/domains.js +153 -0
- package/dist/src/cdp/domains.js.map +1 -0
- package/dist/src/cdp/launcher.d.ts +26 -0
- package/dist/src/cdp/launcher.d.ts.map +1 -0
- package/dist/src/cdp/launcher.js +175 -0
- package/dist/src/cdp/launcher.js.map +1 -0
- package/dist/src/config.d.ts +28 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +72 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/config.test.d.ts +5 -0
- package/dist/src/config.test.d.ts.map +1 -0
- package/dist/src/config.test.js +46 -0
- package/dist/src/config.test.js.map +1 -0
- package/dist/src/errors.d.ts +26 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +27 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +18 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +28 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/journey.d.ts +35 -0
- package/dist/src/journey.d.ts.map +1 -0
- package/dist/src/journey.js +39 -0
- package/dist/src/journey.js.map +1 -0
- package/dist/src/mcp/server.d.ts +22 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +229 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/page-objects/base.page.d.ts +28 -0
- package/dist/src/page-objects/base.page.d.ts.map +1 -0
- package/dist/src/page-objects/base.page.js +51 -0
- package/dist/src/page-objects/base.page.js.map +1 -0
- package/dist/src/page-objects/browser-context.page.d.ts +14 -0
- package/dist/src/page-objects/browser-context.page.d.ts.map +1 -0
- package/dist/src/page-objects/browser-context.page.js +28 -0
- package/dist/src/page-objects/browser-context.page.js.map +1 -0
- package/dist/src/runner/lifecycle-hooks.d.ts +43 -0
- package/dist/src/runner/lifecycle-hooks.d.ts.map +1 -0
- package/dist/src/runner/lifecycle-hooks.js +70 -0
- package/dist/src/runner/lifecycle-hooks.js.map +1 -0
- package/dist/src/runner/run-all-journeys.d.ts +35 -0
- package/dist/src/runner/run-all-journeys.d.ts.map +1 -0
- package/dist/src/runner/run-all-journeys.js +167 -0
- package/dist/src/runner/run-all-journeys.js.map +1 -0
- package/dist/src/runner/run-journey.d.ts +17 -0
- package/dist/src/runner/run-journey.d.ts.map +1 -0
- package/dist/src/runner/run-journey.js +179 -0
- package/dist/src/runner/run-journey.js.map +1 -0
- package/dist/src/runner/spawn-journey.d.ts +36 -0
- package/dist/src/runner/spawn-journey.d.ts.map +1 -0
- package/dist/src/runner/spawn-journey.js +40 -0
- package/dist/src/runner/spawn-journey.js.map +1 -0
- package/dist/src/server/diagnostic-service.d.ts +69 -0
- package/dist/src/server/diagnostic-service.d.ts.map +1 -0
- package/dist/src/server/diagnostic-service.js +165 -0
- package/dist/src/server/diagnostic-service.js.map +1 -0
- package/dist/src/server/diagnostic-service.test.d.ts +5 -0
- package/dist/src/server/diagnostic-service.test.d.ts.map +1 -0
- package/dist/src/server/diagnostic-service.test.js +82 -0
- package/dist/src/server/diagnostic-service.test.js.map +1 -0
- package/dist/src/server/index.d.ts +11 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +167 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/journey-discovery.d.ts +16 -0
- package/dist/src/server/journey-discovery.d.ts.map +1 -0
- package/dist/src/server/journey-discovery.js +38 -0
- package/dist/src/server/journey-discovery.js.map +1 -0
- package/dist/src/server/settings-storage.d.ts +27 -0
- package/dist/src/server/settings-storage.d.ts.map +1 -0
- package/dist/src/server/settings-storage.js +27 -0
- package/dist/src/server/settings-storage.js.map +1 -0
- package/dist/src/server/test-executor.d.ts +64 -0
- package/dist/src/server/test-executor.d.ts.map +1 -0
- package/dist/src/server/test-executor.js +279 -0
- package/dist/src/server/test-executor.js.map +1 -0
- package/dist/src/server/websocket.d.ts +51 -0
- package/dist/src/server/websocket.d.ts.map +1 -0
- package/dist/src/server/websocket.js +28 -0
- package/dist/src/server/websocket.js.map +1 -0
- package/dist/src/utils/browser-discovery.d.ts +11 -0
- package/dist/src/utils/browser-discovery.d.ts.map +1 -0
- package/dist/src/utils/browser-discovery.js +102 -0
- package/dist/src/utils/browser-discovery.js.map +1 -0
- package/dist/src/utils/error-formatter.d.ts +13 -0
- package/dist/src/utils/error-formatter.d.ts.map +1 -0
- package/dist/src/utils/error-formatter.js +29 -0
- package/dist/src/utils/error-formatter.js.map +1 -0
- package/dist/src/utils/escape.d.ts +10 -0
- package/dist/src/utils/escape.d.ts.map +1 -0
- package/dist/src/utils/escape.js +22 -0
- package/dist/src/utils/escape.js.map +1 -0
- package/dist/src/utils/escape.test.d.ts +5 -0
- package/dist/src/utils/escape.test.d.ts.map +1 -0
- package/dist/src/utils/escape.test.js +49 -0
- package/dist/src/utils/escape.test.js.map +1 -0
- package/dist/src/utils/page-object-error.d.ts +5 -0
- package/dist/src/utils/page-object-error.d.ts.map +1 -0
- package/dist/src/utils/page-object-error.js +22 -0
- package/dist/src/utils/page-object-error.js.map +1 -0
- package/dist/src/utils/profile-discovery.d.ts +20 -0
- package/dist/src/utils/profile-discovery.d.ts.map +1 -0
- package/dist/src/utils/profile-discovery.js +68 -0
- package/dist/src/utils/profile-discovery.js.map +1 -0
- package/dist/src/utils/wait-utils.d.ts +10 -0
- package/dist/src/utils/wait-utils.d.ts.map +1 -0
- package/dist/src/utils/wait-utils.js +20 -0
- package/dist/src/utils/wait-utils.js.map +1 -0
- package/dist/src/utils/wait-utils.test.d.ts +5 -0
- package/dist/src/utils/wait-utils.test.d.ts.map +1 -0
- package/dist/src/utils/wait-utils.test.js +30 -0
- package/dist/src/utils/wait-utils.test.js.map +1 -0
- package/package.json +60 -0
- package/src/server/static/index.html +541 -0
- package/ui/dist/3rdpartylicenses.txt +419 -0
- package/ui/dist/browser/assets/logo.svg +29 -0
- package/ui/dist/browser/index.html +13 -0
- package/ui/dist/browser/main-7OJWN7GZ.js +16 -0
- package/ui/dist/browser/polyfills-5CFQRCPP.js +2 -0
- package/ui/dist/browser/styles-HMZYQRBV.css +1 -0
- 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"}
|