@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,146 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from 'vitest';
2
- import * as fs from 'node:fs';
3
- import * as path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import yaml from 'js-yaml';
6
- const { mockExecFileSync, mockPlatform, mockSpawnSync } = vi.hoisted(() => ({
7
- mockExecFileSync: vi.fn(),
8
- mockPlatform: vi.fn(() => 'darwin'),
9
- mockSpawnSync: vi.fn(),
10
- }));
11
- vi.mock('node:child_process', () => ({
12
- spawnSync: mockSpawnSync,
13
- execFileSync: mockExecFileSync,
14
- }));
15
- vi.mock('node:os', async () => {
16
- const actual = await vi.importActual('node:os');
17
- return {
18
- ...actual,
19
- platform: mockPlatform,
20
- };
21
- });
22
- import { executeExternalCli, formatExternalCliLabel, installExternalCli, parseCommand } from './external.js';
23
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
- describe('parseCommand', () => {
25
- it('splits binaries and quoted arguments without invoking a shell', () => {
26
- expect(parseCommand('npm install -g "@scope/tool name"')).toEqual({
27
- binary: 'npm',
28
- args: ['install', '-g', '@scope/tool name'],
29
- });
30
- });
31
- it('rejects shell operators', () => {
32
- expect(() => parseCommand('brew install gh && rm -rf /')).toThrow('Install command contains unsafe shell operators');
33
- });
34
- it('rejects command substitution and multiline input', () => {
35
- expect(() => parseCommand('brew install $(whoami)')).toThrow('Install command contains unsafe shell operators');
36
- expect(() => parseCommand('brew install gh\nrm -rf /')).toThrow('Install command contains unsafe shell operators');
37
- });
38
- it('keeps built-in install commands compatible with the shell-free parser', () => {
39
- const raw = fs.readFileSync(path.join(__dirname, 'external-clis.yaml'), 'utf8');
40
- const entries = (yaml.load(raw) || []);
41
- for (const entry of entries) {
42
- for (const command of Object.values(entry.install ?? {})) {
43
- if (command)
44
- expect(() => parseCommand(command)).not.toThrow();
45
- }
46
- }
47
- });
48
- it('registers Longbridge with safe package-manager installers only', () => {
49
- const raw = fs.readFileSync(path.join(__dirname, 'external-clis.yaml'), 'utf8');
50
- const entries = (yaml.load(raw) || []);
51
- const longbridge = entries.find((entry) => entry.name === 'longbridge');
52
- expect(longbridge).toMatchObject({
53
- binary: 'longbridge',
54
- homepage: 'https://open.longbridge.com/zh-CN/docs/cli/',
55
- install: {
56
- mac: 'brew install --cask longbridge/tap/longbridge-terminal',
57
- windows: 'scoop install https://open.longbridge.com/longbridge/longbridge-terminal/longbridge.json',
58
- },
59
- });
60
- expect(longbridge?.install?.linux).toBeUndefined();
61
- expect(longbridge?.install?.default).toBeUndefined();
62
- });
63
- });
64
- describe('formatExternalCliLabel', () => {
65
- it('shows the package name when the executable name differs', () => {
66
- expect(formatExternalCliLabel({ name: 'wx', binary: 'wx', package: 'wx-cli' })).toBe('wx(wx-cli)');
67
- });
68
- it('keeps the label compact when package and name match', () => {
69
- expect(formatExternalCliLabel({ name: 'docker', binary: 'docker', package: 'docker' })).toBe('docker');
70
- });
71
- it('renders a human-readable brand alias for ambiguous executable names', () => {
72
- expect(formatExternalCliLabel({ name: 'ntn', binary: 'ntn', package: 'notion' })).toBe('ntn(notion)');
73
- expect(formatExternalCliLabel({ name: 'wecom-cli', binary: 'wecom-cli', package: '企业微信' })).toBe('wecom-cli(企业微信)');
74
- });
75
- });
76
- describe('installExternalCli', () => {
77
- const cli = {
78
- name: 'readwise',
79
- binary: 'readwise',
80
- install: {
81
- default: 'npm install -g @readwiseio/readwise-cli',
82
- },
83
- };
84
- beforeEach(() => {
85
- mockExecFileSync.mockReset();
86
- mockSpawnSync.mockReset();
87
- mockPlatform.mockReturnValue('darwin');
88
- process.exitCode = undefined;
89
- });
90
- it('retries with .cmd on Windows when the bare binary is unavailable', () => {
91
- mockPlatform.mockReturnValue('win32');
92
- mockExecFileSync
93
- .mockImplementationOnce(() => {
94
- const err = new Error('not found');
95
- err.code = 'ENOENT';
96
- throw err;
97
- })
98
- .mockReturnValueOnce(Buffer.from(''));
99
- expect(installExternalCli(cli)).toBe(true);
100
- expect(mockExecFileSync).toHaveBeenNthCalledWith(1, 'npm', ['install', '-g', '@readwiseio/readwise-cli'], { stdio: 'inherit' });
101
- expect(mockExecFileSync).toHaveBeenNthCalledWith(2, 'npm.cmd', ['install', '-g', '@readwiseio/readwise-cli'], { stdio: 'inherit' });
102
- });
103
- it('does not mask non-ENOENT failures', () => {
104
- mockPlatform.mockReturnValue('win32');
105
- mockExecFileSync.mockImplementationOnce(() => {
106
- const err = new Error('permission denied');
107
- err.code = 'EACCES';
108
- throw err;
109
- });
110
- expect(installExternalCli(cli)).toBe(false);
111
- expect(mockExecFileSync).toHaveBeenCalledTimes(1);
112
- });
113
- });
114
- describe('executeExternalCli', () => {
115
- beforeEach(() => {
116
- mockExecFileSync.mockReset();
117
- mockSpawnSync.mockReset();
118
- mockPlatform.mockReturnValue('darwin');
119
- process.exitCode = undefined;
120
- });
121
- it('does not spawn a binary that is still unavailable after auto-install', () => {
122
- const docker = {
123
- name: 'docker',
124
- binary: 'docker',
125
- install: { mac: 'brew install --cask docker' },
126
- };
127
- mockExecFileSync
128
- .mockImplementationOnce(() => {
129
- const err = new Error('docker not found');
130
- err.code = 'ENOENT';
131
- throw err;
132
- })
133
- .mockReturnValueOnce(Buffer.from(''))
134
- .mockImplementationOnce(() => {
135
- const err = new Error('docker still not found');
136
- err.code = 'ENOENT';
137
- throw err;
138
- });
139
- executeExternalCli('docker', [], [docker]);
140
- expect(mockExecFileSync).toHaveBeenNthCalledWith(1, 'which', ['docker'], { stdio: 'ignore' });
141
- expect(mockExecFileSync).toHaveBeenNthCalledWith(2, 'brew', ['install', '--cask', 'docker'], { stdio: 'inherit' });
142
- expect(mockExecFileSync).toHaveBeenNthCalledWith(3, 'which', ['docker'], { stdio: 'ignore' });
143
- expect(mockSpawnSync).not.toHaveBeenCalled();
144
- expect(process.exitCode).toBe(69);
145
- });
146
- });
@@ -1,58 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { classifyAdapter, formatRootAdapterHelpText } from './help.js';
3
- describe('classifyAdapter', () => {
4
- it('classifies DNS-style domains as site', () => {
5
- expect(classifyAdapter('www.bilibili.com')).toBe('site');
6
- expect(classifyAdapter('chatgpt.com')).toBe('site');
7
- expect(classifyAdapter('claude.ai')).toBe('site');
8
- expect(classifyAdapter('grok.com')).toBe('site');
9
- });
10
- it('classifies localhost as app (Electron / osascript desktop integrations)', () => {
11
- expect(classifyAdapter('localhost')).toBe('app');
12
- });
13
- it('classifies non-DNS domain strings as app (e.g. literal "doubao-app")', () => {
14
- expect(classifyAdapter('doubao-app')).toBe('app');
15
- });
16
- it('defaults missing domain to site (most adapters without explicit domain are public web scrapers)', () => {
17
- expect(classifyAdapter(undefined)).toBe('site');
18
- });
19
- });
20
- describe('formatRootAdapterHelpText', () => {
21
- it('renders all three sections in External / App / Site order when populated', () => {
22
- const text = formatRootAdapterHelpText({
23
- external: [
24
- { name: 'gh', label: 'gh' },
25
- { name: 'wx', label: 'wx(wx-cli)' },
26
- ],
27
- apps: ['chatwise', 'codex'],
28
- sites: ['bilibili'],
29
- });
30
- expect(text).toContain('External CLIs (2):');
31
- expect(text).toContain('App adapters (2):');
32
- expect(text).toContain('Site adapters (1):');
33
- expect(text).toContain('wx(wx-cli)');
34
- expect(text.indexOf('External CLIs')).toBeLessThan(text.indexOf('App adapters'));
35
- expect(text.indexOf('App adapters')).toBeLessThan(text.indexOf('Site adapters'));
36
- });
37
- it('omits empty sections instead of rendering a (0) header', () => {
38
- const text = formatRootAdapterHelpText({
39
- external: [],
40
- apps: [],
41
- sites: ['bilibili'],
42
- });
43
- expect(text).not.toContain('External CLIs');
44
- expect(text).not.toContain('App adapters');
45
- expect(text).toContain('Site adapters (1):');
46
- });
47
- it('returns empty string when all groups are empty', () => {
48
- expect(formatRootAdapterHelpText({ external: [], apps: [], sites: [] })).toBe('');
49
- });
50
- it('always renders the agent discovery hint when any section is populated', () => {
51
- const text = formatRootAdapterHelpText({
52
- external: [],
53
- apps: [],
54
- sites: ['bilibili'],
55
- });
56
- expect(text).toContain("'bycli <site> --help -f yaml'");
57
- });
58
- });
@@ -1,92 +0,0 @@
1
- /**
2
- * Tests for the plugin lifecycle hooks system.
3
- */
4
- import { describe, it, expect, beforeEach } from 'vitest';
5
- import { onStartup, onBeforeExecute, onAfterExecute, emitHook, clearAllHooks, } from './hooks.js';
6
- beforeEach(() => {
7
- clearAllHooks();
8
- });
9
- describe('hook registration and emission', () => {
10
- it('onBeforeExecute hook is called with context', async () => {
11
- const calls = [];
12
- onBeforeExecute((ctx) => { calls.push({ ...ctx }); });
13
- await emitHook('onBeforeExecute', { command: 'test/cmd', args: { limit: 5 }, startedAt: 100 });
14
- expect(calls).toHaveLength(1);
15
- expect(calls[0].command).toBe('test/cmd');
16
- expect(calls[0].args).toEqual({ limit: 5 });
17
- expect(calls[0].startedAt).toBe(100);
18
- });
19
- it('onAfterExecute hook receives result', async () => {
20
- const results = [];
21
- onAfterExecute((_ctx, result) => { results.push(result); });
22
- const mockResult = [{ title: 'item1' }, { title: 'item2' }];
23
- await emitHook('onAfterExecute', { command: 'test/cmd', args: {} }, mockResult);
24
- expect(results).toHaveLength(1);
25
- expect(results[0]).toEqual(mockResult);
26
- });
27
- it('onStartup hook fires', async () => {
28
- let fired = false;
29
- onStartup(() => { fired = true; });
30
- await emitHook('onStartup', { command: '__startup__', args: {} });
31
- expect(fired).toBe(true);
32
- });
33
- it('multiple hooks on the same event fire in order', async () => {
34
- const order = [];
35
- onBeforeExecute(() => { order.push(1); });
36
- onBeforeExecute(() => { order.push(2); });
37
- onBeforeExecute(() => { order.push(3); });
38
- await emitHook('onBeforeExecute', { command: 'test/cmd', args: {} });
39
- expect(order).toEqual([1, 2, 3]);
40
- });
41
- it('async hooks are awaited', async () => {
42
- const order = [];
43
- onBeforeExecute(async () => {
44
- await new Promise((r) => setTimeout(r, 10));
45
- order.push('async-done');
46
- });
47
- onBeforeExecute(() => { order.push('sync'); });
48
- await emitHook('onBeforeExecute', { command: 'test/cmd', args: {} });
49
- expect(order).toEqual(['async-done', 'sync']);
50
- });
51
- });
52
- describe('hook error isolation', () => {
53
- it('failing hook does not prevent other hooks from running', async () => {
54
- const calls = [];
55
- onBeforeExecute(() => { calls.push('first'); });
56
- onBeforeExecute(() => { throw new Error('boom'); });
57
- onBeforeExecute(() => { calls.push('third'); });
58
- await emitHook('onBeforeExecute', { command: 'test/cmd', args: {} });
59
- // First and third should still run despite the second throwing
60
- expect(calls).toEqual(['first', 'third']);
61
- });
62
- it('async hook rejection does not prevent other hooks', async () => {
63
- const calls = [];
64
- onAfterExecute(() => { calls.push('before-reject'); });
65
- onAfterExecute(async () => { throw new Error('async boom'); });
66
- onAfterExecute(() => { calls.push('after-reject'); });
67
- await emitHook('onAfterExecute', { command: 'test/cmd', args: {} }, null);
68
- expect(calls).toEqual(['before-reject', 'after-reject']);
69
- });
70
- });
71
- describe('no-op when no hooks registered', () => {
72
- it('emitHook with no registered hooks does nothing', async () => {
73
- // Should not throw
74
- await emitHook('onBeforeExecute', { command: 'test/cmd', args: {} });
75
- await emitHook('onAfterExecute', { command: 'test/cmd', args: {} }, []);
76
- await emitHook('onStartup', { command: '__startup__', args: {} });
77
- });
78
- });
79
- describe('clearAllHooks', () => {
80
- it('removes all hooks', async () => {
81
- let called = false;
82
- onStartup(() => { called = true; });
83
- clearAllHooks();
84
- await emitHook('onStartup', { command: '__startup__', args: {} });
85
- expect(called).toBe(false);
86
- });
87
- });
88
- describe('globalThis singleton', () => {
89
- it('uses globalThis.__bycli_hooks__ for shared state', () => {
90
- expect(globalThis.__bycli_hooks__).toBeInstanceOf(Map);
91
- });
92
- });
@@ -1,81 +0,0 @@
1
- /**
2
- * Tests for interceptor.ts: JavaScript code generators for XHR/Fetch interception.
3
- */
4
- import { describe, it, expect } from 'vitest';
5
- import { generateInterceptorJs, generateReadInterceptedJs, generateTapInterceptorJs } from './interceptor.js';
6
- describe('generateInterceptorJs', () => {
7
- it('generates valid JavaScript function source', () => {
8
- const js = generateInterceptorJs('"api/search"');
9
- expect(js).toContain('window.fetch');
10
- expect(js).toContain('XMLHttpRequest');
11
- expect(js).toContain('"api/search"');
12
- // Should be a function expression wrapping
13
- expect(js.trim()).toMatch(/^\(\)\s*=>/);
14
- });
15
- it('uses default array name and patch guard', () => {
16
- const js = generateInterceptorJs('"test"');
17
- expect(js).toContain('__bycli_intercepted');
18
- expect(js).toContain('__bycli_interceptor_patched');
19
- });
20
- it('uses custom array name and patch guard', () => {
21
- const js = generateInterceptorJs('"test"', {
22
- arrayName: '__my_data',
23
- patchGuard: '__my_guard',
24
- });
25
- expect(js).toContain('__my_data');
26
- expect(js).toContain('__my_guard');
27
- expect(js).not.toContain('__bycli_intercepted');
28
- });
29
- it('includes fetch clone and json parsing', () => {
30
- const js = generateInterceptorJs('"api"');
31
- expect(js).toContain('response.clone()');
32
- expect(js).toContain('clone.json()');
33
- });
34
- it('includes XHR open and send patching', () => {
35
- const js = generateInterceptorJs('"api"');
36
- expect(js).toContain('XMLHttpRequest.prototype');
37
- expect(js).toContain('__origOpen');
38
- expect(js).toContain('__origSend');
39
- });
40
- });
41
- describe('generateReadInterceptedJs', () => {
42
- it('generates valid JavaScript to read and clear data', () => {
43
- const js = generateReadInterceptedJs();
44
- expect(js).toContain('__bycli_intercepted');
45
- // Should clear the array after reading
46
- expect(js).toContain('= []');
47
- });
48
- it('uses custom array name', () => {
49
- const js = generateReadInterceptedJs('__custom_arr');
50
- expect(js).toContain('__custom_arr');
51
- expect(js).not.toContain('__bycli_intercepted');
52
- });
53
- });
54
- describe('generateTapInterceptorJs', () => {
55
- it('returns all required fields', () => {
56
- const tap = generateTapInterceptorJs('"api/data"');
57
- expect(tap.setupVar).toBeDefined();
58
- expect(tap.capturedVar).toBe('captured');
59
- expect(tap.promiseVar).toBe('capturePromise');
60
- expect(tap.resolveVar).toBe('captureResolve');
61
- expect(tap.fetchPatch).toBeDefined();
62
- expect(tap.xhrPatch).toBeDefined();
63
- expect(tap.restorePatch).toBeDefined();
64
- });
65
- it('contains the capture pattern in setup', () => {
66
- const tap = generateTapInterceptorJs('"my-pattern"');
67
- expect(tap.setupVar).toContain('"my-pattern"');
68
- });
69
- it('restores original fetch and XHR in restorePatch', () => {
70
- const tap = generateTapInterceptorJs('"test"');
71
- expect(tap.restorePatch).toContain('origFetch');
72
- expect(tap.restorePatch).toContain('origXhrOpen');
73
- expect(tap.restorePatch).toContain('origXhrSend');
74
- });
75
- it('uses first-match capture (only first response)', () => {
76
- const tap = generateTapInterceptorJs('"test"');
77
- // Both fetch and xhr patches should check !captured before storing
78
- expect(tap.fetchPatch).toContain('!captured');
79
- expect(tap.xhrPatch).toContain('!captured');
80
- });
81
- });
@@ -1,138 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { detectProcess, discoverAppPath, launchDetachedApp, launchElectronApp, probeCDP, resolveExecutableCandidates } from './launcher.js';
3
- function createMockChildProcess() {
4
- const listeners = new Map();
5
- return {
6
- once: vi.fn((event, handler) => {
7
- listeners.set(event, [...(listeners.get(event) ?? []), handler]);
8
- }),
9
- off: vi.fn((event, handler) => {
10
- listeners.set(event, (listeners.get(event) ?? []).filter((listener) => listener !== handler));
11
- }),
12
- unref: vi.fn(),
13
- emit: (event, value) => {
14
- for (const listener of listeners.get(event) ?? [])
15
- listener(value);
16
- },
17
- };
18
- }
19
- vi.mock('node:child_process', () => ({
20
- execFileSync: vi.fn(),
21
- spawn: vi.fn(),
22
- }));
23
- const cp = vi.mocked(await import('node:child_process'));
24
- describe('probeCDP', () => {
25
- it('returns false when CDP endpoint is unreachable', async () => {
26
- const result = await probeCDP(59999, 500);
27
- expect(result).toBe(false);
28
- });
29
- });
30
- describe('detectProcess', () => {
31
- beforeEach(() => {
32
- vi.restoreAllMocks();
33
- });
34
- it('returns false when pgrep finds no process', () => {
35
- cp.execFileSync.mockImplementation(() => {
36
- const err = new Error('exit 1');
37
- err.status = 1;
38
- throw err;
39
- });
40
- const result = detectProcess('NonExistentApp');
41
- expect(result).toBe(false);
42
- });
43
- it.skipIf(process.platform === 'win32')('returns true when pgrep finds a process', () => {
44
- cp.execFileSync.mockReturnValue('12345\n');
45
- const result = detectProcess('Cursor');
46
- expect(result).toBe(true);
47
- });
48
- });
49
- describe('discoverAppPath', () => {
50
- beforeEach(() => {
51
- vi.restoreAllMocks();
52
- });
53
- it.skipIf(process.platform !== 'darwin')('returns path when osascript succeeds', () => {
54
- cp.execFileSync.mockReturnValue('/Applications/Cursor.app/\n');
55
- const result = discoverAppPath('Cursor');
56
- expect(result).toBe('/Applications/Cursor.app');
57
- });
58
- it.skipIf(process.platform !== 'darwin')('returns null when osascript fails', () => {
59
- cp.execFileSync.mockImplementation(() => {
60
- throw new Error('app not found');
61
- });
62
- const result = discoverAppPath('NonExistent');
63
- expect(result).toBeNull();
64
- });
65
- it.skipIf(process.platform === 'darwin')('returns null on non-darwin platform', () => {
66
- const result = discoverAppPath('Cursor');
67
- expect(result).toBeNull();
68
- });
69
- });
70
- describe('launchDetachedApp', () => {
71
- beforeEach(() => {
72
- vi.restoreAllMocks();
73
- cp.spawn.mockReset();
74
- });
75
- it('unrefs the process after spawn succeeds', async () => {
76
- const child = createMockChildProcess();
77
- cp.spawn.mockImplementation(() => {
78
- queueMicrotask(() => child.emit('spawn'));
79
- return child;
80
- });
81
- await expect(launchDetachedApp('/Applications/Antigravity.app/Contents/MacOS/Antigravity', ['--remote-debugging-port=9234'], 'Antigravity'))
82
- .resolves
83
- .toBeUndefined();
84
- expect(child.unref).toHaveBeenCalledTimes(1);
85
- });
86
- it('converts ENOENT into a controlled launch error', async () => {
87
- const child = createMockChildProcess();
88
- cp.spawn.mockImplementation(() => {
89
- queueMicrotask(() => child.emit('error', Object.assign(new Error('missing binary'), { code: 'ENOENT' })));
90
- return child;
91
- });
92
- await expect(launchDetachedApp('/Applications/Antigravity.app/Contents/MacOS/Antigravity', ['--remote-debugging-port=9234'], 'Antigravity'))
93
- .rejects
94
- .toThrow('Could not launch Antigravity');
95
- expect(child.unref).not.toHaveBeenCalled();
96
- });
97
- });
98
- describe('resolveExecutableCandidates', () => {
99
- it('prefers explicit executable candidates over processName', () => {
100
- const app = {
101
- port: 9234,
102
- processName: 'Antigravity',
103
- executableNames: ['Electron', 'Antigravity'],
104
- };
105
- expect(resolveExecutableCandidates('/Applications/Antigravity.app', app)).toEqual([
106
- '/Applications/Antigravity.app/Contents/MacOS/Electron',
107
- '/Applications/Antigravity.app/Contents/MacOS/Antigravity',
108
- ]);
109
- });
110
- });
111
- describe('launchElectronApp', () => {
112
- beforeEach(() => {
113
- vi.restoreAllMocks();
114
- cp.spawn.mockReset();
115
- });
116
- it('falls back to the next executable candidate when the first is missing', async () => {
117
- const firstChild = createMockChildProcess();
118
- const secondChild = createMockChildProcess();
119
- const app = {
120
- port: 9234,
121
- processName: 'Antigravity',
122
- executableNames: ['Electron', 'Antigravity'],
123
- };
124
- cp.spawn
125
- .mockImplementationOnce(() => {
126
- queueMicrotask(() => firstChild.emit('error', Object.assign(new Error('missing binary'), { code: 'ENOENT' })));
127
- return firstChild;
128
- })
129
- .mockImplementationOnce(() => {
130
- queueMicrotask(() => secondChild.emit('spawn'));
131
- return secondChild;
132
- });
133
- await expect(launchElectronApp('/Applications/Antigravity.app', app, ['--remote-debugging-port=9234'], 'Antigravity')).resolves.toBeUndefined();
134
- expect(cp.spawn).toHaveBeenNthCalledWith(1, '/Applications/Antigravity.app/Contents/MacOS/Electron', ['--remote-debugging-port=9234'], { detached: true, stdio: 'ignore' });
135
- expect(cp.spawn).toHaveBeenNthCalledWith(2, '/Applications/Antigravity.app/Contents/MacOS/Antigravity', ['--remote-debugging-port=9234'], { detached: true, stdio: 'ignore' });
136
- expect(secondChild.unref).toHaveBeenCalledTimes(1);
137
- });
138
- });
@@ -1,55 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { decideProxy, hasProxyEnv } from './node-network.js';
3
- describe('node network proxy decisions', () => {
4
- it('detects common proxy env variables', () => {
5
- expect(hasProxyEnv({ https_proxy: 'http://127.0.0.1:7897' })).toBe(true);
6
- expect(hasProxyEnv({ HTTP_PROXY: 'http://proxy.example:8080' })).toBe(true);
7
- expect(hasProxyEnv({})).toBe(false);
8
- });
9
- it('routes external https traffic through https_proxy', () => {
10
- const decision = decideProxy(new URL('https://www.v2ex.com/api/topics/latest.json'), { https_proxy: 'http://127.0.0.1:7897' });
11
- expect(decision).toEqual({
12
- mode: 'proxy',
13
- proxyUrl: 'http://127.0.0.1:7897',
14
- });
15
- });
16
- it('falls back to HTTP_PROXY for https traffic when HTTPS_PROXY is absent', () => {
17
- const decision = decideProxy(new URL('https://www.v2ex.com/api/topics/latest.json'), { HTTP_PROXY: 'http://127.0.0.1:7897' });
18
- expect(decision).toEqual({
19
- mode: 'proxy',
20
- proxyUrl: 'http://127.0.0.1:7897',
21
- });
22
- });
23
- it('bypasses proxies for loopback addresses', () => {
24
- const env = { https_proxy: 'http://127.0.0.1:7897', http_proxy: 'http://127.0.0.1:7897' };
25
- expect(decideProxy(new URL('http://127.0.0.1:19825/status'), env)).toEqual({ mode: 'direct' });
26
- expect(decideProxy(new URL('http://localhost:19825/status'), env)).toEqual({ mode: 'direct' });
27
- expect(decideProxy(new URL('http://[::1]:19825/status'), env)).toEqual({ mode: 'direct' });
28
- });
29
- it('honors NO_PROXY domain matches', () => {
30
- const decision = decideProxy(new URL('https://api.example.com/v1/items'), {
31
- https_proxy: 'http://127.0.0.1:7897',
32
- no_proxy: '.example.com',
33
- });
34
- expect(decision).toEqual({ mode: 'direct' });
35
- });
36
- it('supports wildcard-style NO_PROXY subdomain entries', () => {
37
- const decision = decideProxy(new URL('https://api.example.com/v1/items'), {
38
- https_proxy: 'http://127.0.0.1:7897',
39
- no_proxy: '*.example.com',
40
- });
41
- expect(decision).toEqual({ mode: 'direct' });
42
- });
43
- it('matches NO_PROXY entries that rely on the default URL port', () => {
44
- const env = { https_proxy: 'http://127.0.0.1:7897', http_proxy: 'http://127.0.0.1:7897' };
45
- expect(decideProxy(new URL('https://example.com/'), { ...env, NO_PROXY: 'example.com:443' })).toEqual({ mode: 'direct' });
46
- expect(decideProxy(new URL('http://example.com/health'), { ...env, NO_PROXY: 'example.com:80' })).toEqual({ mode: 'direct' });
47
- });
48
- it('falls back to ALL_PROXY when protocol-specific settings are absent', () => {
49
- const decision = decideProxy(new URL('http://example.net/data'), { ALL_PROXY: 'socks5://127.0.0.1:1080' });
50
- expect(decision).toEqual({
51
- mode: 'proxy',
52
- proxyUrl: 'socks5://127.0.0.1:1080',
53
- });
54
- });
55
- });