@xenon-device-management/xenon 2.13.2 → 2.15.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 +17 -8
- package/lib/package.json +5 -5
- package/lib/public/assets/{AnnotationOverlay-BXruClDk.js → AnnotationOverlay-Btq3dZRI.js} +1 -1
- package/lib/public/assets/{ApiKeyGate-qTS4LPLC.js → ApiKeyGate-C9OoAgg_.js} +1 -1
- package/lib/public/assets/DeviceMosaicView-DBC_xczB.js +2 -0
- package/lib/public/assets/{EmptyState-Cr17PdDv.js → EmptyState-DqWU2-vM.js} +1 -1
- package/lib/public/assets/{FieldGroup-Bvn08svv.js → FieldGroup-CveQ3xrA.js} +1 -1
- package/lib/public/assets/{FilterMenu-DDSO8aDf.js → FilterMenu-BfKDSfHz.js} +1 -1
- package/lib/public/assets/{Menu-B-Qn2X3T.js → Menu-CtdCybzA.js} +1 -1
- package/lib/public/assets/{Modal-Cg9V5JYU.js → Modal-Bsvj1tm2.js} +1 -1
- package/lib/public/assets/{RecordingPage-BTUs9VTW.js → RecordingPage-CRofOiyx.js} +1 -1
- package/lib/public/assets/{RecordingsPage-DYcfxITK.js → RecordingsPage-jNQHb2IR.js} +2 -2
- package/lib/public/assets/{SegmentedControl-Zy7suhT5.js → SegmentedControl-C8HtTha-.js} +1 -1
- package/lib/public/assets/{SettingCard-CWYmycoe.js → SettingCard-D8K1LZNo.js} +1 -1
- package/lib/public/assets/{Table-io9fwa98.js → Table-zNTX92Pn.js} +1 -1
- package/lib/public/assets/{activity-Bdf_uIWl.js → activity-CJ8LwZq9.js} +1 -1
- package/lib/public/assets/ai-settings-CgxQZqrc.js +16 -0
- package/lib/public/assets/{api-keys-CPqtVpm3.js → api-keys-ECpo-zTo.js} +1 -1
- package/lib/public/assets/{apps-BgZan0H9.js → apps-BjGymyf3.js} +2 -2
- package/lib/public/assets/{arrow-left-B27ckB31.js → arrow-left-BWfCbeHP.js} +1 -1
- package/lib/public/assets/{arrow-right-DOF8ITCz.js → arrow-right-DC7UGf_n.js} +1 -1
- package/lib/public/assets/{arrow-up-right-eFG5KTFS.js → arrow-up-right-BOjwybDk.js} +1 -1
- package/lib/public/assets/{auth-shell-DlC3_27j.js → auth-shell-CxMTo9aH.js} +2 -2
- package/lib/public/assets/{builds-page-BuXpPfKo.js → builds-page-DOCm4HkA.js} +1 -1
- package/lib/public/assets/{button-fIW8owMI.js → button-Cg08-EMT.js} +1 -1
- package/lib/public/assets/{calendar-WNjmrF-a.js → calendar-CA1ikLJs.js} +1 -1
- package/lib/public/assets/{check-BdTh1Sq7.js → check-BMTaH72W.js} +1 -1
- package/lib/public/assets/{chevron-right-B4BKlsqk.js → chevron-right-B2QOv9Nx.js} +1 -1
- package/lib/public/assets/{circle-check-zJU80_EF.js → circle-check-CYXBoUqT.js} +1 -1
- package/lib/public/assets/{circle-x-5Uwquo0h.js → circle-x-DTwnSAnl.js} +1 -1
- package/lib/public/assets/{clock-BtUprDsZ.js → clock-C8_HViQP.js} +1 -1
- package/lib/public/assets/{copy-DGSbZI3u.js → copy-Be7LNMXV.js} +1 -1
- package/lib/public/assets/derive-UnLRp4r3.js +1 -0
- package/lib/public/assets/device-explorer-BOqtfGXz.js +282 -0
- package/lib/public/assets/{download-WG6l7BgD.js → download-B56lwxWP.js} +1 -1
- package/lib/public/assets/forgot-password-CCU6bzLn.js +1 -0
- package/lib/public/assets/h264Stream-C-OtmIuk.js +26 -0
- package/lib/public/assets/index-B9KQ6LsY.js +15 -0
- package/lib/public/assets/{index-DI1fGIyj.js → index-BOxe43p1.js} +5 -5
- package/lib/public/assets/{index-HDQVe1gi.js → index-CfxsUslp.js} +1 -1
- package/lib/public/assets/{input-BjDRKCea.js → input-CZHFjbSg.js} +1 -1
- package/lib/public/assets/{line-chart-C0zdgd0v.js → line-chart-Gl_Dz3X_.js} +1 -1
- package/lib/public/assets/{list-checks-BdW5CjM8.js → list-checks-CCgjeyGY.js} +1 -1
- package/lib/public/assets/{lock-Dy3L4I8E.js → lock-CkOwgDcx.js} +1 -1
- package/lib/public/assets/{login-BHbY9CLG.js → login-D5cc4w7M.js} +1 -1
- package/lib/public/assets/maintenance-settings-t7qr3fvX.js +6 -0
- package/lib/public/assets/{monitor-8xjkeHHi.js → monitor-DEJixKQO.js} +1 -1
- package/lib/public/assets/{mouse-pointer-2-CXdKMXQ8.js → mouse-pointer-2-CtOrk4M8.js} +1 -1
- package/lib/public/assets/{network-Cj8JOKON.js → network-Dii9qdvk.js} +1 -1
- package/lib/public/assets/{overview-CTg7F0im.js → overview-rolAACrO.js} +1 -1
- package/lib/public/assets/{page-header--aTyJXq6.js → page-header-COQZxJfR.js} +1 -1
- package/lib/public/assets/{play-B-FodgHV.js → play-DrN1Se_R.js} +1 -1
- package/lib/public/assets/{plus-CsIk10Cq.js → plus-5aq-9uRx.js} +1 -1
- package/lib/public/assets/{profile-page-DkFKkMfl.js → profile-page-6i5kY6kF.js} +1 -1
- package/lib/public/assets/{reset-password-I2-zqLlI.js → reset-password-sp2IBrc7.js} +1 -1
- package/lib/public/assets/runbook-page-DJDjeopU.js +253 -0
- package/lib/public/assets/{select-DvCSv25z.js → select-Bpyn7rWO.js} +1 -1
- package/lib/public/assets/{selector-detail-redirect-BLVfMJs_.js → selector-detail-redirect-BH74vmKv.js} +1 -1
- package/lib/public/assets/{selector-health-page-oqadRokn.js → selector-health-page-Cw_g218H.js} +2 -2
- package/lib/public/assets/session-detail-page-AZJE6XXE.js +4 -0
- package/lib/public/assets/settings-C3uyGhyc.js +6 -0
- package/lib/public/assets/{settings-Dep_3kbA.css → settings-K8UHWMdI.css} +1 -1
- package/lib/public/assets/{stat-tile-DV9Ix-4O.js → stat-tile-xVqAKIlI.js} +1 -1
- package/lib/public/assets/{tablet-6b_SEN2X.js → tablet-BxUScAeO.js} +1 -1
- package/lib/public/assets/{teams-BjZyfuHh.js → teams-B5ljGkY2.js} +1 -1
- package/lib/public/assets/{trash-2-CTZpPSdd.js → trash-2-B701i8sy.js} +1 -1
- package/lib/public/assets/{upload-P3XzwQUb.js → upload-C2gr44RS.js} +1 -1
- package/lib/public/assets/{use-builds-data-1cOCMf-z.js → use-builds-data-NeQOFEoy.js} +1 -1
- package/lib/public/assets/{use-password-reset-mode-DgF9w088.js → use-password-reset-mode-DEzJq5ef.js} +1 -1
- package/lib/public/assets/{users-DMF9Mk5H.js → users-D_vv_yz4.js} +1 -1
- package/lib/public/assets/{users-CiNTKUiz.js → users-MY6eNe6s.js} +1 -1
- package/lib/public/assets/{video-off-CHp1KU_T.js → video-off-OK1lNZQn.js} +1 -1
- package/lib/public/assets/webhook-settings-BU-C9lBf.js +1 -0
- package/lib/public/assets/{zap-DRz0tDq5.js → zap-DO9ry1iz.js} +1 -1
- package/lib/public/index.html +1 -1
- package/lib/schema.json +23 -25
- package/lib/src/XenonCapabilityManager.js +22 -5
- package/lib/src/app/dashboardPluginLink.js +117 -0
- package/lib/src/app/index.js +13 -34
- package/lib/src/app/openapi/control.yaml +73 -20
- package/lib/src/app/openapi/grid.yaml +31 -7
- package/lib/src/app/openapi/identity.yaml +103 -31
- package/lib/src/app/openapi/platform.yaml +165 -39
- package/lib/src/app/openapi/sessions.yaml +10 -3
- package/lib/src/app/routers/apikeys.js +14 -2
- package/lib/src/app/routers/auth.js +29 -5
- package/lib/src/app/routers/control.js +20 -2
- package/lib/src/app/routers/dashboard.js +69 -26
- package/lib/src/app/routers/grid.js +37 -13
- package/lib/src/app/routers/profile.js +21 -0
- package/lib/src/app/routers/streamType.js +7 -2
- package/lib/src/app/routers/users.js +10 -5
- package/lib/src/app/routers/webhook.js +8 -4
- package/lib/src/app/swagger.js +2 -0
- package/lib/src/app/ws/h264StreamWs.js +10 -1
- package/lib/src/config.js +51 -5
- package/lib/src/dashboard/commands.js +185 -141
- package/lib/src/dashboard/event-manager.js +88 -67
- package/lib/src/dashboard/services/failure-analysis-service.js +136 -45
- package/lib/src/dashboard/sessionCommandSummary.js +39 -0
- package/lib/src/data-service/appleFamily.js +43 -0
- package/lib/src/data-service/db.js +11 -0
- package/lib/src/data-service/device-service.js +6 -1
- package/lib/src/data-service/device-store.js +76 -3
- package/lib/src/data-service/deviceClaims.js +37 -0
- package/lib/src/data-service/deviceFieldOwners.js +25 -11
- package/lib/src/data-service/deviceSettings.js +79 -0
- package/lib/src/data-service/prisma-store.js +169 -15
- package/lib/src/data-service/web-config-service.js +50 -92
- package/lib/src/device-managers/AndroidDeviceManager.js +9 -31
- package/lib/src/device-managers/android/AndroidH264StreamService.js +69 -20
- package/lib/src/device-managers/android/H264Multiplexer.js +38 -4
- package/lib/src/device-managers/ios/WDAClient.js +44 -43
- package/lib/src/device-managers/shellCommands.js +96 -0
- package/lib/src/device-utils.js +114 -40
- package/lib/src/gateway/defaultGateway.js +1 -1
- package/lib/src/gateway/forwardToNode.js +2 -0
- package/lib/src/gateway/healReport.js +87 -0
- package/lib/src/gateway/sessionGateway.js +12 -2
- package/lib/src/generated/client/edge.js +18 -3
- package/lib/src/generated/client/index-browser.js +15 -0
- package/lib/src/generated/client/index.d.ts +2086 -379
- package/lib/src/generated/client/index.js +18 -3
- package/lib/src/generated/client/package.json +1 -1
- package/lib/src/generated/client/schema.prisma +38 -7
- package/lib/src/generated/client/wasm.js +15 -0
- package/lib/src/interceptors/CommandInterceptor.js +271 -188
- package/lib/src/interceptors/xenonScripts.js +55 -0
- package/lib/src/interfaces/IPluginArgs.js +1 -2
- package/lib/src/middleware/authMiddleware.js +15 -3
- package/lib/src/middleware/commandCaller.js +3 -3
- package/lib/src/middleware/verifyCredential.js +58 -1
- package/lib/src/plugin.js +23 -4
- package/lib/src/prisma.js +1 -1
- package/lib/src/scripts/database-check.js +124 -0
- package/lib/src/services/AICommandService.js +9 -2
- package/lib/src/services/AIService.js +281 -32
- package/lib/src/services/CleanupService.js +6 -1
- package/lib/src/services/EmailService.js +29 -0
- package/lib/src/services/InterceptorService.js +70 -13
- package/lib/src/services/NetworkConditioningService.js +85 -88
- package/lib/src/services/NotificationService.js +36 -29
- package/lib/src/services/OrphanSweeper.js +7 -0
- package/lib/src/services/PortAllocator.js +5 -0
- package/lib/src/services/SelectorVerificationJob.js +15 -4
- package/lib/src/services/ServerManager.js +105 -9
- package/lib/src/services/SessionLifecycleService.js +133 -75
- package/lib/src/services/ShutdownCoordinator.js +33 -0
- package/lib/src/services/SocketServer.js +19 -3
- package/lib/src/services/TeamService.js +20 -3
- package/lib/src/services/bug-report/video-slice.js +4 -1
- package/lib/src/services/device-access/leaseOverride.js +7 -5
- package/lib/src/services/healing/FuzzyXmlHealingProvider.js +51 -0
- package/lib/src/services/healing/HealEtalonService.js +3 -2
- package/lib/src/services/healing/HealingOrchestrator.js +85 -71
- package/lib/src/services/healing/OcrHealingProvider.js +41 -64
- package/lib/src/services/healing/ResilioTreeHealingProvider.js +41 -50
- package/lib/src/services/healing/VisualAiHealingProvider.js +1 -1
- package/lib/src/services/healing/fingerprintIdentity.js +126 -0
- package/lib/src/services/healing/resilioPath.js +274 -0
- package/lib/src/services/interceptor/AndroidProxyAdapter.js +18 -0
- package/lib/src/services/interceptor/interceptorOptions.js +44 -0
- package/lib/src/services/logcat/SessionDeviceLogs.js +271 -0
- package/lib/src/services/logcat/deviceLogBook.js +163 -0
- package/lib/src/services/network/AndroidRadios.js +71 -0
- package/lib/src/services/network/PhoneNetworkLedger.js +184 -0
- package/lib/src/services/network/PhoneNetworkRestore.js +330 -0
- package/lib/src/services/network/adbForPhone.js +60 -0
- package/lib/src/services/network/phoneNetworkLock.js +20 -0
- package/lib/src/services/network/xenonProxy.js +107 -0
- package/lib/src/services/ocr/ocrData.js +118 -0
- package/lib/src/services/ocr/vendor/LICENSE-tessdata.txt +202 -0
- package/lib/src/services/ocr/vendor/eng.traineddata.gz +0 -0
- package/lib/src/services/omni-vision/OmniVisionService.js +132 -95
- package/lib/src/services/omni-vision/VisionAssertionService.js +28 -25
- package/lib/src/services/omni-vision/ocrTextMatch.js +105 -0
- package/lib/src/services/omni-vision/screenScale.js +68 -0
- package/lib/src/services/passwordResetLink.js +50 -9
- package/lib/src/services/passwordResetMode.js +3 -1
- package/lib/src/services/publicUrl.js +45 -0
- package/lib/src/services/recording/concurrency-gate.js +12 -3
- package/lib/src/services/session/sessionIdentity.js +5 -3
- package/lib/src/services/session/shutdownReason.js +26 -0
- package/lib/src/services/settings/SelfHealingSwitch.js +70 -0
- package/lib/src/services/settings/aiEngineSettings.js +219 -0
- package/lib/src/services/settings/labSettings.js +149 -0
- package/lib/src/services/token/mintedLifetime.js +51 -0
- package/lib/src/services/webhookEvents.js +173 -0
- package/lib/src/sessions/SessionManager.js +8 -2
- package/lib/src/sessions/sessionMemory.js +25 -0
- package/lib/test/helpers/fake-adb.js +58 -0
- package/lib/test/helpers/fake-ai-provider.js +188 -0
- package/lib/test/helpers/fake-device-table.js +63 -24
- package/lib/test/helpers/loki-stores.js +33 -0
- package/lib/test/helpers/page-sources.js +164 -0
- package/lib/test/helpers/scratch-database.js +58 -13
- package/lib/test/integration/audit-ingest.spec.js +10 -10
- package/lib/test/integration/auth-flow.spec.js +9 -14
- package/lib/test/integration/auth-rate-limit.spec.js +6 -3
- package/lib/test/integration/bug-report-route.spec.js +22 -2
- package/lib/test/integration/forgot-password-rate-limit.spec.js +6 -3
- package/lib/test/integration/forgot-password.spec.js +17 -18
- package/lib/test/integration/legacy-deprecation-headers.spec.js +5 -2
- package/lib/test/integration/migration.spec.js +6 -1
- package/lib/test/integration/node-pair-auth-rest.spec.js +5 -9
- package/lib/test/integration/ports-router.spec.js +4 -4
- package/lib/test/integration/prisma-device-store-add-devices.spec.js +2 -3
- package/lib/test/integration/prisma-device-store-team-filter.spec.js +2 -5
- package/lib/test/integration/profile-tokens.spec.js +10 -16
- package/lib/test/integration/recordings-router.spec.js +16 -16
- package/lib/test/integration/reset-revokes-sessions.spec.js +4 -9
- package/lib/test/integration/role-matrix.spec.js +4 -9
- package/lib/test/integration/sdk-leases-router.spec.js +9 -9
- package/lib/test/integration/sdk-version.spec.js +2 -2
- package/lib/test/integration/selector-health-endpoint.spec.js +5 -5
- package/lib/test/integration/team-membership-migration.spec.js +73 -12
- package/lib/test/integration/team-visibility-apps.spec.js +15 -22
- package/lib/test/integration/team-visibility-control.spec.js +96 -69
- package/lib/test/integration/team-visibility-dashboard.spec.js +7 -23
- package/lib/test/integration/team-visibility-grid.spec.js +16 -15
- package/lib/test/integration/team-visibility-leases.spec.js +8 -11
- package/lib/test/integration/team-visibility-recordings.spec.js +6 -19
- package/lib/test/integration/team-visibility-sessions.spec.js +6 -19
- package/lib/test/integration/users-flow.spec.js +7 -12
- package/lib/test/integration/users-lockout.spec.js +5 -3
- package/lib/test/unit/EmailService.test.js +66 -0
- package/lib/test/unit/ResilioTreeHealingProvider.test.js +46 -19
- package/lib/test/unit/TeamService.test.js +3 -0
- package/lib/test/unit/XenonCapabilityManager.spec.js +4 -2
- package/lib/test/unit/ai-call-time-limit.spec.js +130 -0
- package/lib/test/unit/ai-engine-settings.spec.js +338 -0
- package/lib/test/unit/ai-provider-switch.spec.js +130 -0
- package/lib/test/unit/ai-rate-limit.spec.js +126 -0
- package/lib/test/unit/android-h264-viewers.spec.js +272 -0
- package/lib/test/unit/android-preview-hold.spec.js +3 -2
- package/lib/test/unit/apikeys-router.spec.js +84 -0
- package/lib/test/unit/apple-family.spec.js +36 -0
- package/lib/test/unit/authMiddleware.bearer.spec.js +9 -0
- package/lib/test/unit/authMiddleware.credentialLifetime.spec.js +149 -0
- package/lib/test/unit/bug-report/video-slice.spec.js +19 -0
- package/lib/test/unit/cleanup-settings-db.spec.js +103 -0
- package/lib/test/unit/cleanup-settings.spec.js +244 -0
- package/lib/test/unit/dashboard-api-paths.spec.js +101 -0
- package/lib/test/unit/dashboard-commands.spec.js +249 -0
- package/lib/test/unit/dashboard-events-device-logs.spec.js +207 -0
- package/lib/test/unit/dashboard-events-team-scope.spec.js +9 -6
- package/lib/test/unit/dashboard-plugin-link.spec.js +213 -0
- package/lib/test/unit/database-check.spec.js +108 -0
- package/lib/test/unit/default-plugin-args.spec.js +33 -0
- package/lib/test/unit/device-log-book.spec.js +180 -0
- package/lib/test/unit/device-offline-webhook.spec.js +81 -0
- package/lib/test/unit/device-setting-columns.spec.js +66 -0
- package/lib/test/unit/device-settings-loki.spec.js +87 -0
- package/lib/test/unit/device-settings-survive.spec.js +555 -0
- package/lib/test/unit/device-sync-lost-update.spec.js +5 -0
- package/lib/test/unit/emulator-boot.spec.js +91 -0
- package/lib/test/unit/enable-dashboard-option.spec.js +57 -0
- package/lib/test/unit/event-log-session-data.spec.js +244 -0
- package/lib/test/unit/failure-analysis.spec.js +182 -0
- package/lib/test/unit/failure-categories.spec.js +128 -0
- package/lib/test/unit/fingerprint-identity.spec.js +433 -0
- package/lib/test/unit/h264-multiplexer.spec.js +46 -0
- package/lib/test/unit/heal-report.spec.js +71 -0
- package/lib/test/unit/healing-instrumentation.spec.js +6 -1
- package/lib/test/unit/healing-tier-gate.spec.js +73 -29
- package/lib/test/unit/healing-tiers-every-session.spec.js +219 -0
- package/lib/test/unit/hub-node-gateway-appium-server.spec.js +219 -0
- package/lib/test/unit/hub-node-same-host.spec.js +5 -0
- package/lib/test/unit/interceptor-visual-elements.spec.js +192 -0
- package/lib/test/unit/iphone-ipad-only.spec.js +132 -0
- package/lib/test/unit/json-logging-option.spec.js +74 -0
- package/lib/test/unit/lab-settings.spec.js +218 -0
- package/lib/test/unit/lease/lease-override.spec.js +23 -6
- package/lib/test/unit/lease/session-lease-proof.spec.js +16 -4
- package/lib/test/unit/max-sessions.spec.js +240 -0
- package/lib/test/unit/ocr-healing-tier-real-ocr.spec.js +113 -0
- package/lib/test/unit/ocr-healing-tier.spec.js +122 -0
- package/lib/test/unit/ocr-offline.spec.js +213 -0
- package/lib/test/unit/ocr-text-match.spec.js +44 -0
- package/lib/test/unit/omni-virtual-element-store.spec.js +301 -0
- package/lib/test/unit/omni-vision-analyze-screen.spec.js +72 -0
- package/lib/test/unit/omni-vision-ios-points.spec.js +159 -0
- package/lib/test/unit/omni-vision-tap-text.spec.js +129 -0
- package/lib/test/unit/omni-vision.spec.js +6 -8
- package/lib/test/unit/package-engines.spec.js +27 -0
- package/lib/test/unit/partial-config-file.spec.js +14 -0
- package/lib/test/unit/passwordResetMode.test.js +10 -2
- package/lib/test/unit/phone-network/boot-clean-up.spec.js +64 -0
- package/lib/test/unit/phone-network/interceptor-options.spec.js +77 -0
- package/lib/test/unit/phone-network/interceptor-proxy-restore.spec.js +145 -0
- package/lib/test/unit/phone-network/network-conditioning.spec.js +145 -0
- package/lib/test/unit/phone-network/phone-network-restore.spec.js +246 -0
- package/lib/test/unit/phone-network/session-end-paths.spec.js +182 -0
- package/lib/test/unit/phone-network/session-start.spec.js +110 -0
- package/lib/test/unit/phone-network/xenon-proxy.spec.js +69 -0
- package/lib/test/unit/plugin.spec.js +3 -3
- package/lib/test/unit/profile-router.test.js +122 -1
- package/lib/test/unit/queue-requester.spec.js +1 -1
- package/lib/test/unit/recording-options.spec.js +181 -0
- package/lib/test/unit/reset-link-address.spec.js +266 -0
- package/lib/test/unit/reset-link.test.js +10 -4
- package/lib/test/unit/resilio-path-healing.spec.js +270 -0
- package/lib/test/unit/selector-learning-every-session.spec.js +179 -0
- package/lib/test/unit/selector-verification-clean-build.spec.js +130 -0
- package/lib/test/unit/selector-verification-job.spec.js +13 -13
- package/lib/test/unit/self-healing-boot.spec.js +80 -0
- package/lib/test/unit/self-healing-setting.spec.js +273 -0
- package/lib/test/unit/session-app-resolution.spec.js +5 -1
- package/lib/test/unit/session-attribution-wiring.spec.js +41 -13
- package/lib/test/unit/session-create-credential-owner.spec.js +242 -0
- package/lib/test/unit/session-credential-strip.spec.js +1 -1
- package/lib/test/unit/session-device-logs.spec.js +347 -0
- package/lib/test/unit/session-end-failure-analysis.spec.js +133 -0
- package/lib/test/unit/session-failed-webhook.spec.js +170 -0
- package/lib/test/unit/session-log-indexes.spec.js +64 -3
- package/lib/test/unit/shell-commands.spec.js +133 -0
- package/lib/test/unit/socketServer.scopedEmit.spec.js +2 -0
- package/lib/test/unit/socketServer.sessionCookie.spec.js +2 -1
- package/lib/test/unit/stream-start-pipelines.spec.js +264 -0
- package/lib/test/unit/stream-status-type.spec.js +4 -0
- package/lib/test/unit/token-mint-limits.spec.js +165 -0
- package/lib/test/unit/unexpected-shutdown-reason.spec.js +163 -0
- package/lib/test/unit/verify-credential.spec.js +33 -0
- package/lib/test/unit/vision-assertion.spec.js +119 -0
- package/lib/test/unit/wda-client-shell.spec.js +133 -0
- package/lib/test/unit/web-config-service.spec.js +98 -0
- package/lib/test/unit/webhook-delivery.spec.js +24 -0
- package/lib/test/unit/webhook-payloads.spec.js +273 -0
- package/lib/test/unit/xenon-execute-scripts.spec.js +138 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/web/src/components/webhook-settings/webhookEventVariables.json +30 -0
- package/package.json +5 -5
- package/prisma/migrations/20261004140000_keep_device_settings/migration.sql +19 -0
- package/prisma/migrations/20261004174413_locator_etalon_path/migration.sql +2 -0
- package/prisma/schema.prisma +38 -7
- package/schema.json +23 -25
- package/scripts/generate-types-from-schema.js +1 -2
- package/scripts/lib/always-present-plugin-args.js +4 -1
- package/lib/public/assets/BugReportButton-BoGhlI7F.js +0 -15
- package/lib/public/assets/DeviceMosaicView-8J0oYqMM.js +0 -2
- package/lib/public/assets/ai-settings-Bce5SJob.js +0 -21
- package/lib/public/assets/device-explorer-C-KnhMHI.js +0 -279
- package/lib/public/assets/forgot-password-DnudqFFo.js +0 -1
- package/lib/public/assets/maintenance-settings-zDVlOMVK.js +0 -6
- package/lib/public/assets/recording-group-store-WVM3hoXn.js +0 -26
- package/lib/public/assets/runbook-page-DJTVCJX7.js +0 -124
- package/lib/public/assets/session-detail-page-CGn55Pvl.js +0 -4
- package/lib/public/assets/settings-MsVU2ukE.js +0 -6
- package/lib/public/assets/webhook-settings-DiS8geIm.js +0 -1
- /package/lib/public/assets/{BugReportButton-CPBjfiv4.css → index-CPBjfiv4.css} +0 -0
|
@@ -45,56 +45,123 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
45
45
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.dashboardCommands = exports.DashboardCommands = void 0;
|
|
48
|
+
exports.dashboardCommands = exports.DashboardCommands = exports.SESSION_DETAILS_COMMANDS = void 0;
|
|
49
|
+
exports.sessionDetailsCommandOf = sessionDetailsCommandOf;
|
|
49
50
|
const session_service_1 = require("./services/session-service");
|
|
50
51
|
const prisma_1 = require("../prisma");
|
|
51
52
|
const logger_1 = __importDefault(require("../logger"));
|
|
52
|
-
const lodash_1 = __importDefault(require("lodash"));
|
|
53
53
|
const SessionManager_1 = require("../sessions/SessionManager");
|
|
54
54
|
const asset_manager_1 = require("./asset-manager");
|
|
55
|
+
const xenonScripts_1 = require("../interceptors/xenonScripts");
|
|
56
|
+
/**
|
|
57
|
+
* The execute commands that write to a session's record (its Session row):
|
|
58
|
+
* `driver.execute('xenon: setSessionName', 'Checkout')` and the like.
|
|
59
|
+
*
|
|
60
|
+
* Each answers `{ recorded: true }` when it wrote, or `{ recorded: false,
|
|
61
|
+
* message }` saying why nothing was written: no record of the session on this
|
|
62
|
+
* server (it runs without `enableDashboard`, or it is a node, which keeps
|
|
63
|
+
* none for the hub's sessions), an argument it can't use, or a failed write.
|
|
64
|
+
* None of them fails the test's command. They are bookkeeping, and a test
|
|
65
|
+
* shouldn't die because the server it ran on records no sessions. Through 2.13.2
|
|
66
|
+
* setSessionName, setSessionStatus and debug failed the command there
|
|
67
|
+
* (Prisma's P2025, a foreign-key error), and addTag and captureEvidence
|
|
68
|
+
* answered `null` as if they had worked.
|
|
69
|
+
*/
|
|
70
|
+
exports.SESSION_DETAILS_COMMANDS = [
|
|
71
|
+
'setSessionName',
|
|
72
|
+
'setSessionStatus',
|
|
73
|
+
'debug',
|
|
74
|
+
'addTag',
|
|
75
|
+
'captureEvidence',
|
|
76
|
+
];
|
|
77
|
+
const RECORDED = { recorded: true };
|
|
78
|
+
const notRecorded = (message) => ({ recorded: false, message });
|
|
79
|
+
/** The session-details command a script names (`xenon: addTag`), or null for any other script. */
|
|
80
|
+
function sessionDetailsCommandOf(script) {
|
|
81
|
+
const name = (0, xenonScripts_1.xenonScriptName)(script);
|
|
82
|
+
return name !== null && exports.SESSION_DETAILS_COMMANDS.includes(name)
|
|
83
|
+
? name
|
|
84
|
+
: null;
|
|
85
|
+
}
|
|
86
|
+
/** The script's arguments as a list, as both the W3C body and Appium's executeScript give them. */
|
|
87
|
+
function argumentList(args) {
|
|
88
|
+
if (Array.isArray(args))
|
|
89
|
+
return args;
|
|
90
|
+
return args === undefined || args === null ? [] : [args];
|
|
91
|
+
}
|
|
92
|
+
function isObject(value) {
|
|
93
|
+
return typeof value === 'object' && value !== null;
|
|
94
|
+
}
|
|
95
|
+
/** A string argument, or the named field of an object argument. */
|
|
96
|
+
function stringArg(value, field) {
|
|
97
|
+
if (typeof value === 'string')
|
|
98
|
+
return value;
|
|
99
|
+
if (isObject(value) && typeof value[field] === 'string')
|
|
100
|
+
return value[field];
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
55
103
|
class DashboardCommands {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Answers a session-details command on an Express-style response, as
|
|
106
|
+
* `{ value: <answer> }`, and returns the answer. The hub's gateway passes
|
|
107
|
+
* the client's response; CommandInterceptor passes one that keeps it.
|
|
108
|
+
*/
|
|
59
109
|
process(sessionId, request, response) {
|
|
60
110
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
111
|
+
var _a;
|
|
112
|
+
const { script, args } = (_a = request.body) !== null && _a !== void 0 ? _a : {};
|
|
113
|
+
const command = sessionDetailsCommandOf(script);
|
|
114
|
+
const answer = command
|
|
115
|
+
? yield this.run(sessionId, command, args)
|
|
116
|
+
: notRecorded(`"${script}" is not a command that records session details.`);
|
|
117
|
+
response.status(200).json({ value: answer });
|
|
118
|
+
return answer;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/** Runs one command. Never throws: a failure is `{ recorded: false, message }`. */
|
|
122
|
+
run(sessionId, command, args) {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
var _a;
|
|
125
|
+
logger_1.default.info(`[DashboardCommands] ${command} for session ${sessionId}`);
|
|
126
|
+
const list = argumentList(args);
|
|
127
|
+
let answer;
|
|
128
|
+
try {
|
|
129
|
+
const row = yield prisma_1.prisma.session.findUnique({
|
|
130
|
+
where: { id: sessionId },
|
|
131
|
+
select: { id: true, tags: true },
|
|
132
|
+
});
|
|
133
|
+
if (!row) {
|
|
134
|
+
answer = notRecorded(`This server keeps no record of session ${sessionId}, so nothing was saved. ` +
|
|
135
|
+
'Sessions are recorded by a server started with enableDashboard, never by a node.');
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
switch (command) {
|
|
139
|
+
case 'setSessionName':
|
|
140
|
+
answer = yield this.setSessionName(sessionId, list);
|
|
141
|
+
break;
|
|
142
|
+
case 'setSessionStatus':
|
|
143
|
+
answer = yield this.setSessionStatus(sessionId, list);
|
|
144
|
+
break;
|
|
145
|
+
case 'debug':
|
|
146
|
+
answer = yield this.debug(sessionId, list);
|
|
147
|
+
break;
|
|
148
|
+
case 'captureEvidence':
|
|
149
|
+
answer = yield this.captureEvidence(sessionId, list);
|
|
150
|
+
break;
|
|
151
|
+
case 'addTag':
|
|
152
|
+
answer = yield this.addTag(sessionId, list, row.tags);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
90
155
|
}
|
|
91
156
|
}
|
|
92
|
-
|
|
157
|
+
catch (err) {
|
|
158
|
+
answer = notRecorded(`Xenon could not save it: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
|
|
159
|
+
}
|
|
160
|
+
if (!answer.recorded)
|
|
161
|
+
logger_1.default.warn(`[DashboardCommands] ${command}: ${answer.message}`);
|
|
162
|
+
return answer;
|
|
93
163
|
});
|
|
94
164
|
}
|
|
95
|
-
sendSuccessResponse(response) {
|
|
96
|
-
return response.status(200).json({ value: null });
|
|
97
|
-
}
|
|
98
165
|
/* Commands */
|
|
99
166
|
/**
|
|
100
167
|
* Set the name of current test(session)
|
|
@@ -103,63 +170,50 @@ class DashboardCommands {
|
|
|
103
170
|
* or
|
|
104
171
|
* driver.executeScript("xenon: setSessionName", {"name": "MyTestName"})
|
|
105
172
|
*/
|
|
106
|
-
setSessionName(sessionId,
|
|
173
|
+
setSessionName(sessionId, args) {
|
|
107
174
|
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
name
|
|
111
|
-
}
|
|
112
|
-
|
|
175
|
+
const name = stringArg(args[0], 'name');
|
|
176
|
+
if (!name || !name.trim()) {
|
|
177
|
+
return notRecorded('setSessionName needs a name, as a string or { name }.');
|
|
178
|
+
}
|
|
179
|
+
yield (0, session_service_1.updateSessionDetails)(sessionId, { name });
|
|
180
|
+
return RECORDED;
|
|
113
181
|
});
|
|
114
182
|
}
|
|
115
183
|
/**
|
|
116
184
|
* Update the status of the session
|
|
117
185
|
*
|
|
118
186
|
* driver.executeScript("xenon: setSessionStatus", {"status": "passed/failed", "reason": "optional reason"})
|
|
187
|
+
* or, positionally, ("xe:setSessionStatus", "failed", "reason")
|
|
119
188
|
*/
|
|
120
|
-
setSessionStatus(sessionId,
|
|
189
|
+
setSessionStatus(sessionId, args) {
|
|
121
190
|
return __awaiter(this, void 0, void 0, function* () {
|
|
122
|
-
const { args
|
|
123
|
-
|
|
124
|
-
|
|
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();
|
|
191
|
+
const statusArg = isObject(args[0]) ? args[0] : { status: args[0], reason: args[1] };
|
|
192
|
+
const given = statusArg.status;
|
|
193
|
+
const inputStatus = typeof given === 'string' ? given.toLowerCase() : '';
|
|
141
194
|
const validStatuses = ['success', 'failed', 'passed'];
|
|
142
195
|
if (!validStatuses.includes(inputStatus)) {
|
|
143
|
-
|
|
144
|
-
|
|
196
|
+
return notRecorded('setSessionStatus takes "passed" or "failed" ("success" also means passed); ' +
|
|
197
|
+
`it was given ${JSON.stringify(given !== null && given !== void 0 ? given : null)}.`);
|
|
145
198
|
}
|
|
146
199
|
// Normalize 'passed' to 'success' for consistency with SessionStatus enum
|
|
147
200
|
const normalizedStatus = inputStatus === 'passed' ? 'success' : inputStatus;
|
|
201
|
+
const reason = typeof statusArg.reason === 'string' ? statusArg.reason : undefined;
|
|
148
202
|
const updated = yield (0, session_service_1.updateSessionDetails)(sessionId, {
|
|
149
203
|
status: normalizedStatus,
|
|
150
|
-
failure_reason:
|
|
204
|
+
failure_reason: reason || undefined,
|
|
151
205
|
});
|
|
152
206
|
// --- REAL-TIME UI UPDATE ---
|
|
153
|
-
//
|
|
207
|
+
// Emit a socket event so the dashboard row updates immediately.
|
|
154
208
|
const { SocketServer } = yield Promise.resolve().then(() => __importStar(require('../services/SocketServer')));
|
|
155
209
|
const { Container } = yield Promise.resolve().then(() => __importStar(require('typedi')));
|
|
156
210
|
const { SocketEvents } = yield Promise.resolve().then(() => __importStar(require('../enums/SocketEvents')));
|
|
157
211
|
void Container.get(SocketServer).emitToDashboardForDevices(SocketEvents.SESSION_STOPPED, {
|
|
158
212
|
id: sessionId,
|
|
159
213
|
status: normalizedStatus,
|
|
160
|
-
failure_reason:
|
|
214
|
+
failure_reason: reason || undefined,
|
|
161
215
|
}, { udid: updated === null || updated === void 0 ? void 0 : updated.device_udid });
|
|
162
|
-
return
|
|
216
|
+
return RECORDED;
|
|
163
217
|
});
|
|
164
218
|
}
|
|
165
219
|
/**
|
|
@@ -169,12 +223,18 @@ class DashboardCommands {
|
|
|
169
223
|
* or
|
|
170
224
|
* driver.executeScript("xenon: debug", "Debug message")
|
|
171
225
|
*/
|
|
172
|
-
debug(sessionId,
|
|
226
|
+
debug(sessionId, args) {
|
|
173
227
|
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
228
|
+
const logData = args[0];
|
|
229
|
+
let message;
|
|
230
|
+
if (typeof logData === 'string')
|
|
231
|
+
message = logData;
|
|
232
|
+
else if (isObject(logData)) {
|
|
233
|
+
message = typeof logData.message === 'string' ? logData.message : JSON.stringify(logData);
|
|
234
|
+
}
|
|
235
|
+
if (!message) {
|
|
236
|
+
return notRecorded('debug needs a message, as a string or { message }.');
|
|
237
|
+
}
|
|
178
238
|
yield prisma_1.prisma.log.create({
|
|
179
239
|
data: {
|
|
180
240
|
session_id: sessionId,
|
|
@@ -182,7 +242,7 @@ class DashboardCommands {
|
|
|
182
242
|
message: message,
|
|
183
243
|
},
|
|
184
244
|
});
|
|
185
|
-
return
|
|
245
|
+
return RECORDED;
|
|
186
246
|
});
|
|
187
247
|
}
|
|
188
248
|
/**
|
|
@@ -192,44 +252,43 @@ class DashboardCommands {
|
|
|
192
252
|
* or
|
|
193
253
|
* driver.executeScript("xenon: captureEvidence", "Checkpoint reached")
|
|
194
254
|
*/
|
|
195
|
-
captureEvidence(sessionId,
|
|
255
|
+
captureEvidence(sessionId, args) {
|
|
196
256
|
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
-
|
|
198
|
-
const evidenceData =
|
|
199
|
-
const reason =
|
|
200
|
-
const label =
|
|
257
|
+
var _a;
|
|
258
|
+
const evidenceData = args[0];
|
|
259
|
+
const reason = stringArg(evidenceData, 'reason') || 'Manual capture';
|
|
260
|
+
const label = isObject(evidenceData) ? evidenceData.label : undefined;
|
|
261
|
+
const session = SessionManager_1.SESSION_MANAGER.getSession(sessionId);
|
|
262
|
+
if (!session) {
|
|
263
|
+
return notRecorded(`Session ${sessionId} isn't running here, so no screenshot was taken.`);
|
|
264
|
+
}
|
|
265
|
+
let screenshotBase64;
|
|
201
266
|
try {
|
|
202
|
-
|
|
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
|
-
}
|
|
267
|
+
screenshotBase64 = yield session.getScreenShot();
|
|
228
268
|
}
|
|
229
269
|
catch (err) {
|
|
230
|
-
|
|
270
|
+
return notRecorded(`No screenshot could be taken: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
|
|
231
271
|
}
|
|
232
|
-
|
|
272
|
+
if (!screenshotBase64)
|
|
273
|
+
return notRecorded('No screenshot could be taken.');
|
|
274
|
+
const screenshotPath = (0, asset_manager_1.saveScreenShot)(sessionId, screenshotBase64);
|
|
275
|
+
yield prisma_1.prisma.sessionLog.create({
|
|
276
|
+
data: {
|
|
277
|
+
session_id: sessionId,
|
|
278
|
+
command_name: 'captureEvidence',
|
|
279
|
+
body: JSON.stringify({ reason, label }),
|
|
280
|
+
response: JSON.stringify({ captured: true }),
|
|
281
|
+
is_success: true,
|
|
282
|
+
is_error: false,
|
|
283
|
+
method: 'POST',
|
|
284
|
+
title: 'Evidence Captured',
|
|
285
|
+
subtitle: reason,
|
|
286
|
+
screenshot: screenshotPath,
|
|
287
|
+
url: '/execute/sync',
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
logger_1.default.info(`[DashboardCommands] Evidence captured for ${sessionId}: ${reason}`);
|
|
291
|
+
return RECORDED;
|
|
233
292
|
});
|
|
234
293
|
}
|
|
235
294
|
/**
|
|
@@ -239,44 +298,29 @@ class DashboardCommands {
|
|
|
239
298
|
* or
|
|
240
299
|
* driver.executeScript("xenon: addTag", "smoke-test")
|
|
241
300
|
*/
|
|
242
|
-
addTag(sessionId,
|
|
301
|
+
addTag(sessionId, args, tags) {
|
|
243
302
|
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if (!newTag) {
|
|
248
|
-
logger_1.default.warn('[DashboardCommands] addTag: No tag provided');
|
|
249
|
-
return this.sendSuccessResponse(response);
|
|
303
|
+
const newTag = stringArg(args[0], 'tag');
|
|
304
|
+
if (!newTag || !newTag.trim()) {
|
|
305
|
+
return notRecorded('addTag needs a tag, as a string or { tag }.');
|
|
250
306
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
}
|
|
307
|
+
let existingTags = [];
|
|
308
|
+
if (tags) {
|
|
309
|
+
try {
|
|
310
|
+
const parsed = JSON.parse(tags);
|
|
311
|
+
if (Array.isArray(parsed))
|
|
312
|
+
existingTags = parsed;
|
|
266
313
|
}
|
|
267
|
-
|
|
268
|
-
|
|
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}`);
|
|
314
|
+
catch (_a) {
|
|
315
|
+
existingTags = [];
|
|
274
316
|
}
|
|
275
317
|
}
|
|
276
|
-
|
|
277
|
-
|
|
318
|
+
if (!existingTags.includes(newTag)) {
|
|
319
|
+
existingTags.push(newTag);
|
|
320
|
+
yield (0, session_service_1.updateSessionDetails)(sessionId, { tags: JSON.stringify(existingTags) });
|
|
321
|
+
logger_1.default.info(`[DashboardCommands] Tag added to ${sessionId}: ${newTag}`);
|
|
278
322
|
}
|
|
279
|
-
return
|
|
323
|
+
return RECORDED;
|
|
280
324
|
});
|
|
281
325
|
}
|
|
282
326
|
}
|