@sovovs/bycli 1.8.0 → 2.0.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.
Files changed (509) hide show
  1. package/cli-manifest.json +0 -61
  2. package/dist/src/adapter-shadow.js +2 -2
  3. package/dist/src/browser/analyze.d.ts +10 -99
  4. package/dist/src/browser/analyze.js +10 -226
  5. package/dist/src/browser/cdp.js +64 -7
  6. package/dist/src/browser/navigation-guard.d.ts +78 -0
  7. package/dist/src/browser/navigation-guard.js +142 -0
  8. package/dist/src/browser/navigation-guard.test.d.ts +1 -0
  9. package/dist/src/browser/url-policy.d.ts +89 -0
  10. package/dist/src/browser/url-policy.js +311 -0
  11. package/dist/src/browser/url-policy.test.d.ts +1 -0
  12. package/dist/src/browser/verify-fixture.js +2 -2
  13. package/dist/src/cli.js +10 -13
  14. package/dist/src/config-paths.d.ts +19 -0
  15. package/dist/src/config-paths.js +31 -0
  16. package/dist/src/daemon.js +240 -0
  17. package/dist/src/discovery.d.ts +5 -3
  18. package/dist/src/discovery.js +8 -6
  19. package/dist/src/execution.js +8 -3
  20. package/dist/src/main.js +18 -2
  21. package/dist/src/plugin.js +11 -8
  22. package/dist/src/recorder/highlevel/analyze.d.ts +29 -0
  23. package/dist/src/recorder/highlevel/analyze.js +91 -0
  24. package/dist/src/recorder/highlevel/init.d.ts +125 -0
  25. package/dist/src/recorder/highlevel/init.js +279 -0
  26. package/dist/src/recorder/highlevel/init.test.d.ts +1 -0
  27. package/dist/src/recorder/highlevel/verify.d.ts +73 -0
  28. package/dist/src/recorder/highlevel/verify.js +74 -0
  29. package/dist/src/recorder/http/analyze-runner.d.ts +28 -0
  30. package/dist/src/recorder/http/analyze-runner.js +78 -0
  31. package/dist/src/recorder/http/analyze-runner.test.d.ts +1 -0
  32. package/dist/src/recorder/http/handlers.d.ts +51 -0
  33. package/dist/src/recorder/http/handlers.js +219 -0
  34. package/dist/src/recorder/http/wrapper-config.d.ts +20 -0
  35. package/dist/src/recorder/http/wrapper-config.js +82 -0
  36. package/dist/src/recorder/http/wrapper-envelope.d.ts +31 -0
  37. package/dist/src/recorder/http/wrapper-envelope.js +51 -0
  38. package/dist/src/recorder/http/wrapper-gates.d.ts +16 -0
  39. package/dist/src/recorder/http/wrapper-gates.js +28 -0
  40. package/dist/src/recorder/http/wrapper-metrics.d.ts +1 -0
  41. package/dist/src/recorder/http/wrapper-metrics.js +5 -0
  42. package/dist/src/recorder/http/wrapper-registry.d.ts +50 -0
  43. package/dist/src/recorder/http/wrapper-registry.js +98 -0
  44. package/dist/src/recorder/http/wrapper-server.d.ts +59 -0
  45. package/dist/src/recorder/http/wrapper-server.js +240 -0
  46. package/dist/src/recorder/http/wrapper.test.d.ts +1 -0
  47. package/dist/src/recorder/observability/logger.d.ts +5 -0
  48. package/dist/src/recorder/observability/logger.js +13 -0
  49. package/dist/src/recorder/runner/config.d.ts +34 -0
  50. package/dist/src/recorder/runner/config.js +84 -0
  51. package/dist/src/recorder/runner/config.test.d.ts +1 -0
  52. package/dist/src/recorder/runner/reap.d.ts +79 -0
  53. package/dist/src/recorder/runner/reap.js +230 -0
  54. package/dist/src/recorder/runner/reap.test.d.ts +1 -0
  55. package/dist/src/recorder/runner/runner-port.d.ts +95 -0
  56. package/dist/src/recorder/runner/runner-port.js +518 -0
  57. package/dist/src/recorder/runner/runner-port.test.d.ts +1 -0
  58. package/dist/src/recorder/runner/session-keys.d.ts +28 -0
  59. package/dist/src/recorder/runner/session-keys.js +72 -0
  60. package/dist/src/recorder/runner/session-keys.test.d.ts +1 -0
  61. package/dist/src/recorder/runner/verify-runner-main.d.ts +95 -0
  62. package/dist/src/recorder/runner/verify-runner-main.js +275 -0
  63. package/dist/src/recorder/runner/verify-runner-main.test.d.ts +1 -0
  64. package/package.json +8 -5
  65. package/scripts/m1-daemon-navigate-drive.mjs +138 -0
  66. package/scripts/m1-extension-spike.mjs +237 -0
  67. package/scripts/m1-live-spike.mjs +156 -0
  68. package/scripts/m6b-connect-back-spike.sh +31 -0
  69. package/scripts/recorder.sh +186 -0
  70. package/clis/12306/utils.test.js +0 -331
  71. package/clis/1688/assets.test.js +0 -39
  72. package/clis/1688/download.test.js +0 -31
  73. package/clis/1688/item.test.js +0 -67
  74. package/clis/1688/search.test.js +0 -75
  75. package/clis/1688/shared.test.js +0 -57
  76. package/clis/1688/store.test.js +0 -62
  77. package/clis/36kr/article.test.js +0 -46
  78. package/clis/36kr/hot.test.js +0 -15
  79. package/clis/36kr/news.test.js +0 -85
  80. package/clis/51job/utils.test.js +0 -69
  81. package/clis/_atlassian/shared.test.js +0 -170
  82. package/clis/aibase/news.test.js +0 -59
  83. package/clis/amazon/bestsellers.test.js +0 -29
  84. package/clis/amazon/discussion.test.js +0 -124
  85. package/clis/amazon/offer.test.js +0 -29
  86. package/clis/amazon/product.test.js +0 -24
  87. package/clis/amazon/rankings.test.js +0 -41
  88. package/clis/amazon/search.test.js +0 -22
  89. package/clis/amazon/shared.test.js +0 -44
  90. package/clis/apple-podcasts/commands.test.js +0 -119
  91. package/clis/apple-podcasts/utils.test.js +0 -57
  92. package/clis/arxiv/arxiv.test.js +0 -112
  93. package/clis/baidu-scholar/search.test.js +0 -23
  94. package/clis/barchart/greeks.test.js +0 -138
  95. package/clis/bilibili/comment.test.js +0 -153
  96. package/clis/bilibili/comments.test.js +0 -142
  97. package/clis/bilibili/dynamic.test.js +0 -68
  98. package/clis/bilibili/hot.test.js +0 -17
  99. package/clis/bilibili/subtitle.test.js +0 -196
  100. package/clis/bilibili/summary.test.js +0 -210
  101. package/clis/bilibili/utils.test.js +0 -61
  102. package/clis/bilibili/video.test.js +0 -132
  103. package/clis/binance/commands.test.js +0 -70
  104. package/clis/bloomberg/utils.test.js +0 -129
  105. package/clis/booking/booking.test.js +0 -356
  106. package/clis/boss/chatlist.test.js +0 -211
  107. package/clis/boss/chatmsg.test.js +0 -230
  108. package/clis/boss/search.test.js +0 -78
  109. package/clis/boss/utils.test.js +0 -34
  110. package/clis/brave/search.test.js +0 -76
  111. package/clis/chaoxing/utils.test.js +0 -45
  112. package/clis/chatgpt/commands.test.js +0 -45
  113. package/clis/chatgpt/envelope.test.js +0 -108
  114. package/clis/chatgpt/image.test.js +0 -188
  115. package/clis/chatgpt/utils.test.js +0 -330
  116. package/clis/chatgpt-app/ax.test.js +0 -35
  117. package/clis/chatwise/composer.test.js +0 -186
  118. package/clis/chess/analyze.test.js +0 -79
  119. package/clis/chess/game.test.js +0 -178
  120. package/clis/chess/games.test.js +0 -164
  121. package/clis/chess/stats.test.js +0 -79
  122. package/clis/chess/utils.test.js +0 -230
  123. package/clis/claude/ask.test.js +0 -338
  124. package/clis/claude/commands.test.js +0 -118
  125. package/clis/claude/utils.test.js +0 -148
  126. package/clis/cnki/search.test.js +0 -18
  127. package/clis/codex/sidebar.test.js +0 -329
  128. package/clis/coingecko/coingecko.test.js +0 -109
  129. package/clis/confluence/commands.test.js +0 -195
  130. package/clis/coupang/coupang.test.js +0 -159
  131. package/clis/coupang/utils.test.js +0 -62
  132. package/clis/ctrip/ctrip.test.js +0 -719
  133. package/clis/dblp/dblp.test.js +0 -397
  134. package/clis/deepseek/ask.test.js +0 -312
  135. package/clis/deepseek/detail.test.js +0 -81
  136. package/clis/deepseek/send.test.js +0 -107
  137. package/clis/deepseek/utils.test.js +0 -370
  138. package/clis/defillama/defillama.test.js +0 -99
  139. package/clis/devto/devto.test.js +0 -236
  140. package/clis/dianping/dianping.test.js +0 -578
  141. package/clis/douban/download.test.js +0 -170
  142. package/clis/douban/movie-hot.test.js +0 -14
  143. package/clis/douban/search.test.js +0 -11
  144. package/clis/douban/subject.test.js +0 -11
  145. package/clis/douban/utils.test.js +0 -438
  146. package/clis/doubao/detail.test.js +0 -42
  147. package/clis/doubao/history.test.js +0 -37
  148. package/clis/doubao/utils.test.js +0 -344
  149. package/clis/douyin/_shared/browser-fetch.test.js +0 -64
  150. package/clis/douyin/_shared/creation-id.test.js +0 -22
  151. package/clis/douyin/_shared/imagex-upload.test.js +0 -87
  152. package/clis/douyin/_shared/sts2.test.js +0 -27
  153. package/clis/douyin/_shared/text-extra.test.js +0 -37
  154. package/clis/douyin/_shared/timing.test.js +0 -28
  155. package/clis/douyin/_shared/tos-upload-short-read.test.js +0 -83
  156. package/clis/douyin/_shared/tos-upload.test.js +0 -229
  157. package/clis/douyin/_shared/transcode.test.js +0 -91
  158. package/clis/douyin/_shared/vod-upload.test.js +0 -38
  159. package/clis/douyin/activities.test.js +0 -55
  160. package/clis/douyin/collections.test.js +0 -45
  161. package/clis/douyin/delete.test.js +0 -100
  162. package/clis/douyin/draft.test.js +0 -335
  163. package/clis/douyin/drafts.test.js +0 -11
  164. package/clis/douyin/hashtag.test.js +0 -171
  165. package/clis/douyin/location.test.js +0 -23
  166. package/clis/douyin/profile.test.js +0 -46
  167. package/clis/douyin/publish-upload-id.test.js +0 -170
  168. package/clis/douyin/publish.test.js +0 -38
  169. package/clis/douyin/stats.test.js +0 -22
  170. package/clis/douyin/update.test.js +0 -11
  171. package/clis/douyin/user-videos.test.js +0 -151
  172. package/clis/douyin/videos.test.js +0 -54
  173. package/clis/duckduckgo/search.test.js +0 -128
  174. package/clis/duckduckgo/suggest.test.js +0 -66
  175. package/clis/eastmoney/hot-rank.test.js +0 -59
  176. package/clis/endoflife/endoflife.test.js +0 -51
  177. package/clis/facebook/feed.test.js +0 -169
  178. package/clis/facebook/marketplace.test.js +0 -91
  179. package/clis/facebook/notifications.test.js +0 -458
  180. package/clis/facebook/search.test.js +0 -55
  181. package/clis/flathub/flathub.test.js +0 -90
  182. package/clis/flomo/memos.test.js +0 -144
  183. package/clis/gemini/ask.test.js +0 -100
  184. package/clis/gemini/deep-research-result.test.js +0 -155
  185. package/clis/gemini/deep-research.test.js +0 -181
  186. package/clis/gemini/reply-state.test.js +0 -671
  187. package/clis/gemini/utils.test.js +0 -198
  188. package/clis/geogebra/geogebra.test.js +0 -175
  189. package/clis/gitee/search.test.js +0 -65
  190. package/clis/gitee/user.test.js +0 -63
  191. package/clis/google/utils.test.js +0 -75
  192. package/clis/google-scholar/cite.test.js +0 -47
  193. package/clis/google-scholar/profile.test.js +0 -49
  194. package/clis/google-scholar/search.test.js +0 -71
  195. package/clis/goproxy/goproxy.test.js +0 -103
  196. package/clis/gov-law/commands.test.js +0 -39
  197. package/clis/gov-policy/gov-policy.test.js +0 -224
  198. package/clis/grok/ask.test.js +0 -29
  199. package/clis/grok/utils.test.js +0 -103
  200. package/clis/hackernews/hackernews.test.js +0 -132
  201. package/clis/hf/hf.test.js +0 -16
  202. package/clis/hupu/hot.test.js +0 -224
  203. package/clis/imdb/utils.test.js +0 -88
  204. package/clis/indeed/indeed.test.js +0 -375
  205. package/clis/instagram/_shared/private-publish.test.js +0 -705
  206. package/clis/instagram/_shared/protocol-capture.test.js +0 -114
  207. package/clis/instagram/download.test.js +0 -118
  208. package/clis/instagram/note.test.js +0 -53
  209. package/clis/instagram/post.test.js +0 -1647
  210. package/clis/instagram/reel.test.js +0 -167
  211. package/clis/instagram/story.test.js +0 -134
  212. package/clis/jd/commands.test.js +0 -41
  213. package/clis/jd/item.test.js +0 -354
  214. package/clis/jianyu/search.test.js +0 -153
  215. package/clis/jianyu/shared/procurement-contract.test.js +0 -72
  216. package/clis/jianyu/shared/procurement-detail.test.js +0 -84
  217. package/clis/jike/read.test.js +0 -86
  218. package/clis/jira/commands.test.js +0 -287
  219. package/clis/juejin/search.js +0 -123
  220. package/clis/juejin/search.test.js +0 -98
  221. package/clis/lesswrong/frontpage.test.js +0 -37
  222. package/clis/lichess/lichess.test.js +0 -85
  223. package/clis/linkedin/connect.test.js +0 -213
  224. package/clis/linkedin/inbox.test.js +0 -152
  225. package/clis/linkedin/job-detail.test.js +0 -38
  226. package/clis/linkedin/jobs-preferences.test.js +0 -43
  227. package/clis/linkedin/people-search.test.js +0 -216
  228. package/clis/linkedin/post-analytics.test.js +0 -40
  229. package/clis/linkedin/posts.test.js +0 -40
  230. package/clis/linkedin/profile-analytics.test.js +0 -67
  231. package/clis/linkedin/profile-experience.test.js +0 -152
  232. package/clis/linkedin/profile-projects.test.js +0 -111
  233. package/clis/linkedin/profile-read.test.js +0 -77
  234. package/clis/linkedin/safe-send.test.js +0 -204
  235. package/clis/linkedin/salesnav-inbox.test.js +0 -113
  236. package/clis/linkedin/salesnav-message.test.js +0 -172
  237. package/clis/linkedin/salesnav-search.test.js +0 -76
  238. package/clis/linkedin/salesnav-thread.test.js +0 -79
  239. package/clis/linkedin/search.test.js +0 -222
  240. package/clis/linkedin/sent-invitations.test.js +0 -62
  241. package/clis/linkedin/services-read.test.js +0 -105
  242. package/clis/linkedin/thread-snapshot.test.js +0 -89
  243. package/clis/linkedin/timeline.test.js +0 -81
  244. package/clis/linkedin-learning/course.test.js +0 -114
  245. package/clis/linkedin-learning/search.test.js +0 -144
  246. package/clis/linkedin-learning/trending.test.js +0 -123
  247. package/clis/linux-do/feed.test.js +0 -153
  248. package/clis/linux-do/topic-content.test.js +0 -59
  249. package/clis/lobsters/lobsters.test.js +0 -169
  250. package/clis/notebooklm/add-source.test.js +0 -97
  251. package/clis/notebooklm/compat.test.js +0 -16
  252. package/clis/notebooklm/create.test.js +0 -58
  253. package/clis/notebooklm/generate-audio.test.js +0 -63
  254. package/clis/notebooklm/generate-slides.test.js +0 -75
  255. package/clis/notebooklm/history.test.js +0 -58
  256. package/clis/notebooklm/note-list.test.js +0 -56
  257. package/clis/notebooklm/notes-get.test.js +0 -72
  258. package/clis/notebooklm/open.test.js +0 -63
  259. package/clis/notebooklm/rpc.test.js +0 -131
  260. package/clis/notebooklm/source-fulltext.test.js +0 -106
  261. package/clis/notebooklm/source-get.test.js +0 -84
  262. package/clis/notebooklm/source-guide.test.js +0 -104
  263. package/clis/notebooklm/summary.test.js +0 -78
  264. package/clis/notebooklm/utils.test.js +0 -449
  265. package/clis/notebooklm/write-note.test.js +0 -70
  266. package/clis/nuget/nuget.test.js +0 -111
  267. package/clis/oeis/oeis.test.js +0 -88
  268. package/clis/ones/task-helpers.test.js +0 -12
  269. package/clis/ones/worklog.test.js +0 -20
  270. package/clis/openfda/openfda.test.js +0 -114
  271. package/clis/openreview/openreview.test.js +0 -427
  272. package/clis/osv/osv.test.js +0 -97
  273. package/clis/paperreview/commands.test.js +0 -243
  274. package/clis/paperreview/utils.test.js +0 -49
  275. package/clis/pixiv/download.test.js +0 -87
  276. package/clis/pixiv/illusts.test.js +0 -99
  277. package/clis/pixiv/search.test.js +0 -83
  278. package/clis/powerchina/search.test.js +0 -93
  279. package/clis/producthunt/utils.test.js +0 -64
  280. package/clis/pubmed/pubmed.test.js +0 -276
  281. package/clis/quark/utils.test.js +0 -58
  282. package/clis/qwen/utils.test.js +0 -45
  283. package/clis/reddit/extract-media.test.js +0 -149
  284. package/clis/reddit/frontpage.test.js +0 -34
  285. package/clis/reddit/home.test.js +0 -170
  286. package/clis/reddit/hot.test.js +0 -32
  287. package/clis/reddit/popular.test.js +0 -26
  288. package/clis/reddit/read.test.js +0 -335
  289. package/clis/reddit/reply.test.js +0 -89
  290. package/clis/reddit/search.test.js +0 -26
  291. package/clis/reddit/subreddit-info.test.js +0 -163
  292. package/clis/reddit/subreddit.test.js +0 -31
  293. package/clis/reddit/subscribed.test.js +0 -168
  294. package/clis/reddit/whoami.test.js +0 -105
  295. package/clis/rednote/navigation.test.js +0 -26
  296. package/clis/rednote/rednote.test.js +0 -222
  297. package/clis/rest-countries/rest-countries.test.js +0 -83
  298. package/clis/reuters/reuters.test.js +0 -299
  299. package/clis/rfc/rfc.test.js +0 -74
  300. package/clis/sinafinance/stock.test.js +0 -59
  301. package/clis/spotify/utils.test.js +0 -67
  302. package/clis/stackoverflow/stackoverflow.test.js +0 -404
  303. package/clis/steam/steam.test.js +0 -46
  304. package/clis/substack/utils.test.js +0 -44
  305. package/clis/suno/commands.test.js +0 -188
  306. package/clis/suno/download.test.js +0 -151
  307. package/clis/suno/generate.test.js +0 -252
  308. package/clis/suno/utils.test.js +0 -329
  309. package/clis/taobao/commands.test.js +0 -41
  310. package/clis/tdx/hot-rank.test.js +0 -59
  311. package/clis/ths/hot-rank.test.js +0 -64
  312. package/clis/tieba/commands.test.js +0 -79
  313. package/clis/tieba/utils.test.js +0 -290
  314. package/clis/tiktok/creator-videos.test.js +0 -113
  315. package/clis/tiktok/refactor.test.js +0 -389
  316. package/clis/tiktok/write-refactor.test.js +0 -370
  317. package/clis/toutiao/toutiao.test.js +0 -378
  318. package/clis/tvmaze/tvmaze.test.js +0 -93
  319. package/clis/twitter/bookmark-folder.test.js +0 -395
  320. package/clis/twitter/bookmark-folders.test.js +0 -152
  321. package/clis/twitter/bookmark.test.js +0 -74
  322. package/clis/twitter/bookmarks.test.js +0 -205
  323. package/clis/twitter/delete.test.js +0 -85
  324. package/clis/twitter/device-follow.test.js +0 -287
  325. package/clis/twitter/download.test.js +0 -457
  326. package/clis/twitter/followers.test.js +0 -62
  327. package/clis/twitter/following.test.js +0 -338
  328. package/clis/twitter/hide-reply.test.js +0 -76
  329. package/clis/twitter/like.test.js +0 -73
  330. package/clis/twitter/likes.test.js +0 -220
  331. package/clis/twitter/list-add.test.js +0 -133
  332. package/clis/twitter/list-create.test.js +0 -169
  333. package/clis/twitter/list-remove.test.js +0 -110
  334. package/clis/twitter/list-tweets.test.js +0 -196
  335. package/clis/twitter/lists.test.js +0 -253
  336. package/clis/twitter/post.test.js +0 -258
  337. package/clis/twitter/profile.test.js +0 -39
  338. package/clis/twitter/quote.test.js +0 -194
  339. package/clis/twitter/reply.test.js +0 -237
  340. package/clis/twitter/retweet.test.js +0 -73
  341. package/clis/twitter/search.test.js +0 -349
  342. package/clis/twitter/shared.test.js +0 -794
  343. package/clis/twitter/thread.test.js +0 -58
  344. package/clis/twitter/timeline.test.js +0 -104
  345. package/clis/twitter/trending.test.js +0 -15
  346. package/clis/twitter/tweets.test.js +0 -362
  347. package/clis/twitter/unbookmark.test.js +0 -73
  348. package/clis/twitter/unlike.test.js +0 -75
  349. package/clis/twitter/unretweet.test.js +0 -73
  350. package/clis/twitter/utils.test.js +0 -169
  351. package/clis/uisdc/news.test.js +0 -66
  352. package/clis/uiverse/_shared.test.js +0 -62
  353. package/clis/uiverse/navigation.test.js +0 -12
  354. package/clis/upwork/upwork.test.js +0 -566
  355. package/clis/wanfang/search.test.js +0 -23
  356. package/clis/web/read.test.js +0 -392
  357. package/clis/weibo/delete.test.js +0 -94
  358. package/clis/weibo/envelope.test.js +0 -85
  359. package/clis/weibo/favorites.test.js +0 -114
  360. package/clis/weibo/publish.test.js +0 -192
  361. package/clis/weibo/user-posts.test.js +0 -92
  362. package/clis/weibo/utils.test.js +0 -36
  363. package/clis/weixin/drafts.test.js +0 -69
  364. package/clis/weixin/search.test.js +0 -227
  365. package/clis/weread/ai-outline.test.js +0 -83
  366. package/clis/weread/book-search.test.js +0 -242
  367. package/clis/weread/commands.test.js +0 -398
  368. package/clis/weread/private-api-regression.test.js +0 -369
  369. package/clis/weread/search-regression.test.js +0 -494
  370. package/clis/weread/utils.test.js +0 -128
  371. package/clis/weread-official/commands.test.js +0 -385
  372. package/clis/weread-official/utils.test.js +0 -242
  373. package/clis/wikidata/wikidata.test.js +0 -83
  374. package/clis/wikipedia/trending.test.js +0 -57
  375. package/clis/wttr/wttr.test.js +0 -84
  376. package/clis/xianyu/chat.test.js +0 -84
  377. package/clis/xianyu/im.test.js +0 -253
  378. package/clis/xianyu/item.test.js +0 -56
  379. package/clis/xianyu/publish.test.js +0 -220
  380. package/clis/xianyu/search.test.js +0 -17
  381. package/clis/xiaoe/xiaoe.test.js +0 -486
  382. package/clis/xiaohongshu/comments.test.js +0 -258
  383. package/clis/xiaohongshu/creator-note-detail.test.js +0 -451
  384. package/clis/xiaohongshu/creator-notes-summary.test.js +0 -94
  385. package/clis/xiaohongshu/creator-notes.test.js +0 -281
  386. package/clis/xiaohongshu/creator-stats.test.js +0 -24
  387. package/clis/xiaohongshu/delete-note.test.js +0 -172
  388. package/clis/xiaohongshu/download.test.js +0 -316
  389. package/clis/xiaohongshu/navigation.test.js +0 -34
  390. package/clis/xiaohongshu/note.test.js +0 -249
  391. package/clis/xiaohongshu/publish.test.js +0 -608
  392. package/clis/xiaohongshu/search.test.js +0 -325
  393. package/clis/xiaohongshu/user-helpers.test.js +0 -160
  394. package/clis/xiaoyuzhou/auth.test.js +0 -124
  395. package/clis/xiaoyuzhou/download.test.js +0 -135
  396. package/clis/xiaoyuzhou/podcast-episodes.test.js +0 -78
  397. package/clis/xiaoyuzhou/transcript.test.js +0 -195
  398. package/clis/xiaoyuzhou/utils.test.js +0 -39
  399. package/clis/xueqiu/comments.test.js +0 -696
  400. package/clis/xueqiu/danjuan-utils.test.js +0 -41
  401. package/clis/xueqiu/utils.test.js +0 -26
  402. package/clis/yahoo/search.test.js +0 -94
  403. package/clis/youdao/note.test.js +0 -99
  404. package/clis/youtube/channel.test.js +0 -59
  405. package/clis/youtube/feed.test.js +0 -131
  406. package/clis/youtube/transcript-group.test.js +0 -99
  407. package/clis/youtube/transcript.test.js +0 -296
  408. package/clis/youtube/utils.test.js +0 -84
  409. package/clis/yuanbao/ask.test.js +0 -124
  410. package/clis/yuanbao/new.test.js +0 -30
  411. package/clis/yuanbao/shared.test.js +0 -80
  412. package/clis/zhihu/answer-comments.test.js +0 -287
  413. package/clis/zhihu/answer-detail.test.js +0 -338
  414. package/clis/zhihu/answer.test.js +0 -54
  415. package/clis/zhihu/collection.test.js +0 -337
  416. package/clis/zhihu/collections.test.js +0 -182
  417. package/clis/zhihu/comment.test.js +0 -50
  418. package/clis/zhihu/download.test.js +0 -12
  419. package/clis/zhihu/favorite.test.js +0 -59
  420. package/clis/zhihu/follow.test.js +0 -42
  421. package/clis/zhihu/like.test.js +0 -41
  422. package/clis/zhihu/question.test.js +0 -251
  423. package/clis/zhihu/recommend.test.js +0 -143
  424. package/clis/zhihu/search.test.js +0 -198
  425. package/clis/zhihu/target.test.js +0 -77
  426. package/clis/zhihu/text.test.js +0 -24
  427. package/clis/zhihu/write-shared.test.js +0 -176
  428. package/clis/zlibrary/commands.test.js +0 -65
  429. package/clis/zsxq/search.test.js +0 -24
  430. package/clis/zsxq/topic.test.js +0 -30
  431. package/clis/zsxq/topics.test.js +0 -24
  432. package/clis/zsxq/utils.test.js +0 -31
  433. package/dist/src/adapter-shadow.test.js +0 -49
  434. package/dist/src/adapter-source.test.js +0 -29
  435. package/dist/src/browser/analyze.test.js +0 -166
  436. package/dist/src/browser/article-extract.e2e.test.js +0 -105
  437. package/dist/src/browser/article-extract.test.js +0 -94
  438. package/dist/src/browser/ax-snapshot.test.js +0 -91
  439. package/dist/src/browser/base-page.test.js +0 -758
  440. package/dist/src/browser/cdp-click-fixture.test.js +0 -87
  441. package/dist/src/browser/cdp.test.js +0 -79
  442. package/dist/src/browser/compound.test.js +0 -175
  443. package/dist/src/browser/daemon-client.test.js +0 -199
  444. package/dist/src/browser/dom-helpers.test.js +0 -106
  445. package/dist/src/browser/dom-snapshot.test.js +0 -313
  446. package/dist/src/browser/errors.test.js +0 -60
  447. package/dist/src/browser/extract.test.js +0 -129
  448. package/dist/src/browser/find.test.js +0 -180
  449. package/dist/src/browser/html-tree.test.js +0 -181
  450. package/dist/src/browser/network-cache.test.js +0 -58
  451. package/dist/src/browser/network-key.test.js +0 -49
  452. package/dist/src/browser/page.test.js +0 -378
  453. package/dist/src/browser/shape-filter.test.js +0 -101
  454. package/dist/src/browser/shape.test.js +0 -82
  455. package/dist/src/browser/stealth.test.js +0 -134
  456. package/dist/src/browser/target-errors.test.js +0 -94
  457. package/dist/src/browser/target-resolver.test.js +0 -118
  458. package/dist/src/browser/utils.test.js +0 -29
  459. package/dist/src/browser/verify-fixture.test.js +0 -219
  460. package/dist/src/browser.test.js +0 -232
  461. package/dist/src/build-manifest.test.js +0 -341
  462. package/dist/src/capabilityRouting.test.js +0 -63
  463. package/dist/src/cli-argv-preprocess.test.js +0 -209
  464. package/dist/src/cli.test.js +0 -2803
  465. package/dist/src/commanderAdapter.test.js +0 -352
  466. package/dist/src/commands/daemon.test.js +0 -219
  467. package/dist/src/completion.test.js +0 -24
  468. package/dist/src/convention-audit.test.js +0 -247
  469. package/dist/src/daemon.test.js +0 -60
  470. package/dist/src/doctor.test.js +0 -263
  471. package/dist/src/download/article-download.test.js +0 -235
  472. package/dist/src/download/index.test.js +0 -140
  473. package/dist/src/download/media-download.test.js +0 -112
  474. package/dist/src/download/progress.test.js +0 -36
  475. package/dist/src/electron-apps.test.js +0 -49
  476. package/dist/src/engine.test.js +0 -312
  477. package/dist/src/errors.test.js +0 -109
  478. package/dist/src/execution.test.js +0 -623
  479. package/dist/src/extension-manifest-regression.test.js +0 -12
  480. package/dist/src/external.test.js +0 -146
  481. package/dist/src/help.test.js +0 -58
  482. package/dist/src/hooks.test.js +0 -92
  483. package/dist/src/interceptor.test.js +0 -81
  484. package/dist/src/launcher.test.js +0 -138
  485. package/dist/src/node-network.test.js +0 -55
  486. package/dist/src/observation/artifact.test.js +0 -121
  487. package/dist/src/observation/manager.test.js +0 -13
  488. package/dist/src/observation/redaction.test.js +0 -32
  489. package/dist/src/observation/retention.test.js +0 -118
  490. package/dist/src/observation/ring-buffer.test.js +0 -22
  491. package/dist/src/output.test.js +0 -53
  492. package/dist/src/package-exports.test.js +0 -112
  493. package/dist/src/pipeline/executor.test.js +0 -182
  494. package/dist/src/pipeline/steps/download.test.js +0 -102
  495. package/dist/src/pipeline/steps/fetch.test.js +0 -117
  496. package/dist/src/pipeline/template.test.js +0 -175
  497. package/dist/src/pipeline/transform.test.js +0 -133
  498. package/dist/src/plugin-manifest.test.js +0 -179
  499. package/dist/src/plugin-scaffold.test.js +0 -83
  500. package/dist/src/plugin.test.js +0 -1324
  501. package/dist/src/registry.test.js +0 -209
  502. package/dist/src/runtime-detect.test.js +0 -39
  503. package/dist/src/serialization.test.js +0 -78
  504. package/dist/src/snapshotFormatter.test.js +0 -521
  505. package/dist/src/tui.test.js +0 -19
  506. package/dist/src/update-check.test.js +0 -116
  507. package/dist/src/utils.test.js +0 -155
  508. package/dist/src/validate.test.js +0 -90
  509. package/dist/src/weixin-download.test.js +0 -45
