@sovovs/bycli 1.8.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (539) hide show
  1. package/cli-manifest.json +0 -61
  2. package/clis/twitter/search.js +3 -3
  3. package/dist/src/adapter-shadow.js +2 -2
  4. package/dist/src/browser/analyze.d.ts +10 -99
  5. package/dist/src/browser/analyze.js +10 -226
  6. package/dist/src/browser/cdp.js +67 -7
  7. package/dist/src/browser/daemon-client.d.ts +2 -0
  8. package/dist/src/browser/daemon-client.js +1 -1
  9. package/dist/src/browser/extension-capabilities.d.ts +13 -0
  10. package/dist/src/browser/extension-capabilities.js +22 -0
  11. package/dist/src/browser/extension-capabilities.test.d.ts +1 -0
  12. package/dist/src/browser/extension-version-metadata.test.d.ts +1 -0
  13. package/dist/src/browser/navigation-guard.d.ts +78 -0
  14. package/dist/src/browser/navigation-guard.js +142 -0
  15. package/dist/src/browser/navigation-guard.test.d.ts +1 -0
  16. package/dist/src/browser/page.d.ts +1 -0
  17. package/dist/src/browser/page.js +20 -1
  18. package/dist/src/browser/url-policy.d.ts +89 -0
  19. package/dist/src/browser/url-policy.js +311 -0
  20. package/dist/src/browser/url-policy.test.d.ts +1 -0
  21. package/dist/src/browser/verify-fixture.js +2 -2
  22. package/dist/src/build-manifest.js +4 -2
  23. package/dist/src/capabilityRouting.d.ts +3 -2
  24. package/dist/src/capabilityRouting.js +10 -2
  25. package/dist/src/cli.js +11 -14
  26. package/dist/src/commanderAdapter.js +5 -5
  27. package/dist/src/config-paths.d.ts +19 -0
  28. package/dist/src/config-paths.js +31 -0
  29. package/dist/src/daemon.js +256 -0
  30. package/dist/src/discovery.d.ts +10 -3
  31. package/dist/src/discovery.js +20 -10
  32. package/dist/src/discovery.test.d.ts +1 -0
  33. package/dist/src/execution.d.ts +5 -0
  34. package/dist/src/execution.js +272 -48
  35. package/dist/src/help.js +8 -8
  36. package/dist/src/main.js +18 -2
  37. package/dist/src/manifest-schema.d.ts +9 -0
  38. package/dist/src/manifest-schema.js +162 -0
  39. package/dist/src/manifest-schema.test.d.ts +1 -0
  40. package/dist/src/manifest-types.d.ts +1 -1
  41. package/dist/src/observation/redaction.js +10 -4
  42. package/dist/src/plugin.js +11 -8
  43. package/dist/src/recorder/highlevel/analyze.d.ts +29 -0
  44. package/dist/src/recorder/highlevel/analyze.js +91 -0
  45. package/dist/src/recorder/highlevel/init.d.ts +125 -0
  46. package/dist/src/recorder/highlevel/init.js +279 -0
  47. package/dist/src/recorder/highlevel/init.test.d.ts +1 -0
  48. package/dist/src/recorder/highlevel/verify.d.ts +73 -0
  49. package/dist/src/recorder/highlevel/verify.js +74 -0
  50. package/dist/src/recorder/http/analyze-runner.d.ts +28 -0
  51. package/dist/src/recorder/http/analyze-runner.js +78 -0
  52. package/dist/src/recorder/http/analyze-runner.test.d.ts +1 -0
  53. package/dist/src/recorder/http/handlers.d.ts +51 -0
  54. package/dist/src/recorder/http/handlers.js +219 -0
  55. package/dist/src/recorder/http/wrapper-config.d.ts +20 -0
  56. package/dist/src/recorder/http/wrapper-config.js +82 -0
  57. package/dist/src/recorder/http/wrapper-envelope.d.ts +31 -0
  58. package/dist/src/recorder/http/wrapper-envelope.js +51 -0
  59. package/dist/src/recorder/http/wrapper-gates.d.ts +16 -0
  60. package/dist/src/recorder/http/wrapper-gates.js +28 -0
  61. package/dist/src/recorder/http/wrapper-metrics.d.ts +1 -0
  62. package/dist/src/recorder/http/wrapper-metrics.js +5 -0
  63. package/dist/src/recorder/http/wrapper-registry.d.ts +50 -0
  64. package/dist/src/recorder/http/wrapper-registry.js +98 -0
  65. package/dist/src/recorder/http/wrapper-server.d.ts +59 -0
  66. package/dist/src/recorder/http/wrapper-server.js +240 -0
  67. package/dist/src/recorder/http/wrapper.test.d.ts +1 -0
  68. package/dist/src/recorder/observability/logger.d.ts +5 -0
  69. package/dist/src/recorder/observability/logger.js +13 -0
  70. package/dist/src/recorder/runner/config.d.ts +34 -0
  71. package/dist/src/recorder/runner/config.js +84 -0
  72. package/dist/src/recorder/runner/config.test.d.ts +1 -0
  73. package/dist/src/recorder/runner/reap.d.ts +79 -0
  74. package/dist/src/recorder/runner/reap.js +230 -0
  75. package/dist/src/recorder/runner/reap.test.d.ts +1 -0
  76. package/dist/src/recorder/runner/runner-port.d.ts +95 -0
  77. package/dist/src/recorder/runner/runner-port.js +518 -0
  78. package/dist/src/recorder/runner/runner-port.test.d.ts +1 -0
  79. package/dist/src/recorder/runner/session-keys.d.ts +28 -0
  80. package/dist/src/recorder/runner/session-keys.js +72 -0
  81. package/dist/src/recorder/runner/session-keys.test.d.ts +1 -0
  82. package/dist/src/recorder/runner/verify-runner-main.d.ts +96 -0
  83. package/dist/src/recorder/runner/verify-runner-main.js +292 -0
  84. package/dist/src/recorder/runner/verify-runner-main.test.d.ts +1 -0
  85. package/dist/src/registry-api.d.ts +1 -1
  86. package/dist/src/registry-api.types.test.d.ts +1 -0
  87. package/dist/src/registry-transaction.d.ts +42 -0
  88. package/dist/src/registry-transaction.js +194 -0
  89. package/dist/src/registry-transaction.test.d.ts +1 -0
  90. package/dist/src/registry.d.ts +58 -16
  91. package/dist/src/registry.js +131 -15
  92. package/dist/src/serialization.d.ts +1 -1
  93. package/dist/src/serialization.js +3 -3
  94. package/dist/src/types.d.ts +2 -0
  95. package/package.json +8 -5
  96. package/scripts/m1-daemon-navigate-drive.mjs +138 -0
  97. package/scripts/m1-extension-spike.mjs +237 -0
  98. package/scripts/m1-live-spike.mjs +156 -0
  99. package/scripts/m6b-connect-back-spike.sh +31 -0
  100. package/clis/12306/utils.test.js +0 -331
  101. package/clis/1688/assets.test.js +0 -39
  102. package/clis/1688/download.test.js +0 -31
  103. package/clis/1688/item.test.js +0 -67
  104. package/clis/1688/search.test.js +0 -75
  105. package/clis/1688/shared.test.js +0 -57
  106. package/clis/1688/store.test.js +0 -62
  107. package/clis/36kr/article.test.js +0 -46
  108. package/clis/36kr/hot.test.js +0 -15
  109. package/clis/36kr/news.test.js +0 -85
  110. package/clis/51job/utils.test.js +0 -69
  111. package/clis/_atlassian/shared.test.js +0 -170
  112. package/clis/aibase/news.test.js +0 -59
  113. package/clis/amazon/bestsellers.test.js +0 -29
  114. package/clis/amazon/discussion.test.js +0 -124
  115. package/clis/amazon/offer.test.js +0 -29
  116. package/clis/amazon/product.test.js +0 -24
  117. package/clis/amazon/rankings.test.js +0 -41
  118. package/clis/amazon/search.test.js +0 -22
  119. package/clis/amazon/shared.test.js +0 -44
  120. package/clis/apple-podcasts/commands.test.js +0 -119
  121. package/clis/apple-podcasts/utils.test.js +0 -57
  122. package/clis/arxiv/arxiv.test.js +0 -112
  123. package/clis/baidu-scholar/search.test.js +0 -23
  124. package/clis/barchart/greeks.test.js +0 -138
  125. package/clis/bilibili/comment.test.js +0 -153
  126. package/clis/bilibili/comments.test.js +0 -142
  127. package/clis/bilibili/dynamic.test.js +0 -68
  128. package/clis/bilibili/hot.test.js +0 -17
  129. package/clis/bilibili/subtitle.test.js +0 -196
  130. package/clis/bilibili/summary.test.js +0 -210
  131. package/clis/bilibili/utils.test.js +0 -61
  132. package/clis/bilibili/video.test.js +0 -132
  133. package/clis/binance/commands.test.js +0 -70
  134. package/clis/bloomberg/utils.test.js +0 -129
  135. package/clis/booking/booking.test.js +0 -356
  136. package/clis/boss/chatlist.test.js +0 -211
  137. package/clis/boss/chatmsg.test.js +0 -230
  138. package/clis/boss/search.test.js +0 -78
  139. package/clis/boss/utils.test.js +0 -34
  140. package/clis/brave/search.test.js +0 -76
  141. package/clis/chaoxing/utils.test.js +0 -45
  142. package/clis/chatgpt/commands.test.js +0 -45
  143. package/clis/chatgpt/envelope.test.js +0 -108
  144. package/clis/chatgpt/image.test.js +0 -188
  145. package/clis/chatgpt/utils.test.js +0 -330
  146. package/clis/chatgpt-app/ax.test.js +0 -35
  147. package/clis/chatwise/composer.test.js +0 -186
  148. package/clis/chess/analyze.test.js +0 -79
  149. package/clis/chess/game.test.js +0 -178
  150. package/clis/chess/games.test.js +0 -164
  151. package/clis/chess/stats.test.js +0 -79
  152. package/clis/chess/utils.test.js +0 -230
  153. package/clis/claude/ask.test.js +0 -338
  154. package/clis/claude/commands.test.js +0 -118
  155. package/clis/claude/utils.test.js +0 -148
  156. package/clis/cnki/search.test.js +0 -18
  157. package/clis/codex/sidebar.test.js +0 -329
  158. package/clis/coingecko/coingecko.test.js +0 -109
  159. package/clis/confluence/commands.test.js +0 -195
  160. package/clis/coupang/coupang.test.js +0 -159
  161. package/clis/coupang/utils.test.js +0 -62
  162. package/clis/ctrip/ctrip.test.js +0 -719
  163. package/clis/dblp/dblp.test.js +0 -397
  164. package/clis/deepseek/ask.test.js +0 -312
  165. package/clis/deepseek/detail.test.js +0 -81
  166. package/clis/deepseek/send.test.js +0 -107
  167. package/clis/deepseek/utils.test.js +0 -370
  168. package/clis/defillama/defillama.test.js +0 -99
  169. package/clis/devto/devto.test.js +0 -236
  170. package/clis/dianping/dianping.test.js +0 -578
  171. package/clis/douban/download.test.js +0 -170
  172. package/clis/douban/movie-hot.test.js +0 -14
  173. package/clis/douban/search.test.js +0 -11
  174. package/clis/douban/subject.test.js +0 -11
  175. package/clis/douban/utils.test.js +0 -438
  176. package/clis/doubao/detail.test.js +0 -42
  177. package/clis/doubao/history.test.js +0 -37
  178. package/clis/doubao/utils.test.js +0 -344
  179. package/clis/douyin/_shared/browser-fetch.test.js +0 -64
  180. package/clis/douyin/_shared/creation-id.test.js +0 -22
  181. package/clis/douyin/_shared/imagex-upload.test.js +0 -87
  182. package/clis/douyin/_shared/sts2.test.js +0 -27
  183. package/clis/douyin/_shared/text-extra.test.js +0 -37
  184. package/clis/douyin/_shared/timing.test.js +0 -28
  185. package/clis/douyin/_shared/tos-upload-short-read.test.js +0 -83
  186. package/clis/douyin/_shared/tos-upload.test.js +0 -229
  187. package/clis/douyin/_shared/transcode.test.js +0 -91
  188. package/clis/douyin/_shared/vod-upload.test.js +0 -38
  189. package/clis/douyin/activities.test.js +0 -55
  190. package/clis/douyin/collections.test.js +0 -45
  191. package/clis/douyin/delete.test.js +0 -100
  192. package/clis/douyin/draft.test.js +0 -335
  193. package/clis/douyin/drafts.test.js +0 -11
  194. package/clis/douyin/hashtag.test.js +0 -171
  195. package/clis/douyin/location.test.js +0 -23
  196. package/clis/douyin/profile.test.js +0 -46
  197. package/clis/douyin/publish-upload-id.test.js +0 -170
  198. package/clis/douyin/publish.test.js +0 -38
  199. package/clis/douyin/stats.test.js +0 -22
  200. package/clis/douyin/update.test.js +0 -11
  201. package/clis/douyin/user-videos.test.js +0 -151
  202. package/clis/douyin/videos.test.js +0 -54
  203. package/clis/duckduckgo/search.test.js +0 -128
  204. package/clis/duckduckgo/suggest.test.js +0 -66
  205. package/clis/eastmoney/hot-rank.test.js +0 -59
  206. package/clis/endoflife/endoflife.test.js +0 -51
  207. package/clis/facebook/feed.test.js +0 -169
  208. package/clis/facebook/marketplace.test.js +0 -91
  209. package/clis/facebook/notifications.test.js +0 -458
  210. package/clis/facebook/search.test.js +0 -55
  211. package/clis/flathub/flathub.test.js +0 -90
  212. package/clis/flomo/memos.test.js +0 -144
  213. package/clis/gemini/ask.test.js +0 -100
  214. package/clis/gemini/deep-research-result.test.js +0 -155
  215. package/clis/gemini/deep-research.test.js +0 -181
  216. package/clis/gemini/reply-state.test.js +0 -671
  217. package/clis/gemini/utils.test.js +0 -198
  218. package/clis/geogebra/geogebra.test.js +0 -175
  219. package/clis/gitee/search.test.js +0 -65
  220. package/clis/gitee/user.test.js +0 -63
  221. package/clis/google/utils.test.js +0 -75
  222. package/clis/google-scholar/cite.test.js +0 -47
  223. package/clis/google-scholar/profile.test.js +0 -49
  224. package/clis/google-scholar/search.test.js +0 -71
  225. package/clis/goproxy/goproxy.test.js +0 -103
  226. package/clis/gov-law/commands.test.js +0 -39
  227. package/clis/gov-policy/gov-policy.test.js +0 -224
  228. package/clis/grok/ask.test.js +0 -29
  229. package/clis/grok/utils.test.js +0 -103
  230. package/clis/hackernews/hackernews.test.js +0 -132
  231. package/clis/hf/hf.test.js +0 -16
  232. package/clis/hupu/hot.test.js +0 -224
  233. package/clis/imdb/utils.test.js +0 -88
  234. package/clis/indeed/indeed.test.js +0 -375
  235. package/clis/instagram/_shared/private-publish.test.js +0 -705
  236. package/clis/instagram/_shared/protocol-capture.test.js +0 -114
  237. package/clis/instagram/download.test.js +0 -118
  238. package/clis/instagram/note.test.js +0 -53
  239. package/clis/instagram/post.test.js +0 -1647
  240. package/clis/instagram/reel.test.js +0 -167
  241. package/clis/instagram/story.test.js +0 -134
  242. package/clis/jd/commands.test.js +0 -41
  243. package/clis/jd/item.test.js +0 -354
  244. package/clis/jianyu/search.test.js +0 -153
  245. package/clis/jianyu/shared/procurement-contract.test.js +0 -72
  246. package/clis/jianyu/shared/procurement-detail.test.js +0 -84
  247. package/clis/jike/read.test.js +0 -86
  248. package/clis/jira/commands.test.js +0 -287
  249. package/clis/juejin/search.js +0 -123
  250. package/clis/juejin/search.test.js +0 -98
  251. package/clis/lesswrong/frontpage.test.js +0 -37
  252. package/clis/lichess/lichess.test.js +0 -85
  253. package/clis/linkedin/connect.test.js +0 -213
  254. package/clis/linkedin/inbox.test.js +0 -152
  255. package/clis/linkedin/job-detail.test.js +0 -38
  256. package/clis/linkedin/jobs-preferences.test.js +0 -43
  257. package/clis/linkedin/people-search.test.js +0 -216
  258. package/clis/linkedin/post-analytics.test.js +0 -40
  259. package/clis/linkedin/posts.test.js +0 -40
  260. package/clis/linkedin/profile-analytics.test.js +0 -67
  261. package/clis/linkedin/profile-experience.test.js +0 -152
  262. package/clis/linkedin/profile-projects.test.js +0 -111
  263. package/clis/linkedin/profile-read.test.js +0 -77
  264. package/clis/linkedin/safe-send.test.js +0 -204
  265. package/clis/linkedin/salesnav-inbox.test.js +0 -113
  266. package/clis/linkedin/salesnav-message.test.js +0 -172
  267. package/clis/linkedin/salesnav-search.test.js +0 -76
  268. package/clis/linkedin/salesnav-thread.test.js +0 -79
  269. package/clis/linkedin/search.test.js +0 -222
  270. package/clis/linkedin/sent-invitations.test.js +0 -62
  271. package/clis/linkedin/services-read.test.js +0 -105
  272. package/clis/linkedin/thread-snapshot.test.js +0 -89
  273. package/clis/linkedin/timeline.test.js +0 -81
  274. package/clis/linkedin-learning/course.test.js +0 -114
  275. package/clis/linkedin-learning/search.test.js +0 -144
  276. package/clis/linkedin-learning/trending.test.js +0 -123
  277. package/clis/linux-do/feed.test.js +0 -153
  278. package/clis/linux-do/topic-content.test.js +0 -59
  279. package/clis/lobsters/lobsters.test.js +0 -169
  280. package/clis/notebooklm/add-source.test.js +0 -97
  281. package/clis/notebooklm/compat.test.js +0 -16
  282. package/clis/notebooklm/create.test.js +0 -58
  283. package/clis/notebooklm/generate-audio.test.js +0 -63
  284. package/clis/notebooklm/generate-slides.test.js +0 -75
  285. package/clis/notebooklm/history.test.js +0 -58
  286. package/clis/notebooklm/note-list.test.js +0 -56
  287. package/clis/notebooklm/notes-get.test.js +0 -72
  288. package/clis/notebooklm/open.test.js +0 -63
  289. package/clis/notebooklm/rpc.test.js +0 -131
  290. package/clis/notebooklm/source-fulltext.test.js +0 -106
  291. package/clis/notebooklm/source-get.test.js +0 -84
  292. package/clis/notebooklm/source-guide.test.js +0 -104
  293. package/clis/notebooklm/summary.test.js +0 -78
  294. package/clis/notebooklm/utils.test.js +0 -449
  295. package/clis/notebooklm/write-note.test.js +0 -70
  296. package/clis/nuget/nuget.test.js +0 -111
  297. package/clis/oeis/oeis.test.js +0 -88
  298. package/clis/ones/task-helpers.test.js +0 -12
  299. package/clis/ones/worklog.test.js +0 -20
  300. package/clis/openfda/openfda.test.js +0 -114
  301. package/clis/openreview/openreview.test.js +0 -427
  302. package/clis/osv/osv.test.js +0 -97
  303. package/clis/paperreview/commands.test.js +0 -243
  304. package/clis/paperreview/utils.test.js +0 -49
  305. package/clis/pixiv/download.test.js +0 -87
  306. package/clis/pixiv/illusts.test.js +0 -99
  307. package/clis/pixiv/search.test.js +0 -83
  308. package/clis/powerchina/search.test.js +0 -93
  309. package/clis/producthunt/utils.test.js +0 -64
  310. package/clis/pubmed/pubmed.test.js +0 -276
  311. package/clis/quark/utils.test.js +0 -58
  312. package/clis/qwen/utils.test.js +0 -45
  313. package/clis/reddit/extract-media.test.js +0 -149
  314. package/clis/reddit/frontpage.test.js +0 -34
  315. package/clis/reddit/home.test.js +0 -170
  316. package/clis/reddit/hot.test.js +0 -32
  317. package/clis/reddit/popular.test.js +0 -26
  318. package/clis/reddit/read.test.js +0 -335
  319. package/clis/reddit/reply.test.js +0 -89
  320. package/clis/reddit/search.test.js +0 -26
  321. package/clis/reddit/subreddit-info.test.js +0 -163
  322. package/clis/reddit/subreddit.test.js +0 -31
  323. package/clis/reddit/subscribed.test.js +0 -168
  324. package/clis/reddit/whoami.test.js +0 -105
  325. package/clis/rednote/navigation.test.js +0 -26
  326. package/clis/rednote/rednote.test.js +0 -222
  327. package/clis/rest-countries/rest-countries.test.js +0 -83
  328. package/clis/reuters/reuters.test.js +0 -299
  329. package/clis/rfc/rfc.test.js +0 -74
  330. package/clis/sinafinance/stock.test.js +0 -59
  331. package/clis/spotify/utils.test.js +0 -67
  332. package/clis/stackoverflow/stackoverflow.test.js +0 -404
  333. package/clis/steam/steam.test.js +0 -46
  334. package/clis/substack/utils.test.js +0 -44
  335. package/clis/suno/commands.test.js +0 -188
  336. package/clis/suno/download.test.js +0 -151
  337. package/clis/suno/generate.test.js +0 -252
  338. package/clis/suno/utils.test.js +0 -329
  339. package/clis/taobao/commands.test.js +0 -41
  340. package/clis/tdx/hot-rank.test.js +0 -59
  341. package/clis/ths/hot-rank.test.js +0 -64
  342. package/clis/tieba/commands.test.js +0 -79
  343. package/clis/tieba/utils.test.js +0 -290
  344. package/clis/tiktok/creator-videos.test.js +0 -113
  345. package/clis/tiktok/refactor.test.js +0 -389
  346. package/clis/tiktok/write-refactor.test.js +0 -370
  347. package/clis/toutiao/toutiao.test.js +0 -378
  348. package/clis/tvmaze/tvmaze.test.js +0 -93
  349. package/clis/twitter/bookmark-folder.test.js +0 -395
  350. package/clis/twitter/bookmark-folders.test.js +0 -152
  351. package/clis/twitter/bookmark.test.js +0 -74
  352. package/clis/twitter/bookmarks.test.js +0 -205
  353. package/clis/twitter/delete.test.js +0 -85
  354. package/clis/twitter/device-follow.test.js +0 -287
  355. package/clis/twitter/download.test.js +0 -457
  356. package/clis/twitter/followers.test.js +0 -62
  357. package/clis/twitter/following.test.js +0 -338
  358. package/clis/twitter/hide-reply.test.js +0 -76
  359. package/clis/twitter/like.test.js +0 -73
  360. package/clis/twitter/likes.test.js +0 -220
  361. package/clis/twitter/list-add.test.js +0 -133
  362. package/clis/twitter/list-create.test.js +0 -169
  363. package/clis/twitter/list-remove.test.js +0 -110
  364. package/clis/twitter/list-tweets.test.js +0 -196
  365. package/clis/twitter/lists.test.js +0 -253
  366. package/clis/twitter/post.test.js +0 -258
  367. package/clis/twitter/profile.test.js +0 -39
  368. package/clis/twitter/quote.test.js +0 -194
  369. package/clis/twitter/reply.test.js +0 -237
  370. package/clis/twitter/retweet.test.js +0 -73
  371. package/clis/twitter/search.test.js +0 -349
  372. package/clis/twitter/shared.test.js +0 -794
  373. package/clis/twitter/thread.test.js +0 -58
  374. package/clis/twitter/timeline.test.js +0 -104
  375. package/clis/twitter/trending.test.js +0 -15
  376. package/clis/twitter/tweets.test.js +0 -362
  377. package/clis/twitter/unbookmark.test.js +0 -73
  378. package/clis/twitter/unlike.test.js +0 -75
  379. package/clis/twitter/unretweet.test.js +0 -73
  380. package/clis/twitter/utils.test.js +0 -169
  381. package/clis/uisdc/news.test.js +0 -66
  382. package/clis/uiverse/_shared.test.js +0 -62
  383. package/clis/uiverse/navigation.test.js +0 -12
  384. package/clis/upwork/upwork.test.js +0 -566
  385. package/clis/wanfang/search.test.js +0 -23
  386. package/clis/web/read.test.js +0 -392
  387. package/clis/weibo/delete.test.js +0 -94
  388. package/clis/weibo/envelope.test.js +0 -85
  389. package/clis/weibo/favorites.test.js +0 -114
  390. package/clis/weibo/publish.test.js +0 -192
  391. package/clis/weibo/user-posts.test.js +0 -92
  392. package/clis/weibo/utils.test.js +0 -36
  393. package/clis/weixin/drafts.test.js +0 -69
  394. package/clis/weixin/search.test.js +0 -227
  395. package/clis/weread/ai-outline.test.js +0 -83
  396. package/clis/weread/book-search.test.js +0 -242
  397. package/clis/weread/commands.test.js +0 -398
  398. package/clis/weread/private-api-regression.test.js +0 -369
  399. package/clis/weread/search-regression.test.js +0 -494
  400. package/clis/weread/utils.test.js +0 -128
  401. package/clis/weread-official/commands.test.js +0 -385
  402. package/clis/weread-official/utils.test.js +0 -242
  403. package/clis/wikidata/wikidata.test.js +0 -83
  404. package/clis/wikipedia/trending.test.js +0 -57
  405. package/clis/wttr/wttr.test.js +0 -84
  406. package/clis/xianyu/chat.test.js +0 -84
  407. package/clis/xianyu/im.test.js +0 -253
  408. package/clis/xianyu/item.test.js +0 -56
  409. package/clis/xianyu/publish.test.js +0 -220
  410. package/clis/xianyu/search.test.js +0 -17
  411. package/clis/xiaoe/xiaoe.test.js +0 -486
  412. package/clis/xiaohongshu/comments.test.js +0 -258
  413. package/clis/xiaohongshu/creator-note-detail.test.js +0 -451
  414. package/clis/xiaohongshu/creator-notes-summary.test.js +0 -94
  415. package/clis/xiaohongshu/creator-notes.test.js +0 -281
  416. package/clis/xiaohongshu/creator-stats.test.js +0 -24
  417. package/clis/xiaohongshu/delete-note.test.js +0 -172
  418. package/clis/xiaohongshu/download.test.js +0 -316
  419. package/clis/xiaohongshu/navigation.test.js +0 -34
  420. package/clis/xiaohongshu/note.test.js +0 -249
  421. package/clis/xiaohongshu/publish.test.js +0 -608
  422. package/clis/xiaohongshu/search.test.js +0 -325
  423. package/clis/xiaohongshu/user-helpers.test.js +0 -160
  424. package/clis/xiaoyuzhou/auth.test.js +0 -124
  425. package/clis/xiaoyuzhou/download.test.js +0 -135
  426. package/clis/xiaoyuzhou/podcast-episodes.test.js +0 -78
  427. package/clis/xiaoyuzhou/transcript.test.js +0 -195
  428. package/clis/xiaoyuzhou/utils.test.js +0 -39
  429. package/clis/xueqiu/comments.test.js +0 -696
  430. package/clis/xueqiu/danjuan-utils.test.js +0 -41
  431. package/clis/xueqiu/utils.test.js +0 -26
  432. package/clis/yahoo/search.test.js +0 -94
  433. package/clis/youdao/note.test.js +0 -99
  434. package/clis/youtube/channel.test.js +0 -59
  435. package/clis/youtube/feed.test.js +0 -131
  436. package/clis/youtube/transcript-group.test.js +0 -99
  437. package/clis/youtube/transcript.test.js +0 -296
  438. package/clis/youtube/utils.test.js +0 -84
  439. package/clis/yuanbao/ask.test.js +0 -124
  440. package/clis/yuanbao/new.test.js +0 -30
  441. package/clis/yuanbao/shared.test.js +0 -80
  442. package/clis/zhihu/answer-comments.test.js +0 -287
  443. package/clis/zhihu/answer-detail.test.js +0 -338
  444. package/clis/zhihu/answer.test.js +0 -54
  445. package/clis/zhihu/collection.test.js +0 -337
  446. package/clis/zhihu/collections.test.js +0 -182
  447. package/clis/zhihu/comment.test.js +0 -50
  448. package/clis/zhihu/download.test.js +0 -12
  449. package/clis/zhihu/favorite.test.js +0 -59
  450. package/clis/zhihu/follow.test.js +0 -42
  451. package/clis/zhihu/like.test.js +0 -41
  452. package/clis/zhihu/question.test.js +0 -251
  453. package/clis/zhihu/recommend.test.js +0 -143
  454. package/clis/zhihu/search.test.js +0 -198
  455. package/clis/zhihu/target.test.js +0 -77
  456. package/clis/zhihu/text.test.js +0 -24
  457. package/clis/zhihu/write-shared.test.js +0 -176
  458. package/clis/zlibrary/commands.test.js +0 -65
  459. package/clis/zsxq/search.test.js +0 -24
  460. package/clis/zsxq/topic.test.js +0 -30
  461. package/clis/zsxq/topics.test.js +0 -24
  462. package/clis/zsxq/utils.test.js +0 -31
  463. package/dist/src/adapter-shadow.test.js +0 -49
  464. package/dist/src/adapter-source.test.js +0 -29
  465. package/dist/src/browser/analyze.test.js +0 -166
  466. package/dist/src/browser/article-extract.e2e.test.js +0 -105
  467. package/dist/src/browser/article-extract.test.js +0 -94
  468. package/dist/src/browser/ax-snapshot.test.js +0 -91
  469. package/dist/src/browser/base-page.test.js +0 -758
  470. package/dist/src/browser/cdp-click-fixture.test.js +0 -87
  471. package/dist/src/browser/cdp.test.js +0 -79
  472. package/dist/src/browser/compound.test.js +0 -175
  473. package/dist/src/browser/daemon-client.test.js +0 -199
  474. package/dist/src/browser/dom-helpers.test.js +0 -106
  475. package/dist/src/browser/dom-snapshot.test.js +0 -313
  476. package/dist/src/browser/errors.test.js +0 -60
  477. package/dist/src/browser/extract.test.js +0 -129
  478. package/dist/src/browser/find.test.js +0 -180
  479. package/dist/src/browser/html-tree.test.js +0 -181
  480. package/dist/src/browser/network-cache.test.js +0 -58
  481. package/dist/src/browser/network-key.test.js +0 -49
  482. package/dist/src/browser/page.test.js +0 -378
  483. package/dist/src/browser/shape-filter.test.js +0 -101
  484. package/dist/src/browser/shape.test.js +0 -82
  485. package/dist/src/browser/stealth.test.js +0 -134
  486. package/dist/src/browser/target-errors.test.js +0 -94
  487. package/dist/src/browser/target-resolver.test.js +0 -118
  488. package/dist/src/browser/utils.test.js +0 -29
  489. package/dist/src/browser/verify-fixture.test.js +0 -219
  490. package/dist/src/browser.test.js +0 -232
  491. package/dist/src/build-manifest.test.js +0 -341
  492. package/dist/src/capabilityRouting.test.js +0 -63
  493. package/dist/src/cli-argv-preprocess.test.js +0 -209
  494. package/dist/src/cli.test.js +0 -2803
  495. package/dist/src/commanderAdapter.test.js +0 -352
  496. package/dist/src/commands/daemon.test.js +0 -219
  497. package/dist/src/completion.test.js +0 -24
  498. package/dist/src/convention-audit.test.js +0 -247
  499. package/dist/src/daemon.test.js +0 -60
  500. package/dist/src/doctor.test.js +0 -263
  501. package/dist/src/download/article-download.test.js +0 -235
  502. package/dist/src/download/index.test.js +0 -140
  503. package/dist/src/download/media-download.test.js +0 -112
  504. package/dist/src/download/progress.test.js +0 -36
  505. package/dist/src/electron-apps.test.js +0 -49
  506. package/dist/src/engine.test.js +0 -312
  507. package/dist/src/errors.test.js +0 -109
  508. package/dist/src/execution.test.js +0 -623
  509. package/dist/src/extension-manifest-regression.test.js +0 -12
  510. package/dist/src/external.test.js +0 -146
  511. package/dist/src/help.test.js +0 -58
  512. package/dist/src/hooks.test.js +0 -92
  513. package/dist/src/interceptor.test.js +0 -81
  514. package/dist/src/launcher.test.js +0 -138
  515. package/dist/src/node-network.test.js +0 -55
  516. package/dist/src/observation/artifact.test.js +0 -121
  517. package/dist/src/observation/manager.test.js +0 -13
  518. package/dist/src/observation/redaction.test.js +0 -32
  519. package/dist/src/observation/retention.test.js +0 -118
  520. package/dist/src/observation/ring-buffer.test.js +0 -22
  521. package/dist/src/output.test.js +0 -53
  522. package/dist/src/package-exports.test.js +0 -112
  523. package/dist/src/pipeline/executor.test.js +0 -182
  524. package/dist/src/pipeline/steps/download.test.js +0 -102
  525. package/dist/src/pipeline/steps/fetch.test.js +0 -117
  526. package/dist/src/pipeline/template.test.js +0 -175
  527. package/dist/src/pipeline/transform.test.js +0 -133
  528. package/dist/src/plugin-manifest.test.js +0 -179
  529. package/dist/src/plugin-scaffold.test.js +0 -83
  530. package/dist/src/plugin.test.js +0 -1324
  531. package/dist/src/registry.test.js +0 -209
  532. package/dist/src/runtime-detect.test.js +0 -39
  533. package/dist/src/serialization.test.js +0 -78
  534. package/dist/src/snapshotFormatter.test.js +0 -521
  535. package/dist/src/tui.test.js +0 -19
  536. package/dist/src/update-check.test.js +0 -116
  537. package/dist/src/utils.test.js +0 -155
  538. package/dist/src/validate.test.js +0 -90
  539. package/dist/src/weixin-download.test.js +0 -45
