@web-auto/webauto 0.1.1 → 0.1.2

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 +247 -12
  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 +37 -9
  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,95 +0,0 @@
1
- // services/unified-api/__tests__/task-state.test.ts
2
- import test from 'node:test';
3
- import assert from 'node:assert';
4
- import { taskStateRegistry } from '../task-state.js';
5
-
6
- test('createTask creates a new task', () => {
7
- const task = taskStateRegistry.createTask({
8
- runId: 'test-run-1',
9
- profileId: 'profile-1',
10
- keyword: 'test-keyword',
11
- phase: 'phase2',
12
- });
13
- assert.equal(task.runId, 'test-run-1');
14
- assert.equal(task.profileId, 'profile-1');
15
- assert.equal(task.keyword, 'test-keyword');
16
- assert.equal(task.phase, 'phase2');
17
- assert.equal(task.status, 'starting');
18
- taskStateRegistry.deleteTask('test-run-1');
19
- });
20
-
21
- test('getTask returns undefined for non-existent task', () => {
22
- const task = taskStateRegistry.getTask('non-existent');
23
- assert.equal(task, undefined);
24
- });
25
-
26
- test('updateProgress updates progress and broadcasts', (t, done) => {
27
- const task = taskStateRegistry.createTask({
28
- runId: 'test-run-2',
29
- profileId: 'profile-1',
30
- keyword: 'test',
31
- });
32
- const unsub = taskStateRegistry.subscribe((update) => {
33
- if (update.runId === 'test-run-2' && update.type === 'progress') {
34
- assert.equal(update.data.processed, 5);
35
- unsub();
36
- taskStateRegistry.deleteTask('test-run-2');
37
- done();
38
- }
39
- });
40
- taskStateRegistry.updateProgress('test-run-2', { processed: 5, total: 10 });
41
- });
42
-
43
- test('pushEvent stores event and broadcasts', (t, done) => {
44
- const task = taskStateRegistry.createTask({
45
- runId: 'test-run-3',
46
- profileId: 'profile-1',
47
- keyword: 'test',
48
- });
49
- const unsub = taskStateRegistry.subscribe((update) => {
50
- if (update.runId === 'test-run-3' && update.type === 'event') {
51
- assert.equal(update.data.type, 'phase_unified_done');
52
- unsub();
53
- taskStateRegistry.deleteTask('test-run-3');
54
- done();
55
- }
56
- });
57
- taskStateRegistry.pushEvent('test-run-3', 'phase_unified_done', { notesProcessed: 1 });
58
- });
59
-
60
- test('setStatus changes status and sets completedAt for terminal states', () => {
61
- const task = taskStateRegistry.createTask({
62
- runId: 'test-run-4',
63
- profileId: 'profile-1',
64
- keyword: 'test',
65
- });
66
- assert.equal(task.completedAt, undefined);
67
- taskStateRegistry.setStatus('test-run-4', 'completed');
68
- const updated = taskStateRegistry.getTask('test-run-4');
69
- assert.ok(updated?.completedAt);
70
- taskStateRegistry.deleteTask('test-run-4');
71
- });
72
-
73
- test('getEvents returns events since timestamp', async () => {
74
- const runId = 'test-run-5';
75
- taskStateRegistry.createTask({ runId, profileId: 'p1', keyword: 'test' });
76
- taskStateRegistry.pushEvent(runId, 'event1', {});
77
- await new Promise(r => setTimeout(r, 10)); // Ensure different timestamps
78
- taskStateRegistry.pushEvent(runId, 'event2', {});
79
- const all = taskStateRegistry.getEvents(runId);
80
- assert.equal(all.length, 2);
81
- const since = taskStateRegistry.getEvents(runId, all[0].timestamp + 1);
82
- assert.equal(since.length, 1);
83
- assert.equal(since[0].type, 'event2');
84
- taskStateRegistry.deleteTask(runId);
85
- });
86
-
87
- test('deleteTask removes task and events', () => {
88
- const runId = 'test-run-6';
89
- taskStateRegistry.createTask({ runId, profileId: 'p1', keyword: 'test' });
90
- taskStateRegistry.pushEvent(runId, 'event', {});
91
- const deleted = taskStateRegistry.deleteTask(runId);
92
- assert.equal(deleted, true);
93
- assert.equal(taskStateRegistry.getTask(runId), undefined);
94
- assert.deepEqual(taskStateRegistry.getEvents(runId), []);
95
- });
package/sitecustomize.py DELETED
@@ -1,19 +0,0 @@
1
- """Ensure functional modules under runtime are importable by legacy module names."""
2
- from __future__ import annotations
3
-
4
- import sys
5
- from pathlib import Path
6
-
7
- ROOT = Path(__file__).resolve().parent
8
- MODULES = [
9
- ROOT / 'runtime' / 'browser',
10
- ROOT / 'runtime' / 'containers',
11
- ROOT / 'runtime' / 'ui',
12
- ROOT / 'runtime' / 'vision',
13
- ROOT / 'runtime' / 'infra',
14
- ]
15
- for module_dir in MODULES:
16
- if module_dir.exists():
17
- path_str = str(module_dir)
18
- if path_str not in sys.path:
19
- sys.path.insert(0, path_str)
package/tests/README.md DELETED
@@ -1,194 +0,0 @@
1
- # WebAuto Test Suite
2
-
3
- ## 测试架构
4
-
5
- 本项目采用测试金字塔架构,包含三个层次的测试:
6
-
7
- ```
8
- ┌─────────────────────────────────────┐
9
- │ E2E Tests (5%) │ 端到端测试
10
- ├─────────────────────────────────────┤
11
- │ Integration Tests (25%) │ 集成测试
12
- ├─────────────────────────────────────┤
13
- │ Unit Tests (70%) │ 单元测试
14
- └─────────────────────────────────────┘
15
- ```
16
-
17
- ## 目录结构
18
-
19
- ```
20
- tests/
21
- ├── unit/ # 单元测试
22
- │ ├── operations/ # Operation System 测试
23
- │ ├── containers/ # Container Engine 测试
24
- │ ├── event-driven/ # EventBus 测试
25
- │ └── controller/ # Controller 测试
26
-
27
- ├── integration/ # 集成测试
28
- │ ├── 03-test-event-flow.test.mjs
29
- │ ├── 05-test-binding-registry.test.mjs
30
- │ ├── 08-test-weibo-feed-workflow.test.mjs
31
- │ └── 09-test-operation-execution.test.mjs
32
-
33
- ├── e2e/ # 端到端测试
34
- │ ├── workflows/ # 工作流测试
35
- │ └── visual/ # 视觉验证
36
-
37
- ├── fixtures/ # 测试 fixtures
38
- │ ├── pages/ # 测试页面 HTML
39
- │ └── data/ # 测试数据
40
-
41
- └── runner/ # 测试运行器
42
- ├── TestRunner.mjs # 主运行器
43
- ├── TestReporter.mjs # 报告生成器
44
- └── config.json # 测试配置
45
- ```
46
-
47
- ## 运行测试
48
-
49
- ### 运行所有测试
50
- ```bash
51
- ./scripts/run-all-tests.sh
52
- ```
53
-
54
- ### 仅运行单元测试(快速验证)
55
- ```bash
56
- ./scripts/quick-test.sh
57
- ```
58
-
59
- ### 运行特定测试套件
60
- ```bash
61
- # 单元测试
62
- node tests/runner/TestRunner.mjs --suite=unit
63
-
64
- # 集成测试
65
- node tests/runner/TestRunner.mjs --suite=integration
66
-
67
- # E2E 测试
68
- node tests/runner/TestRunner.mjs --suite=e2e
69
- ```
70
-
71
- ### 运行单个测试文件
72
- ```bash
73
- # TypeScript 测试
74
- npx tsx tests/unit/event-driven/EventBus.test.ts
75
-
76
- # JavaScript 测试
77
- node tests/integration/03-test-event-flow.test.mjs
78
- ```
79
-
80
- ## 测试状态
81
-
82
- ### Unit Tests (5/5 passing) ✅
83
- - [x] EventBus
84
- - [x] BindingRegistry
85
- - [x] OperationRegistry
86
- - [x] OperationExecutor
87
- - [x] RuntimeController
88
-
89
- ### Integration Tests (3/3 passing) ✅
90
- - [x] Event Flow
91
- - [x] Binding Registry Integration
92
- - [x] Operation Execution
93
-
94
- ### E2E Tests (1/? planned) 🚧
95
- - [x] Weibo Feed Workflow (planned)
96
- - [ ] Visual Verification (planned)
97
- - [ ] Scroll Load More (planned)
98
-
99
- ## 覆盖率目标
100
-
101
- | 组件 | 目标 | 当前 |
102
- |------|------|------|
103
- | EventBus | 95% | ✅ 100% |
104
- | BindingRegistry | 90% | ✅ 90% |
105
- | OperationRegistry | 95% | ✅ 80% |
106
- | OperationExecutor | 90% | ✅ 70% |
107
- | RuntimeController | 85% | ⚠️ 50% |
108
-
109
- ## 测试报告
110
-
111
- 测试报告保存在 `tests/reports/` 目录下,包含:
112
- - JSON 格式的详细报告
113
- - 测试结果统计
114
- - 失败测试的详细信息
115
-
116
- ## 编写新测试
117
-
118
- ### 单元测试
119
-
120
- ```typescript
121
- // tests/unit/module/feature.test.ts
122
- import { describe, it } from 'node:test';
123
- import assert from 'node:assert/strict';
124
-
125
- describe('FeatureName', () => {
126
- it('should do something', () => {
127
- assert.equal(1 + 1, 2);
128
- });
129
- });
130
- ```
131
-
132
- ### 集成测试
133
-
134
- ```javascript
135
- // tests/integration/XX-test-feature.test.mjs
136
- #!/usr/bin/env node
137
-
138
- async function test() {
139
- try {
140
- // Test code here
141
- console.log('✅ Test passed');
142
- process.exit(0);
143
- } catch (error) {
144
- console.error('❌ Test failed:', error.message);
145
- process.exit(1);
146
- }
147
- }
148
-
149
- test();
150
- ```
151
-
152
- ## CI/CD 集成
153
-
154
- 测试套件集成到 CI/CD 流程:
155
-
156
- 1. **Pre-commit**: 运行快速单元测试
157
- 2. **PR 验证**: 运行完整测试套件
158
- 3. **Merge**: 生成覆盖率报告
159
-
160
- ## 故障排除
161
-
162
- ### 测试失败
163
- 1. 检查测试输出日志
164
- 2. 查看 `tests/reports/` 中的详细报告
165
- 3. 运行单个测试以隔离问题
166
-
167
- ### 依赖问题
168
- ```bash
169
- # 重新安装依赖
170
- npm install
171
-
172
- # 清理缓存
173
- npm cache clean --force
174
- ```
175
-
176
- ### 服务未启动
177
- 某些集成测试需要服务运行:
178
- ```bash
179
- # 启动服务
180
- node scripts/start-headful.mjs
181
- ```
182
-
183
- ## 贡献指南
184
-
185
- 1. 为新功能编写测试
186
- 2. 确保所有测试通过
187
- 3. 保持测试覆盖率 > 80%
188
- 4. 测试文件使用描述性命名
189
-
190
- ## 参考资源
191
-
192
- - [Node.js Test Runner](https://nodejs.org/api/test.html)
193
- - [测试最佳实践](docs/testing-best-practices.md)
194
- - [自动化测试系统设计](docs/automated-test-system-design.md)
@@ -1,171 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Weibo Feed Extraction E2E Test (Optimized Version)
4
- * Goal: Extract 50 feed posts and their links
5
- */
6
-
7
- import assert from 'node:assert/strict';
8
- import { spawn } from 'node:child_process';
9
- import WebSocket from 'ws';
10
- import fs from 'node:fs';
11
- import path from 'node:path';
12
-
13
- const UNIFIED_PORT = 7701;
14
- const BROWSER_PORT = 7704;
15
- const PROFILE_ID = 'weibo_fresh';
16
- const TARGET_URL = 'https://weibo.com';
17
- const MAX_POSTS = 50;
18
- const MAX_SCROLLS = 30;
19
-
20
- let serviceProcess = null;
21
- let extractedLinks = [];
22
- let extractedPosts = [];
23
-
24
- function log(msg) {
25
- const timestamp = new Date().toISOString().split('T')[1].slice(0, 8);
26
- console.log(`[${timestamp}] [weibo-e2e] ${msg}`);
27
- }
28
-
29
- async function startServices() {
30
- log('Starting services with headful launcher...');
31
- return new Promise((resolve, reject) => {
32
- const launcherPath = path.resolve('scripts/start-headful.mjs');
33
- serviceProcess = spawn('node', [launcherPath, '--profile', PROFILE_ID, '--url', TARGET_URL], {
34
- stdio: 'pipe',
35
- env: { ...process.env, WEBAUTO_HEADLESS: '0' }
36
- });
37
-
38
- let started = false;
39
-
40
- serviceProcess.stdout.on('data', (data) => {
41
- const output = data.toString();
42
- if (output.includes('✅ 容器匹配成功')) {
43
- log('Services ready and container matched');
44
- started = true;
45
- resolve(true);
46
- }
47
- });
48
-
49
- serviceProcess.stderr.on('data', (data) => {
50
- // Ignore routine logs
51
- });
52
-
53
- setTimeout(() => {
54
- if (!started) reject(new Error('Startup timeout'));
55
- }, 60000);
56
- });
57
- }
58
-
59
- async function sendWsAction(action, payload = {}) {
60
- return new Promise((resolve, reject) => {
61
- const ws = new WebSocket(`ws://127.0.0.1:${UNIFIED_PORT}/ws`);
62
- ws.on('open', () => {
63
- ws.send(JSON.stringify({ type: 'action', action, payload, requestId: Date.now() }));
64
- });
65
- ws.on('message', (data) => {
66
- const msg = JSON.parse(data.toString());
67
- if (msg.type === 'response') {
68
- ws.close();
69
- resolve(msg);
70
- }
71
- });
72
- ws.on('error', (err) => { ws.close(); reject(err); });
73
- });
74
- }
75
-
76
- async function extractLinksFromPost(post) {
77
- const selector = post.match?.nodes?.[0]?.selector;
78
- if (!selector) return [];
79
-
80
- try {
81
- const script = `(() => {
82
- const post = document.querySelector('${selector}');
83
- if (!post) return { links: [] };
84
- return {
85
- links: Array.from(post.querySelectorAll('a[href]'))
86
- .map(a => ({ href: a.href, text: a.textContent.trim() }))
87
- .filter(l => l.href.startsWith('http') && !l.href.includes('javascript:'))
88
- .slice(0, 10)
89
- };
90
- })()`;
91
-
92
- const result = await sendWsAction('browser:execute', {
93
- profile: PROFILE_ID,
94
- script
95
- });
96
-
97
- return result.data?.links || [];
98
- } catch (err) {
99
- log(`Extract failed: ${err.message}`);
100
- return [];
101
- }
102
- }
103
-
104
- async function scrollPage() {
105
- await sendWsAction('browser:execute', {
106
- profile: PROFILE_ID,
107
- script: 'window.scrollBy({ top: 800, behavior: "smooth" })'
108
- });
109
- await new Promise(r => setTimeout(r, 2000));
110
- }
111
-
112
- async function main() {
113
- try {
114
- await startServices();
115
-
116
- let scrollCount = 0;
117
-
118
- while (extractedPosts.length < MAX_POSTS && scrollCount < MAX_SCROLLS) {
119
- log(`Scanning... (Found: ${extractedPosts.length}/${MAX_POSTS})`);
120
-
121
- const matchResult = await sendWsAction('containers:match', {
122
- profile: PROFILE_ID,
123
- url: TARGET_URL,
124
- maxDepth: 3,
125
- maxChildren: 100
126
- });
127
-
128
- const containers = matchResult.data?.snapshot?.container_tree?.containers || [];
129
- const posts = containers.filter(c => c.id.includes('feed_post'));
130
-
131
- // Process new posts
132
- for (const post of posts) {
133
- if (extractedPosts.some(p => p.id === post.id)) continue;
134
-
135
- const links = await extractLinksFromPost(post);
136
- if (links.length > 0) {
137
- extractedPosts.push({ id: post.id, links });
138
- extractedLinks.push(...links);
139
- log(` + Processed post ${post.id} (${links.length} links)`);
140
- }
141
- }
142
-
143
- await scrollPage();
144
- scrollCount++;
145
- }
146
-
147
- log('=== Results ===');
148
- log(`Total Posts: ${extractedPosts.length}`);
149
- log(`Total Links: ${extractedLinks.length}`);
150
-
151
- const resultFile = `/tmp/weibo-results-${Date.now()}.json`;
152
- fs.writeFileSync(resultFile, JSON.stringify({ posts: extractedPosts }, null, 2));
153
- log(`Saved to ${resultFile}`);
154
-
155
- if (extractedPosts.length > 0) {
156
- log('✅ Test Passed');
157
- } else {
158
- log('❌ Test Failed: No posts extracted');
159
- process.exit(1);
160
- }
161
-
162
- } catch (error) {
163
- console.error(error);
164
- process.exit(1);
165
- } finally {
166
- if (serviceProcess) serviceProcess.kill();
167
- process.exit(0);
168
- }
169
- }
170
-
171
- main();
@@ -1,67 +0,0 @@
1
- {
2
- "test_page": {
3
- "id": "test_page",
4
- "name": "Test Page",
5
- "type": "page",
6
- "selectors": [
7
- {
8
- "css": "#app",
9
- "variant": "primary",
10
- "score": 1.0
11
- }
12
- ],
13
- "capabilities": ["highlight", "find-child"],
14
- "children": ["test_page.main_container"]
15
- },
16
- "test_page.main_container": {
17
- "id": "test_page.main_container",
18
- "name": "Main Container",
19
- "type": "section",
20
- "selectors": [
21
- {
22
- "css": "#main-container",
23
- "variant": "primary",
24
- "score": 1.0
25
- }
26
- ],
27
- "capabilities": ["highlight", "find-child"],
28
- "children": ["test_page.list_container"]
29
- },
30
- "test_page.list_container": {
31
- "id": "test_page.list_container",
32
- "name": "List Container",
33
- "type": "collection",
34
- "selectors": [
35
- {
36
- "css": "#list-container",
37
- "variant": "primary",
38
- "score": 1.0
39
- }
40
- ],
41
- "capabilities": ["highlight", "find-child", "scroll"],
42
- "children": ["test_page.item"]
43
- },
44
- "test_page.item": {
45
- "id": "test_page.item",
46
- "name": "List Item",
47
- "type": "content",
48
- "selectors": [
49
- {
50
- "css": ".item",
51
- "variant": "primary",
52
- "score": 1.0
53
- }
54
- ],
55
- "capabilities": ["highlight", "extract"],
56
- "operations": [
57
- {
58
- "type": "extract",
59
- "config": {
60
- "target": "links",
61
- "selector": "a[href]",
62
- "include_text": true
63
- }
64
- }
65
- ]
66
- }
67
- }
@@ -1,69 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Simple Test Page</title>
7
- <style>
8
- body {
9
- font-family: Arial, sans-serif;
10
- padding: 20px;
11
- }
12
- .container {
13
- border: 2px solid #333;
14
- padding: 20px;
15
- margin: 10px 0;
16
- }
17
- .item {
18
- border: 1px solid #999;
19
- padding: 10px;
20
- margin: 5px 0;
21
- }
22
- a {
23
- color: #0066cc;
24
- text-decoration: none;
25
- }
26
- a:hover {
27
- text-decoration: underline;
28
- }
29
- </style>
30
- </head>
31
- <body>
32
- <div id="app">
33
- <h1>Test Page</h1>
34
-
35
- <div id="main-container" class="container">
36
- <h2>Main Container</h2>
37
-
38
- <div id="list-container" class="container">
39
- <h3>List Container</h3>
40
-
41
- <div class="item" data-id="item-1">
42
- <h4>Item 1</h4>
43
- <p>This is item 1</p>
44
- <a href="https://example.com/1">Link 1</a>
45
- </div>
46
-
47
- <div class="item" data-id="item-2">
48
- <h4>Item 2</h4>
49
- <p>This is item 2</p>
50
- <a href="https://example.com/2">Link 2</a>
51
- </div>
52
-
53
- <div class="item" data-id="item-3">
54
- <h4>Item 3</h4>
55
- <p>This is item 3</p>
56
- <a href="https://example.com/3">Link 3</a>
57
- </div>
58
- </div>
59
- </div>
60
- </div>
61
-
62
- <script>
63
- // Add some dynamic behavior for testing
64
- document.addEventListener('DOMContentLoaded', () => {
65
- console.log('Test page loaded');
66
- });
67
- </script>
68
- </body>
69
- </html>