@xenon-device-management/xenon 1.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 +446 -0
- package/lib/package.json +207 -0
- package/lib/public/assets/Layouts-7IT8aFLI.js +11 -0
- package/lib/public/assets/Layouts-DPMls9vh.css +1 -0
- package/lib/public/assets/ai-settings-BbnfgdEx.js +11 -0
- package/lib/public/assets/apps-CRMrI4_p.js +16 -0
- package/lib/public/assets/apps-CcM77dgg.css +1 -0
- package/lib/public/assets/badge-B1nKs8zj.css +1 -0
- package/lib/public/assets/badge-CSvl5xIU.js +11 -0
- package/lib/public/assets/button-CJlKn4PZ.css +1 -0
- package/lib/public/assets/button-CvLaGFYj.js +26 -0
- package/lib/public/assets/calendar-6w-D6Oaw.js +6 -0
- package/lib/public/assets/clock-DcdeWBPr.js +6 -0
- package/lib/public/assets/cpu-DiSoXT9n.js +6 -0
- package/lib/public/assets/device-explorer-CajM63OJ.js +193 -0
- package/lib/public/assets/device-explorer-CxdUAoTL.css +1 -0
- package/lib/public/assets/index-ByQwMN5T.js +174 -0
- package/lib/public/assets/index-C1DBaoSh.js +1 -0
- package/lib/public/assets/index-qzCez_kk.css +1 -0
- package/lib/public/assets/lock-B23ibZmo.js +6 -0
- package/lib/public/assets/maintenance-settings-CirzA6yG.js +6 -0
- package/lib/public/assets/mouse-pointer-2-Cz76SHFb.js +6 -0
- package/lib/public/assets/plus-BBwlIevt.js +6 -0
- package/lib/public/assets/session-dashboard-C2k7FFv_.css +1 -0
- package/lib/public/assets/session-dashboard-HPDtwPOZ.js +62 -0
- package/lib/public/assets/settings-DrZsZwdc.js +1 -0
- package/lib/public/assets/trash-2-DQpvzJec.js +6 -0
- package/lib/public/assets/useSocket-Dxsqae2a.js +16 -0
- package/lib/public/assets/webhook-settings-CDPgsgkb.css +1 -0
- package/lib/public/assets/webhook-settings-Cp-B4Nrw.js +1 -0
- package/lib/public/assets/zap-DovP6iow.js +6 -0
- package/lib/public/favicon.ico +0 -0
- package/lib/public/favicon.png +0 -0
- package/lib/public/favicon.svg +9 -0
- package/lib/public/index.html +46 -0
- package/lib/public/logo.svg +17 -0
- package/lib/public/logo192.png +0 -0
- package/lib/public/logo512.png +0 -0
- package/lib/public/manifest.json +25 -0
- package/lib/public/robots.txt +3 -0
- package/lib/schema.json +348 -0
- package/lib/src/InternalHttpClient.js +212 -0
- package/lib/src/PluginContext.js +29 -0
- package/lib/src/XenonCapabilityManager.js +199 -0
- package/lib/src/app/index.js +167 -0
- package/lib/src/app/routers/apps.js +79 -0
- package/lib/src/app/routers/config.js +131 -0
- package/lib/src/app/routers/control.js +835 -0
- package/lib/src/app/routers/dashboard.js +301 -0
- package/lib/src/app/routers/grid.js +352 -0
- package/lib/src/app/routers/reservation.js +190 -0
- package/lib/src/app/routers/webhook.js +83 -0
- package/lib/src/app/swagger-docs.js +203 -0
- package/lib/src/app/swagger.js +366 -0
- package/lib/src/chromeUtils.js +148 -0
- package/lib/src/commands/handle.js +19 -0
- package/lib/src/commands/index.js +8 -0
- package/lib/src/config.js +73 -0
- package/lib/src/dashboard/asset-manager.js +84 -0
- package/lib/src/dashboard/commands.js +284 -0
- package/lib/src/dashboard/event-manager.js +699 -0
- package/lib/src/dashboard/services/app-service.js +134 -0
- package/lib/src/dashboard/services/failure-analysis-service.js +173 -0
- package/lib/src/dashboard/services/session-service.js +113 -0
- package/lib/src/data-service/CircuitBreaker.js +83 -0
- package/lib/src/data-service/config-service.js +155 -0
- package/lib/src/data-service/db.js +122 -0
- package/lib/src/data-service/device-service.js +320 -0
- package/lib/src/data-service/device-store.interface.js +2 -0
- package/lib/src/data-service/device-store.js +345 -0
- package/lib/src/data-service/pending-sessions-service.js +25 -0
- package/lib/src/data-service/pluginArgs.js +25 -0
- package/lib/src/data-service/prisma-service.js +31 -0
- package/lib/src/data-service/prisma-store.js +385 -0
- package/lib/src/data-service/queue-service.js +150 -0
- package/lib/src/data-service/web-config-service.js +130 -0
- package/lib/src/device-managers/AndroidDeviceManager.js +1155 -0
- package/lib/src/device-managers/ChromeDriverManager.js +68 -0
- package/lib/src/device-managers/HealthMonitorService.js +325 -0
- package/lib/src/device-managers/IOSDeviceManager.js +351 -0
- package/lib/src/device-managers/NodeDevices.js +82 -0
- package/lib/src/device-managers/android/AndroidStreamService.js +370 -0
- package/lib/src/device-managers/android/DeviceLockManager.js +45 -0
- package/lib/src/device-managers/cloud/CapabilityManager.js +26 -0
- package/lib/src/device-managers/cloud/Devices.js +86 -0
- package/lib/src/device-managers/iOSTracker.js +44 -0
- package/lib/src/device-managers/index.js +89 -0
- package/lib/src/device-managers/ios/IOSDiscoveryService.js +268 -0
- package/lib/src/device-managers/ios/IOSStreamService.js +893 -0
- package/lib/src/device-managers/ios/WDAClient.js +866 -0
- package/lib/src/device-utils.js +663 -0
- package/lib/src/enums/Capabilities.js +8 -0
- package/lib/src/enums/Cloud.js +11 -0
- package/lib/src/enums/Platform.js +9 -0
- package/lib/src/enums/SessionType.js +9 -0
- package/lib/src/enums/SocketEvents.js +15 -0
- package/lib/src/helpers/UniversalMjpegProxy.js +273 -0
- package/lib/src/helpers/index.js +229 -0
- package/lib/src/index.js +95 -0
- package/lib/src/interceptors/CommandInterceptor.js +524 -0
- package/lib/src/interfaces/ICloudManager.js +2 -0
- package/lib/src/interfaces/IDevice.js +2 -0
- package/lib/src/interfaces/IDeviceFilterOptions.js +2 -0
- package/lib/src/interfaces/IDeviceManager.js +2 -0
- package/lib/src/interfaces/IOptions.js +2 -0
- package/lib/src/interfaces/IPluginArgs.js +55 -0
- package/lib/src/interfaces/ISessionCapability.js +2 -0
- package/lib/src/logger.js +225 -0
- package/lib/src/plugin.js +244 -0
- package/lib/src/prisma.js +12 -0
- package/lib/src/profiling/AndroidAppProfiler.js +213 -0
- package/lib/src/proxy/wd-command-proxy.js +221 -0
- package/lib/src/scripts/generate-database-migration.js +59 -0
- package/lib/src/scripts/initialize-database.js +55 -0
- package/lib/src/scripts/install-go-ios.js +66 -0
- package/lib/src/scripts/prepare-prisma.js +89 -0
- package/lib/src/services/AICommandService.js +143 -0
- package/lib/src/services/AIService.js +466 -0
- package/lib/src/services/CleanupService.js +141 -0
- package/lib/src/services/EventBus.js +74 -0
- package/lib/src/services/InspectorService.js +395 -0
- package/lib/src/services/MetricsService.js +134 -0
- package/lib/src/services/NetworkConditioningService.js +173 -0
- package/lib/src/services/NotificationService.js +163 -0
- package/lib/src/services/RequestLogService.js +252 -0
- package/lib/src/services/ResourceIsolationService.js +122 -0
- package/lib/src/services/SecurityService.js +120 -0
- package/lib/src/services/ServerManager.js +284 -0
- package/lib/src/services/SessionHeartbeatService.js +158 -0
- package/lib/src/services/SessionLifecycleService.js +572 -0
- package/lib/src/services/SocketClient.js +71 -0
- package/lib/src/services/SocketServer.js +87 -0
- package/lib/src/services/TracingService.js +132 -0
- package/lib/src/services/VideoPipelineService.js +220 -0
- package/lib/src/services/healing/FuzzyXmlHealingProvider.js +333 -0
- package/lib/src/services/healing/HealEtalonService.js +98 -0
- package/lib/src/services/healing/HealedLocatorGenerator.js +132 -0
- package/lib/src/services/healing/HealingOrchestrator.js +165 -0
- package/lib/src/services/healing/LlmHealingProvider.js +77 -0
- package/lib/src/services/healing/OcrHealingProvider.js +119 -0
- package/lib/src/services/healing/ResilioTreeHealingProvider.js +100 -0
- package/lib/src/services/healing/VisualAiHealingProvider.js +90 -0
- package/lib/src/services/healing/types.js +12 -0
- package/lib/src/services/omni-vision/OmniVisionService.js +718 -0
- package/lib/src/services/omni-vision/VisionAssertionService.js +68 -0
- package/lib/src/sessions/CloudSession.js +42 -0
- package/lib/src/sessions/LocalSession.js +313 -0
- package/lib/src/sessions/RemoteSession.js +287 -0
- package/lib/src/sessions/SessionManager.js +238 -0
- package/lib/src/sessions/XenonSession.js +44 -0
- package/lib/src/types/CLIArgs.js +2 -0
- package/lib/src/types/CloudArgs.js +2 -0
- package/lib/src/types/CloudSchema.js +131 -0
- package/lib/src/types/DeviceType.js +2 -0
- package/lib/src/types/DeviceUpdate.js +2 -0
- package/lib/src/types/IOSDevice.js +2 -0
- package/lib/src/types/Platform.js +2 -0
- package/lib/src/types/SessionStatus.js +11 -0
- package/lib/src/validators/CapabilityValidator.js +93 -0
- package/lib/test/e2e/android/conf.spec.js +43 -0
- package/lib/test/e2e/android/conf2.spec.js +44 -0
- package/lib/test/e2e/android/conf3.spec.js +44 -0
- package/lib/test/e2e/e2ehelper.js +113 -0
- package/lib/test/e2e/hubnode/forward-request.spec.js +224 -0
- package/lib/test/e2e/hubnode/hubnode.spec.js +214 -0
- package/lib/test/e2e/ios/conf1.spec.js +39 -0
- package/lib/test/e2e/ios/conf2.spec.js +39 -0
- package/lib/test/e2e/plugin-harness.js +236 -0
- package/lib/test/e2e/plugin.spec.js +97 -0
- package/lib/test/e2e/telemetry_verification.spec.js +83 -0
- package/lib/test/e2e/video-recording-test.spec.js +63 -0
- package/lib/test/helpers/test-container.js +112 -0
- package/lib/test/integration/androidDevices.spec.js +137 -0
- package/lib/test/integration/cliArgs.js +73 -0
- package/lib/test/integration/ios/01iOSSimulator.spec.js +291 -0
- package/lib/test/integration/ios/02iOSDevices.spec.js +75 -0
- package/lib/test/integration/testHelpers.js +74 -0
- package/lib/test/unit/AndroidDeviceManager.spec.js +178 -0
- package/lib/test/unit/ChromeDriverManager.spec.js +26 -0
- package/lib/test/unit/CleanupService.spec.js +21 -0
- package/lib/test/unit/DeviceModel.spec.js +157 -0
- package/lib/test/unit/FuzzyXmlHealingProvider.test.js +294 -0
- package/lib/test/unit/GetAdbOriginal.js +42 -0
- package/lib/test/unit/HealingCascade.test.js +128 -0
- package/lib/test/unit/IOSDeviceManager.spec.js +261 -0
- package/lib/test/unit/RemoteIOs.spec.js +78 -0
- package/lib/test/unit/ResilioTreeHealingProvider.test.js +96 -0
- package/lib/test/unit/commands.spec.js +27 -0
- package/lib/test/unit/config.spec.js +27 -0
- package/lib/test/unit/device-service.spec.js +307 -0
- package/lib/test/unit/device-utils.spec.js +313 -0
- package/lib/test/unit/fixtures/device.config.js +4 -0
- package/lib/test/unit/fixtures/devices.js +89 -0
- package/lib/test/unit/helpers.spec.js +62 -0
- package/lib/test/unit/omni-vision.spec.js +100 -0
- package/lib/test/unit/plugin.spec.js +133 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +207 -0
- package/prisma/data.db +0 -0
- package/prisma/dev.db +0 -0
- package/prisma/dev.db-journal +0 -0
- package/prisma/migrations/20231011074725_initial_tables/migration.sql +47 -0
- package/prisma/migrations/20231226115334_update_session_log/migration.sql +2 -0
- package/prisma/migrations/20251204113710_add_video_recording_enabled/migration.sql +29 -0
- package/prisma/migrations/20251204132449_add_log_table/migration.sql +11 -0
- package/prisma/migrations/20251205050111_add_profiling_support/migration.sql +47 -0
- package/prisma/migrations/20251205050947_add_is_error_field/migration.sql +24 -0
- package/prisma/migrations/20260126201337_add_app_model/migration.sql +18 -0
- package/prisma/migrations/20260130115722_add_performance_trace_and_xenon_sync/migration.sql +2 -0
- package/prisma/migrations/20260130135114_add_device_models/migration.sql +57 -0
- package/prisma/migrations/20260130140655_make_systemport_optional/migration.sql +45 -0
- package/prisma/migrations/20260130140932_make_device_fields_optional/migration.sql +45 -0
- package/prisma/migrations/20260130141040_final_schema_fix/migration.sql +45 -0
- package/prisma/migrations/20260130143234_add_device_health_fields/migration.sql +4 -0
- package/prisma/migrations/20260130144921_add_failure_category/migration.sql +2 -0
- package/prisma/migrations/20260131151456_add_webhook_config/migration.sql +10 -0
- package/prisma/migrations/20260201094507_add_device_tags/migration.sql +11 -0
- package/prisma/migrations/20260201103410_add_managed_process/migration.sql +15 -0
- package/prisma/migrations/20260201140637_add_web_config/migration.sql +22 -0
- package/prisma/migrations/20260201162232_add_session_progress/migration.sql +2 -0
- package/prisma/migrations/20260201174231_add_total_healed_count/migration.sql +2 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +210 -0
- package/schema.json +348 -0
- package/scripts/build-xenon.sh +32 -0
- package/scripts/dev/debug-gemini.ts +44 -0
- package/scripts/generate-types-from-schema.js +86 -0
- package/scripts/install-compatible-driver.js +39 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.prepareDirectory = prepareDirectory;
|
|
40
|
+
exports.saveScreenShot = saveScreenShot;
|
|
41
|
+
exports.saveVideoRecording = saveVideoRecording;
|
|
42
|
+
exports.savePerformanceTrace = savePerformanceTrace;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const config_1 = require("../config");
|
|
46
|
+
const uuid_1 = require("uuid");
|
|
47
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
48
|
+
const SCREENSHOT_DIRECTORY = 'screenshots';
|
|
49
|
+
const VIDEO_DIRECTORY = 'video';
|
|
50
|
+
const PERFORMANCE_DIRECTORY = 'performance';
|
|
51
|
+
function prepareDirectory(sessionId) {
|
|
52
|
+
[SCREENSHOT_DIRECTORY, VIDEO_DIRECTORY, PERFORMANCE_DIRECTORY].forEach((folder) => {
|
|
53
|
+
fs.mkdirSync(path.join(config_1.config.sessionAssetsPath, sessionId, folder), { recursive: true });
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function saveScreenShot(sessionId, screenshotBase64String) {
|
|
57
|
+
const directory = path.join(config_1.config.sessionAssetsPath, sessionId, SCREENSHOT_DIRECTORY);
|
|
58
|
+
if (!fs.existsSync(directory)) {
|
|
59
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
const assetPath = path.join(sessionId, SCREENSHOT_DIRECTORY, `${(0, uuid_1.v4)()}.png`);
|
|
62
|
+
const fullPath = path.join(config_1.config.sessionAssetsPath, assetPath);
|
|
63
|
+
fs.writeFileSync(fullPath, screenshotBase64String, 'base64');
|
|
64
|
+
logger_1.default.info(`[AssetManager] Saved screenshot for session ${sessionId} at ${fullPath}`);
|
|
65
|
+
return assetPath;
|
|
66
|
+
}
|
|
67
|
+
function saveVideoRecording(sessionId, videoBase64String) {
|
|
68
|
+
const directory = path.join(config_1.config.sessionAssetsPath, sessionId, VIDEO_DIRECTORY);
|
|
69
|
+
if (!fs.existsSync(directory)) {
|
|
70
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
71
|
+
}
|
|
72
|
+
const assetPath = path.join(sessionId, VIDEO_DIRECTORY, `${sessionId}.mp4`);
|
|
73
|
+
fs.writeFileSync(path.join(config_1.config.sessionAssetsPath, assetPath), videoBase64String, 'base64');
|
|
74
|
+
return assetPath;
|
|
75
|
+
}
|
|
76
|
+
function savePerformanceTrace(sessionId, traceBase64String) {
|
|
77
|
+
const directory = path.join(config_1.config.sessionAssetsPath, sessionId, PERFORMANCE_DIRECTORY);
|
|
78
|
+
if (!fs.existsSync(directory)) {
|
|
79
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
80
|
+
}
|
|
81
|
+
const assetPath = path.join(sessionId, PERFORMANCE_DIRECTORY, `${sessionId}.zip`);
|
|
82
|
+
fs.writeFileSync(path.join(config_1.config.sessionAssetsPath, assetPath), traceBase64String, 'base64');
|
|
83
|
+
return assetPath;
|
|
84
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.dashboardCommands = exports.DashboardCommands = void 0;
|
|
49
|
+
const session_service_1 = require("./services/session-service");
|
|
50
|
+
const prisma_1 = require("../prisma");
|
|
51
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
52
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
53
|
+
const SessionManager_1 = require("../sessions/SessionManager");
|
|
54
|
+
const asset_manager_1 = require("./asset-manager");
|
|
55
|
+
class DashboardCommands {
|
|
56
|
+
isDashboardCommand(commandName) {
|
|
57
|
+
return commandName.startsWith('xenon') || commandName.startsWith('xe');
|
|
58
|
+
}
|
|
59
|
+
process(sessionId, request, response) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
const { script } = request.body;
|
|
62
|
+
logger_1.default.info(`[DashboardCommands] Processing command: ${script}`);
|
|
63
|
+
if (!script) {
|
|
64
|
+
return this.sendSuccessResponse(response);
|
|
65
|
+
}
|
|
66
|
+
const commandName = script.split(':')[1];
|
|
67
|
+
logger_1.default.info(`[DashboardCommands] Parsed command name: ${commandName}`);
|
|
68
|
+
if (commandName && commandName.trim()) {
|
|
69
|
+
const trimmedCommand = commandName.trim();
|
|
70
|
+
logger_1.default.info(`[DashboardCommands] Trimmed command: ${trimmedCommand}`);
|
|
71
|
+
switch (trimmedCommand) {
|
|
72
|
+
case 'setSessionName':
|
|
73
|
+
logger_1.default.info('[DashboardCommands] Executing setSessionName');
|
|
74
|
+
return yield this.setSessionName(sessionId, request, response);
|
|
75
|
+
case 'setSessionStatus':
|
|
76
|
+
logger_1.default.info('[DashboardCommands] Executing setSessionStatus');
|
|
77
|
+
return yield this.setSessionStatus(sessionId, request, response);
|
|
78
|
+
case 'debug':
|
|
79
|
+
logger_1.default.info('[DashboardCommands] Executing debug command');
|
|
80
|
+
return yield this.debug(sessionId, request, response);
|
|
81
|
+
case 'captureEvidence':
|
|
82
|
+
logger_1.default.info('[DashboardCommands] Executing captureEvidence');
|
|
83
|
+
return yield this.captureEvidence(sessionId, request, response);
|
|
84
|
+
case 'addTag':
|
|
85
|
+
logger_1.default.info('[DashboardCommands] Executing addTag');
|
|
86
|
+
return yield this.addTag(sessionId, request, response);
|
|
87
|
+
default:
|
|
88
|
+
logger_1.default.warn(`[DashboardCommands] Unknown command: ${trimmedCommand}`);
|
|
89
|
+
return this.sendSuccessResponse(response);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return this.sendSuccessResponse(response);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
sendSuccessResponse(response) {
|
|
96
|
+
return response.status(200).json({ value: null });
|
|
97
|
+
}
|
|
98
|
+
/* Commands */
|
|
99
|
+
/**
|
|
100
|
+
* Set the name of current test(session)
|
|
101
|
+
*
|
|
102
|
+
* driver.executeScript("xenon: setSessionName", "MyTestName")
|
|
103
|
+
* or
|
|
104
|
+
* driver.executeScript("xenon: setSessionName", {"name": "MyTestName"})
|
|
105
|
+
*/
|
|
106
|
+
setSessionName(sessionId, request, response) {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
const { args } = request.body;
|
|
109
|
+
yield (0, session_service_1.updateSessionDetails)(sessionId, {
|
|
110
|
+
name: typeof args[0] === 'object' && args[0].name ? args[0].name : args[0],
|
|
111
|
+
});
|
|
112
|
+
return this.sendSuccessResponse(response);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Update the status of the session
|
|
117
|
+
*
|
|
118
|
+
* driver.executeScript("xenon: setSessionStatus", {"status": "passed/failed", "reason": "optional reason"})
|
|
119
|
+
*/
|
|
120
|
+
setSessionStatus(sessionId, request, response) {
|
|
121
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
122
|
+
const { args } = request.body;
|
|
123
|
+
let statusArg = {};
|
|
124
|
+
if (lodash_1.default.isArray(args)) {
|
|
125
|
+
if (typeof args[0] === 'object') {
|
|
126
|
+
statusArg = args[0];
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Handle positional: executeScript("xe:setSessionStatus", "failed", "reason")
|
|
130
|
+
statusArg = {
|
|
131
|
+
status: args[0],
|
|
132
|
+
reason: args[1],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (typeof args === 'object') {
|
|
137
|
+
statusArg = args;
|
|
138
|
+
}
|
|
139
|
+
// Normalize input
|
|
140
|
+
const inputStatus = (statusArg.status || '').toLowerCase();
|
|
141
|
+
const validStatuses = ['success', 'failed', 'passed'];
|
|
142
|
+
if (!validStatuses.includes(inputStatus)) {
|
|
143
|
+
logger_1.default.warn(`[DashboardCommands] Invalid status: ${statusArg.status}. Valid: ${validStatuses.join(', ')}`);
|
|
144
|
+
return this.sendSuccessResponse(response);
|
|
145
|
+
}
|
|
146
|
+
// Normalize 'passed' to 'success' for consistency with SessionStatus enum
|
|
147
|
+
const normalizedStatus = inputStatus === 'passed' ? 'success' : inputStatus;
|
|
148
|
+
yield (0, session_service_1.updateSessionDetails)(sessionId, {
|
|
149
|
+
status: normalizedStatus,
|
|
150
|
+
failure_reason: statusArg.reason || undefined,
|
|
151
|
+
});
|
|
152
|
+
// --- REAL-TIME UI UPDATE ---
|
|
153
|
+
// Principal Speed: Emit a socket event so the dashboard row updates immediately.
|
|
154
|
+
const { SocketServer } = yield Promise.resolve().then(() => __importStar(require('../services/SocketServer')));
|
|
155
|
+
const { Container } = yield Promise.resolve().then(() => __importStar(require('typedi')));
|
|
156
|
+
const { SocketEvents } = yield Promise.resolve().then(() => __importStar(require('../enums/SocketEvents')));
|
|
157
|
+
Container.get(SocketServer).emitToDashboard(SocketEvents.SESSION_STOPPED, {
|
|
158
|
+
id: sessionId,
|
|
159
|
+
status: normalizedStatus,
|
|
160
|
+
failure_reason: args.reason || undefined,
|
|
161
|
+
});
|
|
162
|
+
return this.sendSuccessResponse(response);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Add debug logs to the session
|
|
167
|
+
*
|
|
168
|
+
* driver.executeScript("xenon: debug", {"message": "Debug message"})
|
|
169
|
+
* or
|
|
170
|
+
* driver.executeScript("xenon: debug", "Debug message")
|
|
171
|
+
*/
|
|
172
|
+
debug(sessionId, request, response) {
|
|
173
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
const { args } = request.body;
|
|
175
|
+
const logData = lodash_1.default.isArray(args) ? args[0] : args;
|
|
176
|
+
// Support both string and object format
|
|
177
|
+
const message = typeof logData === 'string' ? logData : logData.message || JSON.stringify(logData);
|
|
178
|
+
yield prisma_1.prisma.log.create({
|
|
179
|
+
data: {
|
|
180
|
+
session_id: sessionId,
|
|
181
|
+
log_type: 'DEBUG',
|
|
182
|
+
message: message,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
return this.sendSuccessResponse(response);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Capture evidence (screenshot) with optional reason/label
|
|
190
|
+
*
|
|
191
|
+
* driver.executeScript("xenon: captureEvidence", {"reason": "Login failed", "label": "error_state"})
|
|
192
|
+
* or
|
|
193
|
+
* driver.executeScript("xenon: captureEvidence", "Checkpoint reached")
|
|
194
|
+
*/
|
|
195
|
+
captureEvidence(sessionId, request, response) {
|
|
196
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
+
const { args } = request.body;
|
|
198
|
+
const evidenceData = lodash_1.default.isArray(args) ? args[0] : args;
|
|
199
|
+
const reason = typeof evidenceData === 'string' ? evidenceData : evidenceData.reason || 'Manual capture';
|
|
200
|
+
const label = typeof evidenceData === 'object' ? evidenceData.label : undefined;
|
|
201
|
+
try {
|
|
202
|
+
const session = SessionManager_1.SESSION_MANAGER.getSession(sessionId);
|
|
203
|
+
if (!session) {
|
|
204
|
+
logger_1.default.warn(`[DashboardCommands] captureEvidence: Session ${sessionId} not found`);
|
|
205
|
+
return this.sendSuccessResponse(response);
|
|
206
|
+
}
|
|
207
|
+
const screenshotBase64 = yield session.getScreenShot();
|
|
208
|
+
if (screenshotBase64) {
|
|
209
|
+
const screenshotPath = (0, asset_manager_1.saveScreenShot)(sessionId, screenshotBase64);
|
|
210
|
+
// Log the evidence capture
|
|
211
|
+
yield prisma_1.prisma.sessionLog.create({
|
|
212
|
+
data: {
|
|
213
|
+
session_id: sessionId,
|
|
214
|
+
command_name: 'captureEvidence',
|
|
215
|
+
body: JSON.stringify({ reason, label }),
|
|
216
|
+
response: JSON.stringify({ captured: true }),
|
|
217
|
+
is_success: true,
|
|
218
|
+
is_error: false,
|
|
219
|
+
method: 'POST',
|
|
220
|
+
title: 'Evidence Captured',
|
|
221
|
+
subtitle: reason,
|
|
222
|
+
screenshot: screenshotPath,
|
|
223
|
+
url: '/execute/sync',
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
logger_1.default.info(`[DashboardCommands] Evidence captured for ${sessionId}: ${reason}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
logger_1.default.error(`[DashboardCommands] captureEvidence failed: ${err.message}`);
|
|
231
|
+
}
|
|
232
|
+
return this.sendSuccessResponse(response);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Add searchable tags to the session
|
|
237
|
+
*
|
|
238
|
+
* driver.executeScript("xenon: addTag", {"tag": "regression"})
|
|
239
|
+
* or
|
|
240
|
+
* driver.executeScript("xenon: addTag", "smoke-test")
|
|
241
|
+
*/
|
|
242
|
+
addTag(sessionId, request, response) {
|
|
243
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
const { args } = request.body;
|
|
245
|
+
const tagData = lodash_1.default.isArray(args) ? args[0] : args;
|
|
246
|
+
const newTag = typeof tagData === 'string' ? tagData : tagData.tag;
|
|
247
|
+
if (!newTag) {
|
|
248
|
+
logger_1.default.warn('[DashboardCommands] addTag: No tag provided');
|
|
249
|
+
return this.sendSuccessResponse(response);
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
// Get current session to append tag
|
|
253
|
+
const session = yield prisma_1.prisma.session.findUnique({
|
|
254
|
+
where: { id: sessionId },
|
|
255
|
+
select: { tags: true },
|
|
256
|
+
});
|
|
257
|
+
// Parse existing tags or initialize empty array
|
|
258
|
+
let existingTags = [];
|
|
259
|
+
if (session === null || session === void 0 ? void 0 : session.tags) {
|
|
260
|
+
try {
|
|
261
|
+
existingTags = JSON.parse(session.tags);
|
|
262
|
+
}
|
|
263
|
+
catch (_a) {
|
|
264
|
+
existingTags = [];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Add new tag if not already present
|
|
268
|
+
if (!existingTags.includes(newTag)) {
|
|
269
|
+
existingTags.push(newTag);
|
|
270
|
+
yield (0, session_service_1.updateSessionDetails)(sessionId, {
|
|
271
|
+
tags: JSON.stringify(existingTags),
|
|
272
|
+
});
|
|
273
|
+
logger_1.default.info(`[DashboardCommands] Tag added to ${sessionId}: ${newTag}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
logger_1.default.error(`[DashboardCommands] addTag failed: ${err.message}`);
|
|
278
|
+
}
|
|
279
|
+
return this.sendSuccessResponse(response);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
exports.DashboardCommands = DashboardCommands;
|
|
284
|
+
exports.dashboardCommands = new DashboardCommands();
|