@@ -1,134 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { generateStealthJs } from './stealth.js';
3
- /**
4
- * Tests for the stealth anti-detection module.
5
- *
6
- * We test the generated JS string for expected content and structure.
7
- * Evaluating in Node is fragile because stealth patches target browser
8
- * globals (navigator, Performance, HTMLIFrameElement) that don't exist
9
- * or behave differently in Node. Instead we verify the code string
10
- * contains the right patches and is syntactically valid.
11
- */
12
- describe('generateStealthJs', () => {
13
- it('returns a non-empty string', () => {
14
- const code = generateStealthJs();
15
- expect(typeof code).toBe('string');
16
- expect(code.length).toBeGreaterThan(0);
17
- });
18
- it('is a valid self-contained IIFE', () => {
19
- const code = generateStealthJs();
20
- // Should start/end as an IIFE
21
- expect(code.trim()).toMatch(/^\(\(\) => \{/);
22
- expect(code.trim()).toMatch(/\}\)\(\)$/);
23
- });
24
- it('patches navigator.webdriver', () => {
25
- const code = generateStealthJs();
26
- expect(code).toContain("navigator, 'webdriver'");
27
- expect(code).toContain('() => false');
28
- });
29
- it('stubs window.chrome', () => {
30
- const code = generateStealthJs();
31
- expect(code).toContain('window.chrome');
32
- expect(code).toContain('runtime');
33
- expect(code).toContain('loadTimes');
34
- expect(code).toContain('csi');
35
- });
36
- it('fakes navigator.plugins if empty', () => {
37
- const code = generateStealthJs();
38
- expect(code).toContain('navigator.plugins');
39
- expect(code).toContain('PDF Viewer');
40
- expect(code).toContain('Chrome PDF Viewer');
41
- });
42
- it('ensures navigator.languages is non-empty', () => {
43
- const code = generateStealthJs();
44
- expect(code).toContain('navigator.languages');
45
- expect(code).toContain("'en-US'");
46
- });
47
- it('normalizes Permissions.query for notifications', () => {
48
- const code = generateStealthJs();
49
- expect(code).toContain('Permissions');
50
- expect(code).toContain('notifications');
51
- });
52
- it('cleans automation artifacts', () => {
53
- const code = generateStealthJs();
54
- expect(code).toContain('__playwright');
55
- expect(code).toContain('__puppeteer');
56
- expect(code).toContain("'cdc_'");
57
- expect(code).toContain("'__cdc_'");
58
- });
59
- it('filters CDP patterns from Error.stack', () => {
60
- const code = generateStealthJs();
61
- expect(code).toContain('puppeteer_evaluation_script');
62
- expect(code).toContain("'pptr:'");
63
- expect(code).toContain("'debugger://'");
64
- });
65
- it('neutralizes debugger statement traps', () => {
66
- const code = generateStealthJs();
67
- // Should patch Function constructor with new.target / Reflect.construct
68
- expect(code).toContain('_OrigFunction');
69
- expect(code).toContain('_PatchedFunction');
70
- expect(code).toContain('new.target');
71
- expect(code).toContain('Reflect.construct');
72
- // Should patch eval
73
- expect(code).toContain('_origEval');
74
- expect(code).toContain('_patchedEval');
75
- // Regex to strip debugger (lookbehind for statement boundaries)
76
- expect(code).toContain('_debuggerRe');
77
- });
78
- it('uses shared toString disguise via WeakMap', () => {
79
- const code = generateStealthJs();
80
- // Shared infrastructure at the top of the IIFE
81
- expect(code).toContain('_origToString');
82
- expect(code).toContain('WeakMap');
83
- expect(code).toContain('_disguised');
84
- expect(code).toContain('_disguise');
85
- // Should NOT have per-instance toString overrides on Function/eval
86
- // (they go through _disguise instead)
87
- });
88
- it('defends console method fingerprinting', () => {
89
- const code = generateStealthJs();
90
- expect(code).toContain('_consoleMethods');
91
- expect(code).toContain("'log'");
92
- expect(code).toContain("'warn'");
93
- expect(code).toContain("'error'");
94
- expect(code).toContain('[native code]');
95
- // Uses saved _origToString reference
96
- expect(code).toContain('_origToString.call');
97
- });
98
- it('defends window dimension detection', () => {
99
- const code = generateStealthJs();
100
- expect(code).toContain('outerWidth');
101
- expect(code).toContain('outerHeight');
102
- expect(code).toContain('innerWidth');
103
- expect(code).toContain('innerHeight');
104
- });
105
- it('filters Performance API entries', () => {
106
- const code = generateStealthJs();
107
- expect(code).toContain('getEntries');
108
- expect(code).toContain('getEntriesByType');
109
- expect(code).toContain('getEntriesByName');
110
- expect(code).toContain('_suspiciousPatterns');
111
- });
112
- it('cleans document $cdc_ properties', () => {
113
- const code = generateStealthJs();
114
- expect(code).toContain("'$cdc_'");
115
- expect(code).toContain("'$chrome_'");
116
- });
117
- it('patches iframe contentWindow.chrome consistency', () => {
118
- const code = generateStealthJs();
119
- expect(code).toContain('contentWindow');
120
- expect(code).toContain('HTMLIFrameElement');
121
- });
122
- it('uses non-enumerable guard flag on EventTarget.prototype', () => {
123
- const code = generateStealthJs();
124
- expect(code).toContain('EventTarget.prototype');
125
- expect(code).toContain("'__lsn'");
126
- expect(code).toContain('enumerable: false');
127
- });
128
- it('generates syntactically valid JavaScript', () => {
129
- const code = generateStealthJs();
130
- // new Function() parses the code without executing it in a real
131
- // browser context, catching syntax errors from template literal issues.
132
- expect(() => new Function(code)).not.toThrow();
133
- });
134
- });
@@ -1,94 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { TargetError } from './target-errors.js';
3
- describe('TargetError', () => {
4
- it('creates not_found error with code and hint', () => {
5
- const err = new TargetError({
6
- code: 'not_found',
7
- message: 'ref=99 not found in DOM',
8
- hint: 'Re-run `bycli browser state` to get a fresh snapshot.',
9
- });
10
- expect(err).toBeInstanceOf(Error);
11
- expect(err.name).toBe('TargetError');
12
- expect(err.code).toBe('not_found');
13
- expect(err.message).toBe('ref=99 not found in DOM');
14
- expect(err.hint).toContain('fresh snapshot');
15
- expect(err.candidates).toBeUndefined();
16
- });
17
- it('creates selector_ambiguous error with candidates + matches_n', () => {
18
- const err = new TargetError({
19
- code: 'selector_ambiguous',
20
- message: 'CSS selector ".btn" matched 3 elements',
21
- hint: 'Use a more specific selector, or pass --nth.',
22
- candidates: ['<button> "Login"', '<button> "Sign Up"', '<button> "Cancel"'],
23
- matches_n: 3,
24
- });
25
- expect(err.code).toBe('selector_ambiguous');
26
- expect(err.candidates).toHaveLength(3);
27
- expect(err.candidates[0]).toContain('Login');
28
- expect(err.matches_n).toBe(3);
29
- });
30
- it('creates invalid_selector error', () => {
31
- const err = new TargetError({
32
- code: 'invalid_selector',
33
- message: 'Invalid CSS selector: >>> (unexpected token)',
34
- hint: 'Check the selector syntax.',
35
- });
36
- expect(err.code).toBe('invalid_selector');
37
- expect(err.message).toContain('Invalid CSS selector');
38
- });
39
- it('creates selector_not_found error with matches_n=0', () => {
40
- const err = new TargetError({
41
- code: 'selector_not_found',
42
- message: 'CSS selector ".missing" matched 0 elements',
43
- hint: 'Check the page or use browser find.',
44
- matches_n: 0,
45
- });
46
- expect(err.code).toBe('selector_not_found');
47
- expect(err.matches_n).toBe(0);
48
- });
49
- it('creates selector_nth_out_of_range error', () => {
50
- const err = new TargetError({
51
- code: 'selector_nth_out_of_range',
52
- message: 'matched 3 elements, but --nth=5 is out of range',
53
- hint: 'Use --nth between 0 and 2.',
54
- matches_n: 3,
55
- });
56
- expect(err.code).toBe('selector_nth_out_of_range');
57
- expect(err.matches_n).toBe(3);
58
- });
59
- it('creates stale_ref error', () => {
60
- const err = new TargetError({
61
- code: 'stale_ref',
62
- message: 'ref=12 was <button>"Login" but now points to <div>"Header"',
63
- hint: 'Re-run `bycli browser state` to refresh.',
64
- });
65
- expect(err.code).toBe('stale_ref');
66
- expect(err.message).toContain('was <button>');
67
- });
68
- it('serializes to JSON for structured output', () => {
69
- const err = new TargetError({
70
- code: 'selector_ambiguous',
71
- message: 'matched 3',
72
- hint: 'be specific',
73
- candidates: ['a', 'b'],
74
- matches_n: 3,
75
- });
76
- const json = err.toJSON();
77
- expect(json).toEqual({
78
- code: 'selector_ambiguous',
79
- message: 'matched 3',
80
- hint: 'be specific',
81
- candidates: ['a', 'b'],
82
- matches_n: 3,
83
- });
84
- });
85
- it('omits candidates from JSON when not present', () => {
86
- const err = new TargetError({
87
- code: 'not_found',
88
- message: 'gone',
89
- hint: 'refresh',
90
- });
91
- const json = err.toJSON();
92
- expect(json).not.toHaveProperty('candidates');
93
- });
94
- });
@@ -1,118 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { resolveTargetJs } from './target-resolver.js';
3
- /**
4
- * Tests for the target resolver JS generator.
5
- *
6
- * Since resolveTargetJs() produces JS strings for browser evaluate(),
7
- * we test the generated JS by running it in a simulated DOM-like context
8
- * and verifying the structure of the output.
9
- */
10
- describe('resolveTargetJs', () => {
11
- it('generates JS that returns structured resolution for numeric ref', () => {
12
- const js = resolveTargetJs('12');
13
- expect(js).toContain('data-bycli-ref');
14
- expect(js).toContain('__bycli_ref_identity');
15
- expect(js).toContain('"12"');
16
- });
17
- it('generates JS that handles CSS selector input', () => {
18
- const js = resolveTargetJs('#submit-btn');
19
- expect(js).toContain('querySelectorAll');
20
- expect(js).toContain('"#submit-btn"');
21
- });
22
- it('generates JS with stale_ref detection for numeric refs', () => {
23
- const js = resolveTargetJs('5');
24
- expect(js).toContain('stale_ref');
25
- expect(js).toContain('__bycli_ref_identity');
26
- });
27
- it('generates JS with ambiguity detection for CSS selectors', () => {
28
- const js = resolveTargetJs('.btn');
29
- expect(js).toContain('selector_ambiguous');
30
- expect(js).toContain('candidates');
31
- });
32
- it('generates JS that propagates --nth option into the CSS branch', () => {
33
- const js = resolveTargetJs('.btn', { nth: 2 });
34
- expect(js).toContain('selector_nth_out_of_range');
35
- // opt.nth=2 should be inlined so the runtime picks matches[2]
36
- expect(js).toMatch(/const nth = 2;?/);
37
- });
38
- it('generates JS that enables firstOnMulti for read commands', () => {
39
- const js = resolveTargetJs('.btn', { firstOnMulti: true });
40
- expect(js).toContain('firstOnMulti = true');
41
- });
42
- it('generates JS with invalid_selector branch for CSS syntax errors', () => {
43
- const js = resolveTargetJs('.btn');
44
- expect(js).toContain('invalid_selector');
45
- });
46
- it('generates JS with selector_not_found branch for 0 matches', () => {
47
- const js = resolveTargetJs('#does-not-exist');
48
- expect(js).toContain('selector_not_found');
49
- });
50
- it('hands every non-numeric input to querySelectorAll (no regex shortlist)', () => {
51
- // Inputs that the old isCssLike regex rejected — must all flow into the
52
- // CSS branch so `find --css` and `get/click/type/select` accept the same surface.
53
- for (const sel of [':root', '*', ':has(.foo)', '::shadow-root', '???']) {
54
- const js = resolveTargetJs(sel);
55
- expect(js).toContain('querySelectorAll');
56
- // invalid selectors still route through invalid_selector at runtime,
57
- // never through a frontend "Cannot parse target" rejection.
58
- expect(js).not.toContain('Cannot parse target');
59
- }
60
- });
61
- it('escapes ref value safely', () => {
62
- const js = resolveTargetJs('"; alert(1); "');
63
- // JSON.stringify should handle escaping
64
- expect(js).not.toContain('alert(1); "');
65
- expect(js).toContain('\\"');
66
- });
67
- it('tags every success envelope with match_level so agents can tell tiers apart', () => {
68
- const numericJs = resolveTargetJs('7');
69
- const cssJs = resolveTargetJs('.btn');
70
- // Exact / reidentified emit the literal directly; stable flows through the
71
- // classifier's `level` variable. All three strings must appear in the JS.
72
- expect(numericJs).toContain("match_level: 'exact'");
73
- expect(numericJs).toContain("match_level: 'reidentified'");
74
- expect(numericJs).toContain("return 'stable'");
75
- // Stable + exact share the same emit site (match_level: level) — make sure
76
- // we didn't hardcode one of them and drop the other.
77
- expect(numericJs).toContain('match_level: level');
78
- // CSS path is always exact (selector ran successfully).
79
- expect(cssJs).toContain("match_level: 'exact'");
80
- });
81
- it('cascading ref path — classifier + reidentifier are both wired in', () => {
82
- const js = resolveTargetJs('3');
83
- // Classifier distinguishes the three tiers
84
- expect(js).toContain('function classifyMatch');
85
- expect(js).toContain("return 'exact'");
86
- expect(js).toContain("return 'stable'");
87
- expect(js).toContain("return 'mismatch'");
88
- // Strong id is the only thing that can rescue a drifted fingerprint
89
- expect(js).toContain('hadStrongId');
90
- // Reidentify searches live DOM with the same fingerprint shape the
91
- // snapshot / find writers emit — id / testId / aria-label only.
92
- expect(js).toContain('function reidentify');
93
- expect(js).toContain('getElementById');
94
- expect(js).toContain('[data-testid="');
95
- expect(js).toContain('[aria-label="');
96
- // Unique match required — never silently picks one of many candidates.
97
- expect(js).toContain('candidates.length === 1');
98
- // Recovered element is re-tagged + identity map refreshed so subsequent
99
- // resolves land on 'exact' instead of re-walking the cascade.
100
- expect(js).toContain("setAttribute('data-bycli-ref', ref)");
101
- expect(js).toContain('identity[ref] = fingerprintOf(recovered)');
102
- });
103
- it('reidentify runs both when data-bycli-ref is missing AND when fingerprint is mismatched', () => {
104
- const js = resolveTargetJs('9');
105
- // Two call sites: one in the !el branch, one after classifyMatch returns mismatch.
106
- const count = js.split('reidentify(fp)').length - 1;
107
- expect(count).toBeGreaterThanOrEqual(2);
108
- });
109
- it('falls through to stale_ref only after reidentify exhausts', () => {
110
- const js = resolveTargetJs('4');
111
- // The stale_ref emit must sit *below* a reidentify attempt so the cascade
112
- // is what produces the error — not the original strict check.
113
- const reidentifyIdx = js.indexOf('const recovered = reidentify(fp);');
114
- const staleIdx = js.indexOf("code: 'stale_ref'");
115
- expect(reidentifyIdx).toBeGreaterThan(-1);
116
- expect(staleIdx).toBeGreaterThan(reidentifyIdx);
117
- });
118
- });
@@ -1,29 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { buildEvaluateExpression, wrapForEval } from './utils.js';
3
- describe('browser eval utils', () => {
4
- it('keeps existing string eval wrapping behavior', () => {
5
- expect(wrapForEval('21 + 21')).toBe('21 + 21');
6
- expect(wrapForEval('() => 42')).toBe('(() => 42)()');
7
- });
8
- it('serializes function eval arguments as JSON', () => {
9
- const code = buildEvaluateExpression((selector) => {
10
- return document.querySelector(selector)?.textContent ?? null;
11
- }, ['.title']);
12
- expect(code).toContain('document.querySelector(selector)');
13
- expect(code).toContain('(...[".title"])');
14
- });
15
- it('accepts compact async arrow functions', () => {
16
- const fn = new Function('return async()=>42')();
17
- expect(buildEvaluateExpression(fn)).toBe('(async()=>42)(...[])');
18
- });
19
- it('rejects string eval with stray args', () => {
20
- expect(() => buildEvaluateExpression('document.title', ['ignored']))
21
- .toThrow('use page.evaluate(fn, ...args)');
22
- });
23
- it('rejects non-JSON-serializable function args', () => {
24
- const circular = {};
25
- circular.self = circular;
26
- expect(() => buildEvaluateExpression((value) => value, [circular]))
27
- .toThrow('JSON-serializable');
28
- });
29
- });
@@ -1,219 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { deriveFixture, expandFixtureArgs, parseSeedArgs, validateRows, validateRowShape } from './verify-fixture.js';
3
- describe('validateRows', () => {
4
- it('passes when rows meet all expectations', () => {
5
- const fixture = {
6
- expect: {
7
- rowCount: { min: 1, max: 3 },
8
- columns: ['id', 'title', 'url'],
9
- types: { id: 'number', title: 'string', url: 'string' },
10
- patterns: { url: '^https://' },
11
- notEmpty: ['title', 'url'],
12
- },
13
- };
14
- const rows = [
15
- { id: 1, title: 'a', url: 'https://x.com/a' },
16
- { id: 2, title: 'b', url: 'https://x.com/b' },
17
- ];
18
- expect(validateRows(rows, fixture)).toEqual([]);
19
- });
20
- it('reports rowCount below min', () => {
21
- const failures = validateRows([], { expect: { rowCount: { min: 1 } } });
22
- expect(failures).toHaveLength(1);
23
- expect(failures[0]).toMatchObject({ rule: 'rowCount' });
24
- expect(failures[0].detail).toContain('at least 1');
25
- });
26
- it('reports rowCount above max', () => {
27
- const failures = validateRows([{}, {}, {}, {}], { expect: { rowCount: { max: 3 } } });
28
- expect(failures).toHaveLength(1);
29
- expect(failures[0].detail).toContain('at most 3');
30
- });
31
- it('reports missing columns per row', () => {
32
- const failures = validateRows([{ a: 1 }, { a: 2, b: 3 }], { expect: { columns: ['a', 'b'] } });
33
- // row 0 missing 'b', row 1 complete
34
- expect(failures).toEqual([
35
- { rule: 'column', detail: 'missing column "b"', rowIndex: 0 },
36
- ]);
37
- });
38
- it('reports type mismatch including null', () => {
39
- const failures = validateRows([{ a: 'abc' }, { a: null }, { a: 42 }], { expect: { types: { a: 'string' } } });
40
- // row 0 string ok, row 1 null fail, row 2 number fail
41
- expect(failures).toHaveLength(2);
42
- expect(failures[0].rowIndex).toBe(1);
43
- expect(failures[0].detail).toContain('null');
44
- expect(failures[1].rowIndex).toBe(2);
45
- expect(failures[1].detail).toContain('number');
46
- });
47
- it('accepts union types like "number|string"', () => {
48
- const failures = validateRows([{ id: 1 }, { id: 'abc' }], { expect: { types: { id: 'number|string' } } });
49
- expect(failures).toEqual([]);
50
- });
51
- it('accepts "any" as wildcard type', () => {
52
- const failures = validateRows([{ v: 1 }, { v: 'x' }, { v: null }, { v: [1, 2] }], { expect: { types: { v: 'any' } } });
53
- expect(failures).toEqual([]);
54
- });
55
- it('reports pattern mismatch with row index and truncated value', () => {
56
- const failures = validateRows([{ url: 'https://ok.com' }, { url: 'not-a-url' }], { expect: { patterns: { url: '^https?://' } } });
57
- expect(failures).toHaveLength(1);
58
- expect(failures[0]).toMatchObject({ rule: 'pattern', rowIndex: 1 });
59
- expect(failures[0].detail).toContain('not-a-url');
60
- });
61
- it('skips pattern check for null/undefined values', () => {
62
- const failures = validateRows([{ url: null }, { url: undefined }], { expect: { patterns: { url: '^x' } } });
63
- expect(failures).toEqual([]);
64
- });
65
- it('reports invalid regex without crashing', () => {
66
- const failures = validateRows([{ a: 'x' }], { expect: { patterns: { a: '[unclosed' } } });
67
- expect(failures.some((f) => f.rule === 'pattern' && f.detail.includes('invalid'))).toBe(true);
68
- });
69
- it('treats empty/whitespace/null as failing notEmpty', () => {
70
- const failures = validateRows([{ t: '' }, { t: ' ' }, { t: null }, { t: 'ok' }], { expect: { notEmpty: ['t'] } });
71
- expect(failures).toHaveLength(3);
72
- expect(failures.map((f) => f.rowIndex)).toEqual([0, 1, 2]);
73
- });
74
- it('no failures when fixture has no expect block', () => {
75
- expect(validateRows([{ anything: 1 }], {})).toEqual([]);
76
- });
77
- it('mustNotContain flags substring bleed in columns', () => {
78
- const failures = validateRows([
79
- { description: 'Lead engineer, 5 years exp. address: Shanghai. category: IT' },
80
- { description: 'Clean text.' },
81
- ], {
82
- expect: {
83
- mustNotContain: { description: ['address:', 'category:'] },
84
- },
85
- });
86
- expect(failures).toHaveLength(2);
87
- expect(failures.every((f) => f.rule === 'mustNotContain')).toBe(true);
88
- expect(failures.every((f) => f.rowIndex === 0)).toBe(true);
89
- });
90
- it('mustNotContain skips null/undefined values', () => {
91
- const failures = validateRows([{ description: null }, { description: undefined }], { expect: { mustNotContain: { description: ['x'] } } });
92
- expect(failures).toEqual([]);
93
- });
94
- it('mustBeTruthy catches silent 0 / false / "" fallbacks', () => {
95
- const failures = validateRows([{ count: 10 }, { count: 0 }, { count: false }, { count: '' }, { count: null }], { expect: { mustBeTruthy: ['count'] } });
96
- expect(failures).toHaveLength(4);
97
- expect(failures.every((f) => f.rule === 'mustBeTruthy')).toBe(true);
98
- expect(failures.map((f) => f.rowIndex)).toEqual([1, 2, 3, 4]);
99
- });
100
- });
101
- describe('validateRowShape', () => {
102
- it('passes flat rows with a compact key set', () => {
103
- const failures = validateRowShape([
104
- { id: '1', title: 'A', author: { name: 'Ada' }, tags: ['ai', 'web'] },
105
- ]);
106
- expect(failures).toEqual([]);
107
- });
108
- it('reports rows with too many top-level keys', () => {
109
- const row = Object.fromEntries(Array.from({ length: 13 }, (_, i) => [`k${i}`, i]));
110
- const failures = validateRowShape([row]);
111
- expect(failures).toEqual([
112
- {
113
- rule: 'shapeKeyCount',
114
- detail: 'row has 13 top-level keys, expected at most 12',
115
- rowIndex: 0,
116
- },
117
- ]);
118
- });
119
- it('reports nesting deeper than one level', () => {
120
- const failures = validateRowShape([
121
- { title: 'A', stats: { author: { name: 'Ada' } } },
122
- ]);
123
- expect(failures).toEqual([
124
- {
125
- rule: 'shapeDepth',
126
- detail: '"stats" nesting depth is 2, expected at most 1',
127
- rowIndex: 0,
128
- },
129
- ]);
130
- });
131
- it('reports nested id-shaped fields even when one-level nesting is otherwise allowed', () => {
132
- const failures = validateRowShape([
133
- { title: 'A', author: { user_id: 'u1', name: 'Ada' } },
134
- ]);
135
- expect(failures).toEqual([
136
- {
137
- rule: 'shapeNestedId',
138
- detail: 'id-shaped field "author.user_id" must be a top-level row key',
139
- rowIndex: 0,
140
- },
141
- ]);
142
- });
143
- });
144
- describe('deriveFixture', () => {
145
- it('returns rowCount.min=0 when rows are empty', () => {
146
- expect(deriveFixture([])).toEqual({ expect: { rowCount: { min: 0 } } });
147
- });
148
- it('extracts columns from first row and infers types per column', () => {
149
- const fixture = deriveFixture([
150
- { id: 1, title: 'a', url: 'https://x' },
151
- { id: 2, title: 'b', url: 'https://y' },
152
- ]);
153
- expect(fixture.expect?.columns).toEqual(['id', 'title', 'url']);
154
- expect(fixture.expect?.types).toEqual({
155
- id: 'number',
156
- title: 'string',
157
- url: 'string',
158
- });
159
- expect(fixture.expect?.rowCount).toEqual({ min: 1 });
160
- });
161
- it('unions mixed types across rows as "a|b"', () => {
162
- const fixture = deriveFixture([
163
- { v: 1 },
164
- { v: 'two' },
165
- { v: null },
166
- ]);
167
- expect(fixture.expect?.types?.v).toBe('null|number|string');
168
- });
169
- it('embeds args when provided', () => {
170
- const fixture = deriveFixture([{ x: 1 }], { limit: 5 });
171
- expect(fixture.args).toEqual({ limit: 5 });
172
- });
173
- it('embeds positional argv array when provided', () => {
174
- const fixture = deriveFixture([{ x: 1 }], ['123', '--limit', '3']);
175
- expect(fixture.args).toEqual(['123', '--limit', '3']);
176
- });
177
- it('does not add patterns or notEmpty automatically', () => {
178
- const fixture = deriveFixture([{ a: 'x' }]);
179
- expect(fixture.expect?.patterns).toBeUndefined();
180
- expect(fixture.expect?.notEmpty).toBeUndefined();
181
- });
182
- });
183
- describe('expandFixtureArgs', () => {
184
- it('returns [] for undefined', () => {
185
- expect(expandFixtureArgs(undefined)).toEqual([]);
186
- });
187
- it('expands object form as --key value pairs', () => {
188
- expect(expandFixtureArgs({ limit: 3, sort: 'hot' })).toEqual(['--limit', '3', '--sort', 'hot']);
189
- });
190
- it('passes array form verbatim, stringifying values', () => {
191
- expect(expandFixtureArgs(['123456', '--limit', 3])).toEqual(['123456', '--limit', '3']);
192
- });
193
- it('handles empty object and empty array', () => {
194
- expect(expandFixtureArgs({})).toEqual([]);
195
- expect(expandFixtureArgs([])).toEqual([]);
196
- });
197
- it('preserves positional + flag mix (e.g. <tid> --limit 3)', () => {
198
- expect(expandFixtureArgs(['https://example.com/thread-1', '--comments', '5'])).toEqual([
199
- 'https://example.com/thread-1',
200
- '--comments',
201
- '5',
202
- ]);
203
- });
204
- });
205
- describe('parseSeedArgs', () => {
206
- it('treats plain text as one positional arg', () => {
207
- expect(parseSeedArgs('bycli-verify')).toEqual(['bycli-verify']);
208
- });
209
- it('accepts JSON array seed args', () => {
210
- expect(parseSeedArgs('["subject", "--limit", 3]')).toEqual(['subject', '--limit', 3]);
211
- });
212
- it('accepts JSON object seed args', () => {
213
- expect(parseSeedArgs('{"limit":3,"sort":"hot"}')).toEqual({ limit: 3, sort: 'hot' });
214
- });
215
- it('ignores empty input', () => {
216
- expect(parseSeedArgs(undefined)).toBeUndefined();
217
- expect(parseSeedArgs(' ')).toBeUndefined();
218
- });
219
- });