@web-auto/webauto 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/apps/desktop-console/default-settings.json +1 -0
  2. package/apps/desktop-console/dist/main/index.mjs +1618 -0
  3. package/apps/desktop-console/{src → dist}/main/preload.mjs +10 -0
  4. package/apps/desktop-console/dist/renderer/index.js +3063 -0
  5. package/apps/desktop-console/entry/ui-console.mjs +299 -0
  6. package/apps/webauto/entry/account.mjs +356 -0
  7. package/apps/webauto/entry/lib/account-detect.mjs +160 -0
  8. package/apps/webauto/entry/lib/account-store.mjs +587 -0
  9. package/apps/webauto/entry/lib/profilepool.mjs +1 -1
  10. package/apps/webauto/entry/xhs-install.mjs +27 -3
  11. package/apps/webauto/entry/xhs-status.mjs +152 -0
  12. package/apps/webauto/entry/xhs-unified.mjs +595 -17
  13. package/bin/webauto.mjs +263 -15
  14. package/dist/apps/webauto/server.js +66 -0
  15. package/dist/modules/camo-backend/src/index.js +575 -0
  16. package/dist/modules/camo-backend/src/internal/BrowserSession.js +817 -0
  17. package/dist/modules/camo-backend/src/internal/ElementRegistry.js +61 -0
  18. package/dist/modules/camo-backend/src/internal/ProfileLock.js +85 -0
  19. package/dist/modules/camo-backend/src/internal/SessionManager.js +172 -0
  20. package/dist/modules/camo-backend/src/internal/container-matcher.js +852 -0
  21. package/dist/modules/camo-backend/src/internal/engine-manager.js +258 -0
  22. package/dist/modules/camo-backend/src/internal/fingerprint.js +203 -0
  23. package/dist/modules/camo-backend/src/internal/pageRuntime.js +29 -0
  24. package/dist/modules/camo-backend/src/internal/runtimeInjector.js +30 -0
  25. package/dist/modules/camo-backend/src/internal/state-bus.js +46 -0
  26. package/dist/modules/camo-backend/src/internal/storage-paths.js +36 -0
  27. package/dist/modules/camo-backend/src/internal/ws-server.js +1202 -0
  28. package/dist/modules/camo-runtime/src/utils/browser-service.mjs +423 -0
  29. package/dist/modules/camo-runtime/src/utils/config.mjs +77 -0
  30. package/dist/modules/container-registry/src/index.js +184 -0
  31. package/dist/modules/logging/src/index.js +92 -0
  32. package/dist/modules/operations/src/builtin.js +27 -0
  33. package/dist/modules/operations/src/container-binding.js +75 -0
  34. package/dist/modules/operations/src/executor.js +146 -0
  35. package/dist/modules/operations/src/operations/click.js +167 -0
  36. package/dist/modules/operations/src/operations/extract.js +204 -0
  37. package/dist/modules/operations/src/operations/find-child.js +17 -0
  38. package/dist/modules/operations/src/operations/highlight.js +138 -0
  39. package/dist/modules/operations/src/operations/key.js +61 -0
  40. package/dist/modules/operations/src/operations/navigate.js +148 -0
  41. package/dist/modules/operations/src/operations/scroll.js +126 -0
  42. package/dist/modules/operations/src/operations/type.js +190 -0
  43. package/dist/modules/operations/src/queue.js +100 -0
  44. package/dist/modules/operations/src/registry.js +11 -0
  45. package/dist/modules/operations/src/system/mouse.js +33 -0
  46. package/dist/modules/state/src/atomic-json.js +33 -0
  47. package/dist/modules/workflow/blocks/AnchorVerificationBlock.js +71 -0
  48. package/dist/modules/workflow/blocks/BehaviorRandomizer.js +26 -0
  49. package/dist/modules/workflow/blocks/CallWorkflowBlock.js +38 -0
  50. package/dist/modules/workflow/blocks/CloseDetailBlock.js +209 -0
  51. package/dist/modules/workflow/blocks/CollectBatch.js +137 -0
  52. package/dist/modules/workflow/blocks/CollectCommentsBlock.js +415 -0
  53. package/dist/modules/workflow/blocks/CollectSearchListBlock.js +599 -0
  54. package/dist/modules/workflow/blocks/CollectWeiboPosts.js +229 -0
  55. package/dist/modules/workflow/blocks/DetectPageStateBlock.js +259 -0
  56. package/dist/modules/workflow/blocks/EnsureLoginBlock.js +162 -0
  57. package/dist/modules/workflow/blocks/EnsureSession.js +426 -0
  58. package/dist/modules/workflow/blocks/ErrorClassifier.js +164 -0
  59. package/dist/modules/workflow/blocks/ErrorRecoveryBlock.js +319 -0
  60. package/dist/modules/workflow/blocks/ExpandCommentsBlock.js +1032 -0
  61. package/dist/modules/workflow/blocks/ExtractDetailBlock.js +310 -0
  62. package/dist/modules/workflow/blocks/ExtractPostFields.js +88 -0
  63. package/dist/modules/workflow/blocks/GenerateSmartReplyBlock.js +68 -0
  64. package/dist/modules/workflow/blocks/GoToSearchBlock.js +497 -0
  65. package/dist/modules/workflow/blocks/GracefulFallbackBlock.js +104 -0
  66. package/dist/modules/workflow/blocks/HighlightBlock.js +66 -0
  67. package/dist/modules/workflow/blocks/InitAutoScroll.js +65 -0
  68. package/dist/modules/workflow/blocks/LoadContainerDefinition.js +50 -0
  69. package/dist/modules/workflow/blocks/LoadContainerIndex.js +43 -0
  70. package/dist/modules/workflow/blocks/LocateAndGuardBlock.js +176 -0
  71. package/dist/modules/workflow/blocks/LoginRecoveryBlock.js +242 -0
  72. package/dist/modules/workflow/blocks/MatchContainers.js +64 -0
  73. package/dist/modules/workflow/blocks/MonitoringBlock.js +190 -0
  74. package/dist/modules/workflow/blocks/OpenDetailBlock.js +1240 -0
  75. package/dist/modules/workflow/blocks/OrganizeXhsNotesBlock.js +117 -0
  76. package/dist/modules/workflow/blocks/PersistXhsNoteBlock.js +270 -0
  77. package/dist/modules/workflow/blocks/PickSinglePost.js +69 -0
  78. package/dist/modules/workflow/blocks/ProgressTracker.js +125 -0
  79. package/dist/modules/workflow/blocks/RecordFixtureBlock.js +44 -0
  80. package/dist/modules/workflow/blocks/RenderMarkdown.js +48 -0
  81. package/dist/modules/workflow/blocks/SaveFile.js +54 -0
  82. package/dist/modules/workflow/blocks/ScrollNextBatch.js +72 -0
  83. package/dist/modules/workflow/blocks/SessionHealthBlock.js +73 -0
  84. package/dist/modules/workflow/blocks/StartBrowserService.js +45 -0
  85. package/dist/modules/workflow/blocks/ValidateContainerDefinition.js +67 -0
  86. package/dist/modules/workflow/blocks/ValidateExtract.js +35 -0
  87. package/dist/modules/workflow/blocks/WaitSearchPermitBlock.js +162 -0
  88. package/dist/modules/workflow/blocks/WaitStable.js +74 -0
  89. package/dist/modules/workflow/blocks/WarmupCommentsBlock.js +120 -0
  90. package/dist/modules/workflow/blocks/WorkflowExecutor.js +156 -0
  91. package/dist/modules/workflow/blocks/XiaohongshuCollectFromLinksBlock.js +1004 -0
  92. package/dist/modules/workflow/blocks/XiaohongshuCollectLinksBlock.js +1049 -0
  93. package/dist/modules/workflow/blocks/XiaohongshuFullCollectBlock.js +782 -0
  94. package/dist/modules/workflow/blocks/helpers/anchorVerify.js +198 -0
  95. package/dist/modules/workflow/blocks/helpers/asyncWorkQueue.js +53 -0
  96. package/dist/modules/workflow/blocks/helpers/commentScroller.js +334 -0
  97. package/dist/modules/workflow/blocks/helpers/commentSectionLocator.js +126 -0
  98. package/dist/modules/workflow/blocks/helpers/containerAnchors.js +301 -0
  99. package/dist/modules/workflow/blocks/helpers/debugArtifacts.js +6 -0
  100. package/dist/modules/workflow/blocks/helpers/downloadPaths.js +29 -0
  101. package/dist/modules/workflow/blocks/helpers/expandCommentsController.js +53 -0
  102. package/dist/modules/workflow/blocks/helpers/expandCommentsExtractor.js +129 -0
  103. package/dist/modules/workflow/blocks/helpers/macosVisionOcrPlugin.js +116 -0
  104. package/dist/modules/workflow/blocks/helpers/mergeXhsMarkdown.js +109 -0
  105. package/dist/modules/workflow/blocks/helpers/openDetailController.js +56 -0
  106. package/dist/modules/workflow/blocks/helpers/openDetailTypes.js +7 -0
  107. package/dist/modules/workflow/blocks/helpers/openDetailViewport.js +474 -0
  108. package/dist/modules/workflow/blocks/helpers/openDetailWaiter.js +104 -0
  109. package/dist/modules/workflow/blocks/helpers/operationLogger.js +195 -0
  110. package/dist/modules/workflow/blocks/helpers/persistedNotes.js +107 -0
  111. package/dist/modules/workflow/blocks/helpers/replyExpander.js +260 -0
  112. package/dist/modules/workflow/blocks/helpers/scrollIntoView.js +138 -0
  113. package/dist/modules/workflow/blocks/helpers/searchExecutor.js +328 -0
  114. package/dist/modules/workflow/blocks/helpers/searchGate.js +46 -0
  115. package/dist/modules/workflow/blocks/helpers/searchPageState.js +164 -0
  116. package/dist/modules/workflow/blocks/helpers/searchResultWaiter.js +64 -0
  117. package/dist/modules/workflow/blocks/helpers/simpleAnchor.js +134 -0
  118. package/dist/modules/workflow/blocks/helpers/smartReply.js +40 -0
  119. package/dist/modules/workflow/blocks/helpers/systemInput.js +635 -0
  120. package/dist/modules/workflow/blocks/helpers/targetCountMode.js +9 -0
  121. package/dist/modules/workflow/blocks/helpers/xhsCliArgs.js +80 -0
  122. package/dist/modules/workflow/blocks/helpers/xhsCommentDom.js +805 -0
  123. package/dist/modules/workflow/blocks/helpers/xhsNoteOrganizer.js +140 -0
  124. package/dist/modules/workflow/blocks/restore/RestorePhaseBlock.js +204 -0
  125. package/dist/modules/workflow/config/workflowRegistry.js +32 -0
  126. package/dist/modules/workflow/definitions/batch-collect-workflow.js +63 -0
  127. package/dist/modules/workflow/definitions/scroll-extract-workflow.js +74 -0
  128. package/dist/modules/workflow/definitions/xiaohongshu-collect-workflow-v2.js +81 -0
  129. package/dist/modules/workflow/definitions/xiaohongshu-collect-workflow.js +57 -0
  130. package/dist/modules/workflow/definitions/xiaohongshu-full-collect-workflow-v3.js +68 -0
  131. package/dist/modules/workflow/definitions/xiaohongshu-note-collect.js +49 -0
  132. package/dist/modules/workflow/definitions/xiaohongshu-phase1-workflow-v3.js +30 -0
  133. package/dist/modules/workflow/definitions/xiaohongshu-phase2-links-workflow-v3.js +40 -0
  134. package/dist/modules/workflow/definitions/xiaohongshu-phase3-collect-workflow-v1.js +54 -0
  135. package/dist/modules/workflow/definitions/xiaohongshu-phase34-from-links-workflow-v3.js +25 -0
  136. package/dist/modules/workflow/src/WeiboEventDrivenWorkflowRunner.js +308 -0
  137. package/dist/modules/workflow/src/context.js +70 -0
  138. package/dist/modules/workflow/src/index.js +5 -0
  139. package/dist/modules/workflow/src/orchestrator.js +230 -0
  140. package/dist/modules/workflow/src/runner.js +55 -0
  141. package/dist/modules/workflow/src/runtime.js +70 -0
  142. package/dist/modules/workflow/workflows/WeiboFeedExtractionWorkflow.js +359 -0
  143. package/dist/modules/workflow/workflows/XiaohongshuLoginWorkflow.js +110 -0
  144. package/dist/modules/xiaohongshu/app/src/blocks/MatchCommentsBlock.js +139 -0
  145. package/dist/modules/xiaohongshu/app/src/blocks/Phase1EnsureServicesBlock.js +36 -0
  146. package/dist/modules/xiaohongshu/app/src/blocks/Phase1MonitorCookieBlock.js +213 -0
  147. package/dist/modules/xiaohongshu/app/src/blocks/Phase1StartProfileBlock.js +121 -0
  148. package/dist/modules/xiaohongshu/app/src/blocks/Phase2CollectLinksBlock.js +1249 -0
  149. package/dist/modules/xiaohongshu/app/src/blocks/Phase2SearchBlock.js +703 -0
  150. package/dist/modules/xiaohongshu/app/src/blocks/Phase34CloseDetailBlock.js +41 -0
  151. package/dist/modules/xiaohongshu/app/src/blocks/Phase34CloseTabsBlock.js +44 -0
  152. package/dist/modules/xiaohongshu/app/src/blocks/Phase34CollectCommentsBlock.js +150 -0
  153. package/dist/modules/xiaohongshu/app/src/blocks/Phase34ExtractDetailBlock.js +117 -0
  154. package/dist/modules/xiaohongshu/app/src/blocks/Phase34OpenDetailBlock.js +102 -0
  155. package/dist/modules/xiaohongshu/app/src/blocks/Phase34OpenTabsBlock.js +109 -0
  156. package/dist/modules/xiaohongshu/app/src/blocks/Phase34PersistDetailBlock.js +117 -0
  157. package/dist/modules/xiaohongshu/app/src/blocks/Phase34ProcessSingleNoteBlock.js +114 -0
  158. package/dist/modules/xiaohongshu/app/src/blocks/Phase34ValidateLinksBlock.js +90 -0
  159. package/dist/modules/xiaohongshu/app/src/blocks/Phase3InteractBlock.js +1009 -0
  160. package/dist/modules/xiaohongshu/app/src/blocks/Phase4MultiTabHarvestBlock.js +233 -0
  161. package/dist/modules/xiaohongshu/app/src/blocks/ReplyInteractBlock.js +291 -0
  162. package/dist/modules/xiaohongshu/app/src/blocks/XhsDiscoverFallbackBlock.js +240 -0
  163. package/dist/modules/xiaohongshu/app/src/blocks/helpers/commentMatchDsl.js +126 -0
  164. package/dist/modules/xiaohongshu/app/src/blocks/helpers/commentMatcher.js +99 -0
  165. package/dist/modules/xiaohongshu/app/src/blocks/helpers/evidence.js +27 -0
  166. package/dist/modules/xiaohongshu/app/src/blocks/helpers/sharding.js +42 -0
  167. package/dist/modules/xiaohongshu/app/src/blocks/helpers/xhsComments.js +270 -0
  168. package/dist/modules/xiaohongshu/app/src/index.js +9 -0
  169. package/dist/modules/xiaohongshu/app/src/utils/checkpoints.js +222 -0
  170. package/dist/modules/xiaohongshu/app/src/utils/controllerAction.js +43 -0
  171. package/dist/services/controller/src/controller.js +1476 -0
  172. package/dist/services/controller/src/index.js +2 -0
  173. package/dist/services/controller/src/payload-normalizer.js +129 -0
  174. package/dist/services/shared/heartbeat.js +120 -0
  175. package/dist/services/shared/lib/errorHandler.js +2 -0
  176. package/dist/services/shared/serviceProcessLogger.js +139 -0
  177. package/dist/services/unified-api/RemoteBrowserSession.js +176 -0
  178. package/dist/services/unified-api/RemoteSessionManager.js +148 -0
  179. package/dist/services/unified-api/container-operations-handler.js +115 -0
  180. package/dist/services/unified-api/server.js +652 -0
  181. package/dist/services/unified-api/state-registry.js +274 -0
  182. package/dist/services/unified-api/task-persistence.js +66 -0
  183. package/dist/services/unified-api/task-state.js +130 -0
  184. package/modules/camo-runtime/src/autoscript/action-providers/xhs/search.mjs +12 -5
  185. package/modules/xiaohongshu/app/pnpm-lock.yaml +24 -0
  186. package/package.json +38 -10
  187. package/.beads/README.md +0 -81
  188. package/.beads/config.yaml +0 -67
  189. package/.beads/interactions.jsonl +0 -0
  190. package/.beads/issues.jsonl +0 -180
  191. package/.beads/metadata.json +0 -4
  192. package/.claude/settings.local.json +0 -10
  193. package/.github/workflows/ci.yml +0 -55
  194. package/AGENTS.md +0 -253
  195. package/apps/desktop-console/README.md +0 -27
  196. package/apps/desktop-console/package-lock.json +0 -897
  197. package/apps/desktop-console/package.json +0 -20
  198. package/apps/desktop-console/scripts/build-and-install.mjs +0 -19
  199. package/apps/desktop-console/scripts/build.mjs +0 -45
  200. package/apps/desktop-console/scripts/test-preload.mjs +0 -13
  201. package/apps/desktop-console/src/main/config.mts +0 -26
  202. package/apps/desktop-console/src/main/core-daemon-manager.mts +0 -131
  203. package/apps/desktop-console/src/main/desktop-settings.mts +0 -267
  204. package/apps/desktop-console/src/main/heartbeat-watchdog.mts +0 -50
  205. package/apps/desktop-console/src/main/heartbeat-watchdog.test.mts +0 -68
  206. package/apps/desktop-console/src/main/index-streaming.test.mts +0 -20
  207. package/apps/desktop-console/src/main/index.mts +0 -980
  208. package/apps/desktop-console/src/main/profile-store.mts +0 -239
  209. package/apps/desktop-console/src/main/profile-store.test.mts +0 -54
  210. package/apps/desktop-console/src/main/state-bridge.mts +0 -114
  211. package/apps/desktop-console/src/main/task-state-types.ts +0 -32
  212. package/apps/desktop-console/src/renderer/hooks/use-task-state.mts +0 -120
  213. package/apps/desktop-console/src/renderer/index.mts +0 -133
  214. package/apps/desktop-console/src/renderer/index.test.mts +0 -34
  215. package/apps/desktop-console/src/renderer/path-helpers.mts +0 -46
  216. package/apps/desktop-console/src/renderer/path-helpers.test.mts +0 -14
  217. package/apps/desktop-console/src/renderer/tabs/debug.mts +0 -48
  218. package/apps/desktop-console/src/renderer/tabs/debug.test.mts +0 -22
  219. package/apps/desktop-console/src/renderer/tabs/logs.mts +0 -421
  220. package/apps/desktop-console/src/renderer/tabs/logs.test.mts +0 -27
  221. package/apps/desktop-console/src/renderer/tabs/preflight.mts +0 -486
  222. package/apps/desktop-console/src/renderer/tabs/preflight.test.mts +0 -33
  223. package/apps/desktop-console/src/renderer/tabs/profile-pool.mts +0 -213
  224. package/apps/desktop-console/src/renderer/tabs/results.mts +0 -171
  225. package/apps/desktop-console/src/renderer/tabs/run.test.mts +0 -63
  226. package/apps/desktop-console/src/renderer/tabs/runtime.mts +0 -151
  227. package/apps/desktop-console/src/renderer/tabs/settings.mts +0 -146
  228. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/account-flow.mts +0 -486
  229. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/guide-browser-check.mts +0 -56
  230. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/helpers.mts +0 -262
  231. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/layout-block.mts +0 -430
  232. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/live-stats.mts +0 -847
  233. package/apps/desktop-console/src/renderer/tabs/xiaohongshu/run-flow.mts +0 -443
  234. package/apps/desktop-console/src/renderer/tabs/xiaohongshu-state.mts +0 -425
  235. package/apps/desktop-console/src/renderer/tabs/xiaohongshu.mts +0 -497
  236. package/apps/desktop-console/src/renderer/tabs/xiaohongshu.test.mts +0 -291
  237. package/apps/desktop-console/src/renderer/ui-components.mts +0 -31
  238. package/docs/README_camoufox_chinese.md +0 -141
  239. package/docs/USAGE_V3.md +0 -163
  240. package/docs/arch/OCR_MACOS_PLUGIN.md +0 -39
  241. package/docs/arch/PORTS.md +0 -40
  242. package/docs/arch/REGRESSION_CHECKLIST.md +0 -121
  243. package/docs/arch/SEARCH_GATE.md +0 -224
  244. package/docs/arch/VIEWPORT_SAFETY.md +0 -182
  245. package/docs/arch/XIAOHONGSHU_OFFLINE_MOCK_DESIGN.md +0 -267
  246. package/docs/xiaohongshu-container-driven-summary.md +0 -221
  247. package/docs/xiaohongshu-full-collect-runbook.md +0 -134
  248. package/docs/xiaohongshu-next-steps.md +0 -228
  249. package/docs/xiaohongshu-quickstart.md +0 -73
  250. package/docs/xiaohongshu-workflow-summary.md +0 -227
  251. package/modules/container-registry/tests/container-registry.test.ts +0 -16
  252. package/modules/logging/tests/logging.test.ts +0 -38
  253. package/modules/operations/tests/operations.test.ts +0 -22
  254. package/modules/operations/tests/viewport-filter.test.ts +0 -161
  255. package/modules/operations/tests/visible-only.test.ts +0 -250
  256. package/modules/session-manager/tests/session-manager.test.ts +0 -23
  257. package/modules/state/src/atomic-json.test.ts +0 -30
  258. package/modules/state/src/paths.test.ts +0 -59
  259. package/modules/state/src/xiaohongshu-collect-state.test.ts +0 -259
  260. package/modules/workflow/blocks/AnchorVerificationBlock.d.ts.map +0 -1
  261. package/modules/workflow/blocks/AnchorVerificationBlock.js.map +0 -1
  262. package/modules/workflow/blocks/DetectPageStateBlock.d.ts.map +0 -1
  263. package/modules/workflow/blocks/DetectPageStateBlock.js.map +0 -1
  264. package/modules/workflow/blocks/ErrorRecoveryBlock.d.ts.map +0 -1
  265. package/modules/workflow/blocks/ErrorRecoveryBlock.js.map +0 -1
  266. package/modules/workflow/blocks/WaitSearchPermitBlock.d.ts.map +0 -1
  267. package/modules/workflow/blocks/WaitSearchPermitBlock.js.map +0 -1
  268. package/modules/workflow/blocks/helpers/containerAnchors.d.ts.map +0 -1
  269. package/modules/workflow/blocks/helpers/containerAnchors.js.map +0 -1
  270. package/modules/workflow/blocks/helpers/downloadPaths.test.ts +0 -62
  271. package/modules/workflow/blocks/helpers/mergeXhsMarkdown.test.ts +0 -121
  272. package/modules/workflow/blocks/helpers/operationLogger.d.ts.map +0 -1
  273. package/modules/workflow/blocks/helpers/operationLogger.js.map +0 -1
  274. package/modules/workflow/blocks/helpers/persistedNotes.test.ts +0 -268
  275. package/modules/workflow/blocks/helpers/searchPageState.d.ts.map +0 -1
  276. package/modules/workflow/blocks/helpers/searchPageState.js.map +0 -1
  277. package/modules/workflow/blocks/helpers/targetCountMode.test.ts +0 -29
  278. package/modules/workflow/blocks/helpers/xhsCliArgs.test.ts +0 -75
  279. package/modules/workflow/tests/smartReply.test.ts +0 -32
  280. package/modules/xiaohongshu/app/src/blocks/Phase3Interact.matcher.test.ts +0 -33
  281. package/modules/xiaohongshu/app/src/utils/__tests__/checkpoints.test.ts +0 -141
  282. package/modules/xiaohongshu/app/tests/commentMatchDsl.test.ts +0 -50
  283. package/modules/xiaohongshu/app/tests/commentMatcher.test.ts +0 -46
  284. package/modules/xiaohongshu/app/tests/sharding.test.ts +0 -31
  285. package/package-scripts.json +0 -8
  286. package/runtime/infra/utils/README.md +0 -13
  287. package/runtime/infra/utils/scripts/README.md +0 -0
  288. package/runtime/infra/utils/scripts/development/eval-in-session.mjs +0 -40
  289. package/runtime/infra/utils/scripts/development/highlight-search-containers.mjs +0 -35
  290. package/runtime/infra/utils/scripts/service/kill-port.mjs +0 -24
  291. package/runtime/infra/utils/scripts/service/start-api.mjs +0 -39
  292. package/runtime/infra/utils/scripts/service/start-browser-service.mjs +0 -106
  293. package/runtime/infra/utils/scripts/service/stop-api.mjs +0 -18
  294. package/runtime/infra/utils/scripts/service/stop-browser-service.mjs +0 -104
  295. package/runtime/infra/utils/scripts/test-services.mjs +0 -94
  296. package/services/shared/heartbeat.test.ts +0 -102
  297. package/services/unified-api/__tests__/task-state.test.ts +0 -95
  298. package/sitecustomize.py +0 -19
  299. package/tests/README.md +0 -194
  300. package/tests/e2e/workflows/weibo-feed-extraction.test.ts +0 -171
  301. package/tests/fixtures/data/container-definitions.json +0 -67
  302. package/tests/fixtures/pages/simple-page.html +0 -69
  303. package/tests/integration/01-test-container-match.mjs +0 -188
  304. package/tests/integration/02-test-dom-branch.mjs +0 -161
  305. package/tests/integration/03-test-container-operation-system.mjs +0 -91
  306. package/tests/integration/05-test-container-lifecycle-events.mjs +0 -224
  307. package/tests/integration/05-test-container-lifecycle-with-events.mjs +0 -250
  308. package/tests/integration/06-test-container-dom-tree-drawing.mjs +0 -256
  309. package/tests/integration/07-test-weibo-container-lifecycle.mjs +0 -355
  310. package/tests/integration/08-test-weibo-feed-workflow.test.mjs +0 -164
  311. package/tests/integration/10-test-visual-analyzer.mjs +0 -312
  312. package/tests/integration/11-test-visual-loop.mjs +0 -284
  313. package/tests/integration/12-test-simple-visual-loop.mjs +0 -242
  314. package/tests/integration/13-test-visual-robust.mjs +0 -185
  315. package/tests/integration/14-test-visual-highlight-loop.mjs +0 -271
  316. package/tests/integration/inspect-page.mjs +0 -50
  317. package/tests/integration/run-all-tests.mjs +0 -95
  318. package/tests/patch_verification/CODEX_PATCH_TEST.md +0 -103
  319. package/tests/patch_verification/PHASE2_ANALYSIS.md +0 -179
  320. package/tests/patch_verification/PHASE2_OPTIMIZATION_REPORT.md +0 -55
  321. package/tests/patch_verification/PHASE2_TO_PHASE4_SUMMARY.md +0 -126
  322. package/tests/patch_verification/QUICK_TEST_SEQUENCE.md +0 -262
  323. package/tests/patch_verification/README.md +0 -143
  324. package/tests/patch_verification/RUN_TESTS.md +0 -60
  325. package/tests/patch_verification/TEST_EXECUTION.md +0 -99
  326. package/tests/patch_verification/TEST_PLAN.md +0 -328
  327. package/tests/patch_verification/TEST_RESULTS.md +0 -34
  328. package/tests/patch_verification/TOOL_TEST_PLAN.md +0 -48
  329. package/tests/patch_verification/run-tool-test.mjs +0 -121
  330. package/tests/patch_verification/temp_test_files/test01.txt +0 -1
  331. package/tests/patch_verification/temp_test_files/test02.txt +0 -3
  332. package/tests/patch_verification/temp_test_files/test02_gnu.txt +0 -3
  333. package/tests/patch_verification/temp_test_files/test03.txt +0 -1
  334. package/tests/patch_verification/temp_test_files/test03_multiline.txt +0 -5
  335. package/tests/patch_verification/temp_test_files/test04_function.ts +0 -5
  336. package/tests/patch_verification/temp_test_files/test05_import.ts +0 -4
  337. package/tests/patch_verification/temp_test_files/test06_special_chars.txt +0 -4
  338. package/tests/patch_verification/temp_test_files/test07_indentation.ts +0 -5
  339. package/tests/patch_verification/temp_test_files/test08_mismatch.txt +0 -1
  340. package/tests/patch_verification/temp_test_files/test_add_02.txt +0 -3
  341. package/tests/patch_verification/temp_test_files/test_simple.txt +0 -1
  342. package/tests/runner/TestReporter.mjs +0 -57
  343. package/tests/runner/TestRunner.mjs +0 -244
  344. package/tests/unit/commands/profile.test.mjs +0 -10
  345. package/tests/unit/container/change-notifier.test.mjs +0 -181
  346. package/tests/unit/lifecycle/session-registry.test.mjs +0 -135
  347. package/tests/unit/operations/registry.test.ts +0 -73
  348. package/tests/unit/utils/browser-service.test.mjs +0 -153
  349. package/tests/unit/utils/config.test.mjs +0 -166
  350. package/tests/unit/utils/fingerprint.test.mjs +0 -166
  351. package/tsconfig.json +0 -31
  352. package/tsconfig.services.json +0 -26
  353. /package/apps/desktop-console/{src → dist}/renderer/index.html +0 -0
  354. /package/apps/desktop-console/{src/renderer/tabs → dist/renderer}/run.mts +0 -0