@@ -1,313 +0,0 @@
1
- /**
2
- * Tests for dom-snapshot.ts: DOM snapshot engine.
3
- *
4
- * Since the engine generates JavaScript strings for in-page evaluation,
5
- * these tests validate:
6
- * 1. The generated code is syntactically valid JS
7
- * 2. Options are correctly embedded
8
- * 3. The output structure matches expected format
9
- * 4. All features are present (Shadow DOM, iframe, table, diff, etc.)
10
- */
11
- import { describe, it, expect } from 'vitest';
12
- import { generateSnapshotJs, scrollToRefJs, getFormStateJs } from './dom-snapshot.js';
13
- describe('generateSnapshotJs', () => {
14
- it('returns a non-empty string', () => {
15
- const js = generateSnapshotJs();
16
- expect(typeof js).toBe('string');
17
- expect(js.length).toBeGreaterThan(100);
18
- });
19
- it('generates syntactically valid JS (can be parsed)', () => {
20
- const js = generateSnapshotJs();
21
- expect(() => new Function(js)).not.toThrow();
22
- });
23
- it('embeds default options correctly', () => {
24
- const js = generateSnapshotJs();
25
- expect(js).toContain('VIEWPORT_EXPAND = 800');
26
- expect(js).toContain('MAX_DEPTH = 50');
27
- expect(js).toContain('INTERACTIVE_ONLY = false');
28
- expect(js).toContain('MAX_TEXT_LEN = 120');
29
- expect(js).toContain('INCLUDE_SCROLL_INFO = true');
30
- expect(js).toContain('BBOX_DEDUP = true');
31
- expect(js).toContain('INCLUDE_SHADOW_DOM = true');
32
- expect(js).toContain('INCLUDE_IFRAMES = true');
33
- expect(js).toContain('PAINT_ORDER_CHECK = true');
34
- expect(js).toContain('ANNOTATE_REFS = true');
35
- expect(js).toContain('REPORT_HIDDEN = true');
36
- expect(js).toContain('FILTER_ADS = true');
37
- expect(js).toContain('MARKDOWN_TABLES = true');
38
- expect(js).toContain('PREV_HASHES = null');
39
- });
40
- it('embeds custom options correctly', () => {
41
- const js = generateSnapshotJs({
42
- viewportExpand: 2000,
43
- maxDepth: 30,
44
- interactiveOnly: true,
45
- maxTextLength: 200,
46
- includeScrollInfo: false,
47
- bboxDedup: false,
48
- includeShadowDom: false,
49
- includeIframes: false,
50
- maxIframes: 3,
51
- paintOrderCheck: false,
52
- annotateRefs: false,
53
- reportHidden: false,
54
- filterAds: false,
55
- markdownTables: false,
56
- });
57
- expect(js).toContain('VIEWPORT_EXPAND = 2000');
58
- expect(js).toContain('MAX_DEPTH = 30');
59
- expect(js).toContain('INTERACTIVE_ONLY = true');
60
- expect(js).toContain('MAX_TEXT_LEN = 200');
61
- expect(js).toContain('INCLUDE_SCROLL_INFO = false');
62
- expect(js).toContain('BBOX_DEDUP = false');
63
- expect(js).toContain('INCLUDE_SHADOW_DOM = false');
64
- expect(js).toContain('INCLUDE_IFRAMES = false');
65
- expect(js).toContain('MAX_IFRAMES = 3');
66
- expect(js).toContain('PAINT_ORDER_CHECK = false');
67
- expect(js).toContain('ANNOTATE_REFS = false');
68
- expect(js).toContain('REPORT_HIDDEN = false');
69
- expect(js).toContain('FILTER_ADS = false');
70
- expect(js).toContain('MARKDOWN_TABLES = false');
71
- });
72
- it('clamps maxDepth between 1 and 200', () => {
73
- expect(generateSnapshotJs({ maxDepth: -5 })).toContain('MAX_DEPTH = 1');
74
- expect(generateSnapshotJs({ maxDepth: 999 })).toContain('MAX_DEPTH = 200');
75
- expect(generateSnapshotJs({ maxDepth: 75 })).toContain('MAX_DEPTH = 75');
76
- });
77
- it('wraps output as an IIFE', () => {
78
- const js = generateSnapshotJs();
79
- expect(js.startsWith('(() =>')).toBe(true);
80
- expect(js.trimEnd().endsWith(')()')).toBe(true);
81
- });
82
- it('embeds previousHashes for incremental diff', () => {
83
- const hashes = JSON.stringify(['12345', '67890']);
84
- const js = generateSnapshotJs({ previousHashes: hashes });
85
- expect(js).toContain('new Set(["12345","67890"])');
86
- });
87
- it('includes all core features in generated code', () => {
88
- const js = generateSnapshotJs();
89
- // Tag filtering
90
- expect(js).toContain('SKIP_TAGS');
91
- expect(js).toContain("'script'");
92
- expect(js).toContain("'style'");
93
- // SVG collapsing
94
- expect(js).toContain('SVG_CHILDREN');
95
- // Interactive detection
96
- expect(js).toContain('INTERACTIVE_TAGS');
97
- expect(js).toContain('INTERACTIVE_ROLES');
98
- expect(js).toContain('isInteractive');
99
- // Visibility
100
- expect(js).toContain('isVisibleByCSS');
101
- expect(js).toContain('isInExpandedViewport');
102
- // BBox dedup
103
- expect(js).toContain('isContainedBy');
104
- expect(js).toContain('PROPAGATING_TAGS');
105
- expect(js).toContain('PROPAGATING_ROLES');
106
- expect(js).toContain('isBboxPropagator');
107
- expect(js).toContain('isDistinctivelyInteractive');
108
- // Shadow DOM
109
- expect(js).toContain('shadowRoot');
110
- expect(js).toContain('|shadow|');
111
- // iframe
112
- expect(js).toContain('walkIframe');
113
- expect(js).toContain('|iframe|');
114
- // Paint order
115
- expect(js).toContain('isOccludedByOverlay');
116
- expect(js).toContain('elementFromPoint');
117
- // Ad filtering
118
- expect(js).toContain('isAdElement');
119
- expect(js).toContain('AD_PATTERNS');
120
- // data-ref annotation
121
- expect(js).toContain('data-bycli-ref');
122
- // Hidden elements report
123
- expect(js).toContain('hiddenInteractives');
124
- expect(js).toContain('hidden_interactive');
125
- // Incremental diff
126
- expect(js).toContain('hashElement');
127
- expect(js).toContain('currentHashes');
128
- expect(js).toContain('__bycli_prev_hashes');
129
- // Table serialization
130
- expect(js).toContain('serializeTable');
131
- expect(js).toContain('|table|');
132
- // Synthetic attributes
133
- expect(js).toContain("'YYYY-MM-DD'");
134
- expect(js).toContain('value=••••');
135
- // Page metadata
136
- expect(js).toContain('location.href');
137
- expect(js).toContain('document.title');
138
- });
139
- it('contains proper attribute whitelist', () => {
140
- const js = generateSnapshotJs();
141
- const expectedAttrs = [
142
- 'aria-label', 'aria-expanded', 'aria-checked', 'aria-selected',
143
- 'placeholder', 'href', 'role', 'data-testid', 'autocomplete',
144
- ];
145
- for (const attr of expectedAttrs) {
146
- expect(js).toContain(`'${attr}'`);
147
- }
148
- });
149
- it('includes scroll info formatting', () => {
150
- const js = generateSnapshotJs();
151
- expect(js).toContain('scrollHeight');
152
- expect(js).toContain('scrollTop');
153
- expect(js).toContain('|scroll|');
154
- expect(js).toContain('page_scroll');
155
- });
156
- });
157
- describe('BBox 99% containment filter', () => {
158
- it('propagates bbox for both PROPAGATING_TAGS and PROPAGATING_ROLES', () => {
159
- const js = generateSnapshotJs();
160
- // Role-based propagator list covers the common wrapper-as-control patterns
161
- // that show up as <div role=button><svg/><span/></div> on modern SPAs.
162
- for (const role of ['button', 'link', 'menuitem', 'tab', 'option']) {
163
- expect(js).toContain(`'${role}'`);
164
- }
165
- // propagate site uses the unified helper, not only the tag set
166
- expect(js).toContain('isBboxPropagator(el, tag)');
167
- });
168
- it('suppresses interactive descendants at 0.99 containment when they are not distinctive', () => {
169
- const js = generateSnapshotJs();
170
- expect(js).toContain('isContainedBy(rect, parentPropagatingRect, 0.99)');
171
- expect(js).toContain('!isDistinctivelyInteractive(el)');
172
- // The suppression path flips the local interactive flag so the node is
173
- // still emitted (for text / shape) but does not get its own [N] ref.
174
- expect(js).toContain('interactive = false');
175
- });
176
- it('does not suppress inputs / href-bearing anchors even when fully contained', () => {
177
- const js = generateSnapshotJs();
178
- // Guards inside isDistinctivelyInteractive
179
- expect(js).toContain("tag === 'input'");
180
- expect(js).toContain("tag === 'select'");
181
- expect(js).toContain("tag === 'textarea'");
182
- expect(js).toContain("tag === 'a'");
183
- expect(js).toContain("el.hasAttribute('href')");
184
- // aria-label / aria-labelledby / id / test-id / name preserve distinctness
185
- expect(js).toContain("el.hasAttribute('aria-label')");
186
- expect(js).toContain("el.hasAttribute('aria-labelledby')");
187
- expect(js).toContain("el.id");
188
- expect(js).toContain("el.getAttribute('data-testid')");
189
- expect(js).toContain("el.hasAttribute('name')");
190
- });
191
- it('keeps the existing 0.95 non-interactive dedup tier in place', () => {
192
- const js = generateSnapshotJs();
193
- // The original non-interactive bbox filter is still present alongside the
194
- // new interactive tier — two complementary thresholds, not a replacement.
195
- expect(js).toContain('isContainedBy(rect, parentPropagatingRect, 0.95)');
196
- });
197
- it('bbox containment branches are gated on BBOX_DEDUP flag', () => {
198
- const off = generateSnapshotJs({ bboxDedup: false });
199
- // When the option is off, the filter becomes inert (BBOX_DEDUP = false)
200
- // but the inlined helpers still ship — we only guard at the call sites.
201
- expect(off).toContain('BBOX_DEDUP = false');
202
- expect(off).toContain('isBboxPropagator');
203
- expect(off).toContain('isDistinctivelyInteractive');
204
- });
205
- });
206
- describe('scrollToRefJs', () => {
207
- it('generates valid JS', () => {
208
- const js = scrollToRefJs('42');
209
- expect(() => new Function(js)).not.toThrow();
210
- });
211
- it('targets data-bycli-ref', () => {
212
- const js = scrollToRefJs('7');
213
- expect(js).toContain('data-bycli-ref');
214
- expect(js).toContain('scrollIntoView');
215
- expect(js).toContain('"7"');
216
- });
217
- it('falls back to data-ref', () => {
218
- const js = scrollToRefJs('3');
219
- expect(js).toContain('data-ref');
220
- });
221
- it('returns scrolled info', () => {
222
- const js = scrollToRefJs('1');
223
- expect(js).toContain('scrolled: true');
224
- expect(js).toContain('tag:');
225
- });
226
- });
227
- describe('getFormStateJs', () => {
228
- it('generates valid JS', () => {
229
- const js = getFormStateJs();
230
- expect(() => new Function(js)).not.toThrow();
231
- });
232
- it('collects form elements', () => {
233
- const js = getFormStateJs();
234
- expect(js).toContain('document.forms');
235
- expect(js).toContain('form.elements');
236
- });
237
- it('collects orphan fields', () => {
238
- const js = getFormStateJs();
239
- expect(js).toContain('orphanFields');
240
- expect(js).toContain('el.form');
241
- });
242
- it('handles different input types', () => {
243
- const js = getFormStateJs();
244
- expect(js).toContain('checkbox');
245
- expect(js).toContain('radio');
246
- expect(js).toContain('password');
247
- expect(js).toContain('contenteditable');
248
- });
249
- it('extracts labels', () => {
250
- const js = getFormStateJs();
251
- expect(js).toContain('aria-label');
252
- expect(js).toContain('label[for=');
253
- expect(js).toContain('closest');
254
- expect(js).toContain('placeholder');
255
- });
256
- it('masks passwords', () => {
257
- const js = getFormStateJs();
258
- expect(js).toContain('••••');
259
- });
260
- it('includes data-bycli-ref in output', () => {
261
- const js = getFormStateJs();
262
- expect(js).toContain('data-bycli-ref');
263
- });
264
- });
265
- describe('Search Element Detection', () => {
266
- it('includes SEARCH_INDICATORS set', () => {
267
- const js = generateSnapshotJs();
268
- expect(js).toContain('SEARCH_INDICATORS');
269
- expect(js).toContain('search');
270
- expect(js).toContain('magnify');
271
- expect(js).toContain('glass');
272
- });
273
- it('includes hasFormControlDescendant function', () => {
274
- const js = generateSnapshotJs();
275
- expect(js).toContain('hasFormControlDescendant');
276
- expect(js).toContain('input');
277
- expect(js).toContain('select');
278
- expect(js).toContain('textarea');
279
- });
280
- it('includes isSearchElement function', () => {
281
- const js = generateSnapshotJs();
282
- expect(js).toContain('isSearchElement');
283
- expect(js).toContain('className');
284
- expect(js).toContain('data-');
285
- });
286
- it('checks label wrapper detection in isInteractive', () => {
287
- const js = generateSnapshotJs();
288
- // Label elements without "for" attribute should check for form control descendants
289
- expect(js).toContain('hasFormControlDescendant(el, 2)');
290
- });
291
- it('checks span wrapper detection in isInteractive', () => {
292
- const js = generateSnapshotJs();
293
- // Span elements should check for form control descendants
294
- expect(js).toContain("tag === 'span'");
295
- });
296
- it('integrates search element detection into isInteractive', () => {
297
- const js = generateSnapshotJs();
298
- expect(js).toContain('isSearchElement(el)');
299
- });
300
- // Blocker B regression: compound contract must be emitted by `browser state`,
301
- // not only by `browser find --css`. Otherwise agents inspecting the default
302
- // snapshot still have to round-trip `find` on every date/select/file control.
303
- it('inlines compoundInfoOf() and attaches compound info to each interactive ref', () => {
304
- const js = generateSnapshotJs();
305
- expect(js).toContain('function compoundInfoOf(el)');
306
- // Wiring: the walk body should call compoundInfoOf on every interactive node
307
- expect(js).toContain('compoundInfoOf(el)');
308
- // And collect them into a per-ref map keyed by the same [N] index as the tree
309
- expect(js).toContain('compoundInfos');
310
- // And emit a sidecar section after the tree so agents can find the JSON
311
- expect(js).toContain("'compounds ('");
312
- });
313
- });
@@ -1,60 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { classifyBrowserError, isTransientBrowserError } from './errors.js';
3
- describe('classifyBrowserError', () => {
4
- it('classifies extension transient errors with 1500ms delay', () => {
5
- for (const msg of [
6
- 'Extension disconnected',
7
- 'Extension not connected',
8
- 'attach failed',
9
- 'Detached while handling command',
10
- 'Debugger is not attached to the tab: 123',
11
- 'no longer exists',
12
- 'No tab with id: 456',
13
- 'CDP connection reset',
14
- 'Daemon command failed',
15
- 'No window with id: 123',
16
- ]) {
17
- const advice = classifyBrowserError(new Error(msg));
18
- expect(advice.kind, `expected "${msg}" → extension-transient`).toBe('extension-transient');
19
- expect(advice.retryable).toBe(true);
20
- expect(advice.delayMs).toBe(1500);
21
- }
22
- });
23
- it('classifies CDP target navigation errors with 200ms delay', () => {
24
- const advice = classifyBrowserError(new Error('Inspected target navigated or closed'));
25
- expect(advice.kind).toBe('target-navigation');
26
- expect(advice.retryable).toBe(true);
27
- expect(advice.delayMs).toBe(200);
28
- });
29
- it('classifies CDP -32000 target errors with 200ms delay', () => {
30
- const advice = classifyBrowserError(new Error('{"code":-32000,"message":"Target closed"}'));
31
- expect(advice.kind).toBe('target-navigation');
32
- expect(advice.retryable).toBe(true);
33
- expect(advice.delayMs).toBe(200);
34
- });
35
- it('classifies CDP -32000 execution-context errors with 200ms delay', () => {
36
- const advice = classifyBrowserError(new Error('{"code":-32000,"message":"Cannot find default execution context"}'));
37
- expect(advice.kind).toBe('target-navigation');
38
- expect(advice.retryable).toBe(true);
39
- expect(advice.delayMs).toBe(200);
40
- });
41
- it('returns non-retryable for unrelated errors', () => {
42
- for (const msg of ['Permission denied', 'malformed exec payload', 'SyntaxError']) {
43
- const advice = classifyBrowserError(new Error(msg));
44
- expect(advice.kind).toBe('non-retryable');
45
- expect(advice.retryable).toBe(false);
46
- }
47
- });
48
- it('handles non-Error values', () => {
49
- expect(classifyBrowserError('Extension disconnected').kind).toBe('extension-transient');
50
- expect(classifyBrowserError(42).kind).toBe('non-retryable');
51
- });
52
- });
53
- describe('isTransientBrowserError (convenience wrapper)', () => {
54
- it('returns true for transient errors', () => {
55
- expect(isTransientBrowserError(new Error('No window with id: 123'))).toBe(true);
56
- });
57
- it('returns false for non-transient errors', () => {
58
- expect(isTransientBrowserError(new Error('Permission denied'))).toBe(false);
59
- });
60
- });
@@ -1,129 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { buildExtractHtmlJs, chunkMarkdown, runExtractFromHtml } from './extract.js';
3
- describe('chunkMarkdown', () => {
4
- it('returns the full content when it fits in one chunk', () => {
5
- const content = 'short body';
6
- const r = chunkMarkdown({ content, start: 0, chunkSize: 20000 });
7
- expect(r.content).toBe(content);
8
- expect(r.start).toBe(0);
9
- expect(r.end).toBe(content.length);
10
- expect(r.nextStartChar).toBeNull();
11
- });
12
- it('emits next_start_char when more content remains', () => {
13
- // Build content long enough that chunkSize cuts it mid-stream.
14
- const para = 'p'.repeat(400);
15
- const content = [para, para, para].join('\n\n');
16
- const r = chunkMarkdown({ content, start: 0, chunkSize: 500 });
17
- expect(r.nextStartChar).not.toBeNull();
18
- expect(r.nextStartChar).toBeGreaterThan(0);
19
- expect(r.nextStartChar).toBeLessThan(content.length);
20
- });
21
- it('prefers to break at a paragraph boundary inside the boundary window', () => {
22
- // chunkSize=500, window=15% → [425, 500). Place `\n\n` at 450 so it lands
23
- // inside the window; the chunker should snap the cut back to it.
24
- const a = 'a'.repeat(450);
25
- const b = 'b'.repeat(400);
26
- const content = `${a}\n\n${b}`;
27
- const r = chunkMarkdown({ content, start: 0, chunkSize: 500 });
28
- expect(r.content.endsWith('\n\n')).toBe(true);
29
- expect(r.nextStartChar).toBe(r.end);
30
- expect(content.slice(r.end).startsWith('b')).toBe(true);
31
- });
32
- it('falls back to a single newline when no paragraph boundary is in window', () => {
33
- // 6 lines × 90 chars joined by `\n` → `\n` at 90, 181, 272, 363, 454.
34
- // chunkSize=500 with window [425, 500) catches the `\n` at 454.
35
- const line = 'l'.repeat(90);
36
- const content = Array.from({ length: 6 }, () => line).join('\n');
37
- const r = chunkMarkdown({ content, start: 0, chunkSize: 500 });
38
- expect(r.content.endsWith('\n')).toBe(true);
39
- expect(content.slice(r.end).startsWith('l')).toBe(true);
40
- });
41
- it('hard-cuts when no boundary is found within the window', () => {
42
- const content = 'x'.repeat(5000);
43
- const r = chunkMarkdown({ content, start: 0, chunkSize: 500 });
44
- expect(r.end).toBe(500);
45
- expect(r.content).toHaveLength(500);
46
- expect(r.nextStartChar).toBe(500);
47
- });
48
- it('handles start >= content.length with an empty final chunk', () => {
49
- const content = 'hello';
50
- const r = chunkMarkdown({ content, start: 5, chunkSize: 100 });
51
- expect(r.content).toBe('');
52
- expect(r.nextStartChar).toBeNull();
53
- });
54
- it('resumes from a provided start cursor until the stream terminates', () => {
55
- const content = `${'a'.repeat(100)}\n\n${'b'.repeat(100)}\n\n${'c'.repeat(100)}`;
56
- const first = chunkMarkdown({ content, start: 0, chunkSize: 110 });
57
- expect(first.nextStartChar).not.toBeNull();
58
- const second = chunkMarkdown({ content, start: first.nextStartChar, chunkSize: 110 });
59
- expect(second.start).toBe(first.nextStartChar);
60
- expect(second.content.length).toBeGreaterThan(0);
61
- let cursor = second.nextStartChar;
62
- let safety = 20;
63
- while (cursor !== null && safety-- > 0) {
64
- const step = chunkMarkdown({ content, start: cursor, chunkSize: 110 });
65
- cursor = step.nextStartChar;
66
- }
67
- expect(cursor).toBeNull();
68
- });
69
- it('clamps chunk size to the configured minimum', () => {
70
- const content = 'a'.repeat(2000);
71
- const r = chunkMarkdown({ content, start: 0, chunkSize: 1 });
72
- // MIN_CHUNK_SIZE is 100 — requesting 1 should still produce >= 100 chars.
73
- expect(r.end).toBeGreaterThanOrEqual(100);
74
- });
75
- });
76
- describe('runExtractFromHtml', () => {
77
- it('converts HTML to markdown and wraps it in the chunking envelope', () => {
78
- const html = '<article><h1>Title</h1><p>Hello <strong>world</strong>.</p></article>';
79
- const r = runExtractFromHtml({
80
- html,
81
- url: 'https://example.com/a',
82
- title: 'Example',
83
- selector: 'article',
84
- start: 0,
85
- chunkSize: 20000,
86
- });
87
- expect(r.url).toBe('https://example.com/a');
88
- expect(r.title).toBe('Example');
89
- expect(r.selector).toBe('article');
90
- expect(r.content).toContain('# Title');
91
- expect(r.content).toContain('**world**');
92
- expect(r.start).toBe(0);
93
- expect(r.end).toBe(r.content.length);
94
- expect(r.total_chars).toBe(r.content.length);
95
- expect(r.next_start_char).toBeNull();
96
- });
97
- it('reports total_chars and chunk_size against the final markdown', () => {
98
- const body = Array.from({ length: 30 }, (_, i) => `<p>paragraph ${i} ${'x'.repeat(200)}</p>`).join('');
99
- const r = runExtractFromHtml({
100
- html: `<main>${body}</main>`,
101
- url: 'https://example.com/b',
102
- title: 't',
103
- selector: 'main',
104
- start: 0,
105
- chunkSize: 500,
106
- });
107
- expect(r.total_chars).toBeGreaterThan(r.end);
108
- expect(r.chunk_size).toBe(r.end - r.start);
109
- expect(r.next_start_char).toBe(r.end);
110
- });
111
- });
112
- describe('buildExtractHtmlJs', () => {
113
- it('embeds the selector as a JSON literal', () => {
114
- const js = buildExtractHtmlJs('main.article');
115
- expect(js).toContain('"main.article"');
116
- });
117
- it('uses null when no selector given', () => {
118
- const js = buildExtractHtmlJs(null);
119
- // The expression references `sel` and compares to null.
120
- expect(js).toContain('const sel = null;');
121
- });
122
- it('includes the denoise selector list', () => {
123
- const js = buildExtractHtmlJs(null);
124
- expect(js).toContain("'script'");
125
- expect(js).toContain("'nav'");
126
- expect(js).toContain("'iframe'");
127
- expect(js).toContain("'[aria-hidden=\"true\"]'");
128
- });
129
- });