@@ -1,244 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Test Runner - 主测试运行器
4
- * 支持单元测试、集成测试、E2E 测试
5
- */
6
-
7
- import fs from 'node:fs/promises';
8
- import path from 'node:path';
9
- import { fileURLToPath } from 'node:url';
10
- import { spawn } from 'node:child_process';
11
-
12
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
- const PROJECT_ROOT = path.resolve(__dirname, '../..');
14
-
15
- class TestRunner {
16
- constructor(config) {
17
- this.config = config;
18
- this.results = [];
19
- this.startTime = Date.now();
20
- }
21
-
22
- async loadConfig() {
23
- const configPath = path.join(__dirname, 'config.json');
24
- const content = await fs.readFile(configPath, 'utf8');
25
- return JSON.parse(content);
26
- }
27
-
28
- async findTestFiles(suitePath) {
29
- const files = [];
30
-
31
- async function scan(dir) {
32
- const entries = await fs.readdir(dir, { withFileTypes: true });
33
-
34
- for (const entry of entries) {
35
- const fullPath = path.join(dir, entry.name);
36
-
37
- if (entry.isDirectory()) {
38
- await scan(fullPath);
39
- } else if (entry.isFile() && (entry.name.endsWith('.test.ts') || entry.name.endsWith('.test.mjs'))) {
40
- files.push(fullPath);
41
- }
42
- }
43
- }
44
-
45
- await scan(suitePath);
46
- return files;
47
- }
48
-
49
- async runTest(testFile) {
50
- const start = Date.now();
51
- const testName = path.relative(PROJECT_ROOT, testFile);
52
-
53
- console.log(` Running: ${testName}`);
54
-
55
- return new Promise((resolve) => {
56
- const isTs = testFile.endsWith('.ts');
57
- const cmd = isTs ? 'npx' : 'node';
58
- const args = isTs ? ['tsx', testFile] : [testFile];
59
-
60
- const proc = spawn(cmd, args, {
61
- cwd: PROJECT_ROOT,
62
- stdio: 'pipe',
63
- env: { ...process.env, NODE_ENV: 'test' }
64
- });
65
-
66
- let stdout = '';
67
- let stderr = '';
68
-
69
- proc.stdout.on('data', (data) => {
70
- stdout += data.toString();
71
- });
72
-
73
- proc.stderr.on('data', (data) => {
74
- stderr += data.toString();
75
- });
76
-
77
- proc.on('close', (code) => {
78
- const duration = Date.now() - start;
79
-
80
- if (code === 0) {
81
- console.log(` ✅ Passed (${duration}ms)`);
82
- resolve({
83
- name: testName,
84
- status: 'passed',
85
- duration,
86
- stdout,
87
- stderr
88
- });
89
- } else {
90
- console.log(` ❌ Failed (${duration}ms)`);
91
- console.log(` ${stderr.split('\n')[0]}`);
92
- resolve({
93
- name: testName,
94
- status: 'failed',
95
- duration,
96
- stdout,
97
- stderr,
98
- error: stderr
99
- });
100
- }
101
- });
102
-
103
- proc.on('error', (err) => {
104
- const duration = Date.now() - start;
105
- console.log(` ❌ Error (${duration}ms)`);
106
- console.log(` ${err.message}`);
107
- resolve({
108
- name: testName,
109
- status: 'failed',
110
- duration,
111
- error: err.message
112
- });
113
- });
114
- });
115
- }
116
-
117
- async runSuite(suite) {
118
- console.log(`\n📦 Running ${suite.name} tests...`);
119
-
120
- const suitePath = path.join(PROJECT_ROOT, suite.path);
121
-
122
- // Check if suite directory exists
123
- try {
124
- await fs.access(suitePath);
125
- } catch (err) {
126
- console.log(` ⚠️ Suite directory not found: ${suitePath}`);
127
- return [];
128
- }
129
-
130
- const testFiles = await this.findTestFiles(suitePath);
131
-
132
- if (testFiles.length === 0) {
133
- console.log(` ℹ️ No test files found`);
134
- return [];
135
- }
136
-
137
- console.log(` Found ${testFiles.length} test file(s)`);
138
-
139
- const results = [];
140
-
141
- if (suite.parallel) {
142
- // Run tests in parallel
143
- const promises = testFiles.map(file => this.runTest(file));
144
- const suiteResults = await Promise.all(promises);
145
- results.push(...suiteResults);
146
- } else {
147
- // Run tests sequentially
148
- for (const file of testFiles) {
149
- const result = await this.runTest(file);
150
- results.push(result);
151
-
152
- // Stop on first failure if configured
153
- if (suite.stopOnFailure && result.status === 'failed') {
154
- console.log(` ⚠️ Stopping suite on first failure`);
155
- break;
156
- }
157
- }
158
- }
159
-
160
- return results;
161
- }
162
-
163
- async run(suiteNames = []) {
164
- console.log('🧪 WebAuto Test Runner\n');
165
-
166
- const config = await this.loadConfig();
167
-
168
- // Determine which suites to run
169
- let suitesToRun = config.suites;
170
- if (suiteNames.length > 0) {
171
- suitesToRun = config.suites.filter(s => suiteNames.includes(s.name));
172
- }
173
-
174
- for (const suite of suitesToRun) {
175
- const results = await this.runSuite(suite);
176
- this.results.push(...results);
177
- }
178
-
179
- this.printSummary();
180
-
181
- return this.results;
182
- }
183
-
184
- printSummary() {
185
- const duration = Date.now() - this.startTime;
186
- const passed = this.results.filter(r => r.status === 'passed').length;
187
- const failed = this.results.filter(r => r.status === 'failed').length;
188
- const total = this.results.length;
189
-
190
- console.log('\n' + '═'.repeat(60));
191
- console.log('📊 Test Summary');
192
- console.log('═'.repeat(60));
193
- console.log(`Total: ${total}`);
194
- console.log(`Passed: ${passed} ✅`);
195
- console.log(`Failed: ${failed} ❌`);
196
- console.log(`Duration: ${(duration / 1000).toFixed(2)}s`);
197
- console.log(`Success: ${total > 0 ? ((passed / total * 100).toFixed(2)) : 0}%`);
198
- console.log('═'.repeat(60));
199
-
200
- if (failed > 0) {
201
- console.log('\n❌ Failed Tests:');
202
- this.results
203
- .filter(r => r.status === 'failed')
204
- .forEach(r => {
205
- console.log(` • ${r.name}`);
206
- if (r.error) {
207
- const firstLine = r.error.split('\n')[0];
208
- console.log(` ${firstLine}`);
209
- }
210
- });
211
- }
212
- }
213
- }
214
-
215
- // CLI
216
- if (import.meta.url === `file://${process.argv[1]}`) {
217
- const args = process.argv.slice(2);
218
- const suiteArg = args.find(a => a.startsWith('--suite='));
219
- const allFlag = args.includes('--all');
220
-
221
- const runner = new TestRunner();
222
-
223
- let suites = [];
224
- if (allFlag) {
225
- // Run all suites
226
- suites = [];
227
- } else if (suiteArg) {
228
- // Run specific suite
229
- suites = [suiteArg.split('=')[1]];
230
- } else {
231
- // Default: run unit tests only
232
- suites = ['unit'];
233
- }
234
-
235
- runner.run(suites).then((results) => {
236
- const failed = results.filter(r => r.status === 'failed').length;
237
- process.exit(failed > 0 ? 1 : 0);
238
- }).catch((err) => {
239
- console.error('❌ Test runner failed:', err);
240
- process.exit(1);
241
- });
242
- }
243
-
244
- export default TestRunner;
@@ -1,10 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert';
3
-
4
- // Simple unit tests for profile command handler
5
- describe('profile command', () => {
6
- it('should export handleProfileCommand', async () => {
7
- const { handleProfileCommand } = await import('../../../src/commands/profile.mjs');
8
- assert.strictEqual(typeof handleProfileCommand, 'function');
9
- });
10
- });
@@ -1,181 +0,0 @@
1
- @@ -0,0 +1,184 @@
2
- import { describe, it, beforeEach, afterEach } from 'node:test';
3
- import assert from 'node:assert';
4
- import { ChangeNotifier, getChangeNotifier, destroyChangeNotifier } from '../../../src/container/change-notifier.mjs';
5
-
6
- describe('ChangeNotifier', () => {
7
- let notifier;
8
-
9
- beforeEach(() => {
10
- notifier = new ChangeNotifier();
11
- });
12
-
13
- afterEach(() => {
14
- notifier.destroy();
15
- });
16
-
17
- describe('subscribe', () => {
18
- it('should subscribe to a topic', () => {
19
- let called = false;
20
- notifier.subscribe('test-topic', () => { called = true; });
21
- notifier.notify('test-topic', { data: 'test' });
22
- assert.strictEqual(called, true);
23
- });
24
-
25
- it('should return unsubscribe function', () => {
26
- let callCount = 0;
27
- const unsub = notifier.subscribe('test-topic', () => { callCount++; });
28
- notifier.notify('test-topic', {});
29
- assert.strictEqual(callCount, 1);
30
- unsub();
31
- notifier.notify('test-topic', {});
32
- assert.strictEqual(callCount, 1);
33
- });
34
-
35
- it('should support multiple subscribers', () => {
36
- const results = [];
37
- notifier.subscribe('topic', () => results.push(1));
38
- notifier.subscribe('topic', () => results.push(2));
39
- notifier.notify('topic', {});
40
- assert.deepStrictEqual(results.sort(), [1, 2]);
41
- });
42
-
43
- it('should not throw on non-existent topic', () => {
44
- assert.doesNotThrow(() => notifier.notify('no-topic', {}));
45
- });
46
- });
47
-
48
- describe('watch', () => {
49
- it('should register element watcher', () => {
50
- let appeared = false;
51
- notifier.watch('.my-selector', { onAppear: () => { appeared = true; } });
52
- assert.strictEqual(notifier.elementWatchers.has('.my-selector'), true);
53
- });
54
-
55
- it('should return unsubscribe function', () => {
56
- const unsub = notifier.watch('.selector', {});
57
- unsub();
58
- assert.strictEqual(notifier.elementWatchers.has('.selector'), false);
59
- });
60
- });
61
-
62
- describe('processSnapshot', () => {
63
- it('should notify dom:changed topic', () => {
64
- let received = null;
65
- notifier.subscribe('dom:changed', (data) => { received = data; });
66
- const snapshot = { root: {} };
67
- notifier.processSnapshot(snapshot);
68
- assert.strictEqual(received.snapshot, snapshot);
69
- });
70
-
71
- it('should trigger onAppear for new elements', () => {
72
- const appeared = [];
73
- notifier.watch('.item', { onAppear: (els) => appeared.push(...els), throttle: 0 });
74
-
75
- const snapshot = {
76
- selector: '.item',
77
- children: [
78
- { selector: '.item', path: 'root/0' },
79
- ]
80
- };
81
- notifier.processSnapshot(snapshot);
82
-
83
- // Process again to detect change from null state
84
- const snapshot2 = {
85
- selector: '.item',
86
- children: [
87
- { selector: '.item', path: 'root/0' },
88
- { selector: '.item', path: 'root/1' },
89
- ]
90
- };
91
- notifier.processSnapshot(snapshot2);
92
-
93
- assert.ok(appeared.length >= 1);
94
- });
95
-
96
- it('should trigger onDisappear for removed elements', () => {
97
- const disappeared = [];
98
- notifier.watch('.item', {
99
- onDisappear: (els) => disappeared.push(...els),
100
- throttle: 0
101
- });
102
-
103
- const snapshot1 = {
104
- children: [
105
- { selector: '.item', path: 'root/0' },
106
- { selector: '.item', path: 'root/1' },
107
- ]
108
- };
109
- notifier.processSnapshot(snapshot1);
110
-
111
- const snapshot2 = {
112
- children: [
113
- { selector: '.item', path: 'root/0' },
114
- ]
115
- };
116
- notifier.processSnapshot(snapshot2);
117
-
118
- assert.ok(disappeared.length >= 1);
119
- });
120
- });
121
-
122
- describe('findElements', () => {
123
- it('should find matching elements recursively', () => {
124
- const tree = {
125
- selector: '.root',
126
- children: [
127
- { selector: '.item' },
128
- { selector: '.other' },
129
- {
130
- selector: '.container',
131
- children: [
132
- { selector: '.item' },
133
- ]
134
- },
135
- ]
136
- };
137
-
138
- const results = notifier.findElements(tree, { css: '.item' });
139
- assert.strictEqual(results.length, 2);
140
- });
141
- });
142
-
143
- describe('nodeMatchesSelector', () => {
144
- it('should match by css selector', () => {
145
- const node = { selector: '.test-class' };
146
- assert.strictEqual(notifier.nodeMatchesSelector(node, { css: '.test-class' }), true);
147
- });
148
-
149
- it('should match by id', () => {
150
- const node = { id: 'my-id' };
151
- assert.strictEqual(notifier.nodeMatchesSelector(node, { id: 'my-id' }), true);
152
- });
153
-
154
- it('should match by classes', () => {
155
- const node = { classes: ['a', 'b'] };
156
- assert.strictEqual(notifier.nodeMatchesSelector(node, { classes: ['a', 'b'] }), true);
157
- });
158
-
159
- it('should return false for no match', () => {
160
- const node = { classes: ['x'] };
161
- assert.strictEqual(notifier.nodeMatchesSelector(node, { classes: ['y'] }), false);
162
- });
163
- });
164
-
165
- describe('global instance', () => {
166
- it('should return singleton', () => {
167
- const n1 = getChangeNotifier();
168
- const n2 = getChangeNotifier();
169
- assert.strictEqual(n1, n2);
170
- destroyChangeNotifier();
171
- });
172
-
173
- it('should destroy global instance', () => {
174
- const n = getChangeNotifier();
175
- destroyChangeNotifier();
176
- const n2 = getChangeNotifier();
177
- assert.notStrictEqual(n, n2);
178
- destroyChangeNotifier();
179
- });
180
- });
181
- });
@@ -1,135 +0,0 @@
1
- import { describe, it } from 'node:test';
2
- import assert from 'node:assert';
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import os from 'node:os';
6
- import {
7
- registerSession,
8
- updateSession,
9
- getSessionInfo,
10
- unregisterSession,
11
- listRegisteredSessions,
12
- markSessionReconnecting,
13
- markSessionActive,
14
- markSessionClosed,
15
- cleanupStaleSessions,
16
- recoverSession,
17
- getSessionFile,
18
- } from '../../../src/lifecycle/session-registry.mjs';
19
-
20
- const TEST_PREFIX = 'test-sreg-' + Date.now();
21
-
22
- describe('session registry', () => {
23
- it('should register and read a session', () => {
24
- const id = TEST_PREFIX + '-1';
25
- const data = registerSession(id, { sessionId: 'abc' });
26
- assert.strictEqual(data.profileId, id);
27
- assert.strictEqual(data.sessionId, 'abc');
28
- const read = getSessionInfo(id);
29
- assert.strictEqual(read.profileId, id);
30
- unregisterSession(id);
31
- });
32
-
33
- it('should update existing session', () => {
34
- const id = TEST_PREFIX + '-2';
35
- registerSession(id, { status: 'active' });
36
- const updated = updateSession(id, { pageCount: 2 });
37
- assert.strictEqual(updated.profileId, id);
38
- assert.strictEqual(updated.pageCount, 2);
39
- unregisterSession(id);
40
- });
41
-
42
- it('should create when update called on missing session', () => {
43
- const id = TEST_PREFIX + '-3';
44
- const updated = updateSession(id, { foo: 'bar' });
45
- assert.strictEqual(updated.profileId, id);
46
- assert.strictEqual(updated.foo, 'bar');
47
- unregisterSession(id);
48
- });
49
-
50
- it('should handle corrupted session JSON by re-registering', () => {
51
- const id = TEST_PREFIX + '-4';
52
- registerSession(id);
53
- const file = getSessionFile(id);
54
- fs.writeFileSync(file, '{bad-json');
55
- const updated = updateSession(id, { repaired: true });
56
- assert.strictEqual(updated.profileId, id);
57
- assert.strictEqual(updated.repaired, true);
58
- unregisterSession(id);
59
- });
60
-
61
- it('should return null for corrupted getSessionInfo', () => {
62
- const id = TEST_PREFIX + '-5';
63
- registerSession(id);
64
- const file = getSessionFile(id);
65
- fs.writeFileSync(file, '{bad-json');
66
- const info = getSessionInfo(id);
67
- assert.strictEqual(info, null);
68
- unregisterSession(id);
69
- });
70
-
71
- it('should list registered sessions', () => {
72
- const id = TEST_PREFIX + '-6';
73
- registerSession(id);
74
- const sessions = listRegisteredSessions();
75
- assert.ok(sessions.some((s) => s.profileId === id));
76
- unregisterSession(id);
77
- });
78
-
79
- it('should mark reconnecting and active', () => {
80
- const id = TEST_PREFIX + '-7';
81
- registerSession(id);
82
- const rec = markSessionReconnecting(id);
83
- assert.strictEqual(rec.status, 'reconnecting');
84
- const act = markSessionActive(id, { sessionId: 'sid' });
85
- assert.strictEqual(act.status, 'active');
86
- assert.strictEqual(act.sessionId, 'sid');
87
- unregisterSession(id);
88
- });
89
-
90
- it('should mark closed and unregister', () => {
91
- const id = TEST_PREFIX + '-8';
92
- registerSession(id);
93
- const removed = markSessionClosed(id);
94
- assert.strictEqual(removed, true);
95
- assert.strictEqual(getSessionInfo(id), null);
96
- });
97
-
98
- it('should cleanup stale/closed/corrupted sessions', () => {
99
- const id1 = TEST_PREFIX + '-9';
100
- const id2 = TEST_PREFIX + '-10';
101
- const id3 = TEST_PREFIX + '-11';
102
- registerSession(id1, { status: 'closed' });
103
- registerSession(id2, { lastSeen: Date.now() - (10 * 24 * 60 * 60 * 1000) });
104
- registerSession(id3);
105
- fs.writeFileSync(getSessionFile(id3), '{broken');
106
-
107
- const cleaned = cleanupStaleSessions();
108
- assert.ok(cleaned >= 2);
109
-
110
- unregisterSession(id1);
111
- unregisterSession(id2);
112
- unregisterSession(id3);
113
- });
114
-
115
- it('should recover session as needs_recovery when health fails', async () => {
116
- const id = TEST_PREFIX + '-12';
117
- registerSession(id);
118
- const res = await recoverSession(id, async () => false);
119
- assert.strictEqual(res.status, 'needs_recovery');
120
- unregisterSession(id);
121
- });
122
-
123
- it('should recover session as recovered when health passes', async () => {
124
- const id = TEST_PREFIX + '-13';
125
- registerSession(id);
126
- const res = await recoverSession(id, async () => true);
127
- assert.strictEqual(res.status, 'recovered');
128
- unregisterSession(id);
129
- });
130
-
131
- it('should return null when recovering missing session', async () => {
132
- const res = await recoverSession('missing-' + TEST_PREFIX, async () => true);
133
- assert.strictEqual(res, null);
134
- });
135
- });
@@ -1,73 +0,0 @@
1
- /**
2
- * Operation Registry Unit Tests
3
- */
4
-
5
- import { describe, it } from 'node:test';
6
- import assert from 'node:assert/strict';
7
- import { registerOperation, getOperation, listOperations } from '../../../modules/operations/src/registry.js';
8
-
9
- describe('OperationRegistry', () => {
10
- it('should register and retrieve an operation', () => {
11
- const testOp = {
12
- id: 'test-op',
13
- description: 'Test operation',
14
- run: async (ctx: any, config: any) => ({ success: true, data: 'test' })
15
- };
16
-
17
- registerOperation(testOp);
18
- const op = getOperation('test-op');
19
-
20
- assert.ok(op);
21
- assert.equal(op.id, 'test-op');
22
- assert.equal(op.description, 'Test operation');
23
- });
24
-
25
- it('should return undefined for non-existent operation', () => {
26
- const op = getOperation('non-existent');
27
- assert.equal(op, undefined);
28
- });
29
-
30
- it('should list all registered operations', () => {
31
- // Clear any existing operations and register a test operation
32
- // Note: In a real scenario, we'd need a way to clear the registry
33
- const ops = listOperations();
34
- assert.ok(ops.length >= 1); // At least our test-op should be there
35
- });
36
-
37
- it('should run operation with context and config', async () => {
38
- const testOp = {
39
- id: 'run-test',
40
- description: 'Run test operation',
41
- run: async (ctx: any, config: any) => {
42
- return {
43
- success: true,
44
- contextReceived: !!ctx,
45
- configReceived: config,
46
- pageAvailable: !!ctx?.page,
47
- systemInputAvailable: !!ctx?.systemInput
48
- };
49
- }
50
- };
51
-
52
- registerOperation(testOp);
53
-
54
- const context = {
55
- page: { evaluate: async (fn: any) => fn() },
56
- systemInput: {
57
- mouseMove: async (x: number, y: number) => ({ x, y }),
58
- mouseClick: async (x: number, y: number) => ({ x, y })
59
- }
60
- };
61
-
62
- const result = await testOp.run(context, { test: 'config' });
63
-
64
- assert.ok(result.success);
65
- assert.ok(result.contextReceived);
66
- assert.ok(result.configReceived);
67
- assert.ok(result.pageAvailable);
68
- assert.ok(result.systemInputAvailable);
69
- assert.deepEqual(result.configReceived, { test: 'config' });
70
- });
71
- });
72
-
73
- console.log('✅ OperationRegistry tests completed');