@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.
- package/cli-manifest.json +0 -61
- package/clis/twitter/search.js +3 -3
- package/dist/src/adapter-shadow.js +2 -2
- package/dist/src/browser/analyze.d.ts +10 -99
- package/dist/src/browser/analyze.js +10 -226
- package/dist/src/browser/cdp.js +67 -7
- package/dist/src/browser/daemon-client.d.ts +2 -0
- package/dist/src/browser/daemon-client.js +1 -1
- package/dist/src/browser/extension-capabilities.d.ts +13 -0
- package/dist/src/browser/extension-capabilities.js +22 -0
- package/dist/src/browser/extension-capabilities.test.d.ts +1 -0
- package/dist/src/browser/extension-version-metadata.test.d.ts +1 -0
- package/dist/src/browser/navigation-guard.d.ts +78 -0
- package/dist/src/browser/navigation-guard.js +142 -0
- package/dist/src/browser/navigation-guard.test.d.ts +1 -0
- package/dist/src/browser/page.d.ts +1 -0
- package/dist/src/browser/page.js +20 -1
- package/dist/src/browser/url-policy.d.ts +89 -0
- package/dist/src/browser/url-policy.js +311 -0
- package/dist/src/browser/url-policy.test.d.ts +1 -0
- package/dist/src/browser/verify-fixture.js +2 -2
- package/dist/src/build-manifest.js +4 -2
- package/dist/src/capabilityRouting.d.ts +3 -2
- package/dist/src/capabilityRouting.js +10 -2
- package/dist/src/cli.js +11 -14
- package/dist/src/commanderAdapter.js +5 -5
- package/dist/src/config-paths.d.ts +19 -0
- package/dist/src/config-paths.js +31 -0
- package/dist/src/daemon.js +256 -0
- package/dist/src/discovery.d.ts +10 -3
- package/dist/src/discovery.js +20 -10
- package/dist/src/discovery.test.d.ts +1 -0
- package/dist/src/execution.d.ts +5 -0
- package/dist/src/execution.js +272 -48
- package/dist/src/help.js +8 -8
- package/dist/src/main.js +18 -2
- package/dist/src/manifest-schema.d.ts +9 -0
- package/dist/src/manifest-schema.js +162 -0
- package/dist/src/manifest-schema.test.d.ts +1 -0
- package/dist/src/manifest-types.d.ts +1 -1
- package/dist/src/observation/redaction.js +10 -4
- package/dist/src/plugin.js +11 -8
- package/dist/src/recorder/highlevel/analyze.d.ts +29 -0
- package/dist/src/recorder/highlevel/analyze.js +91 -0
- package/dist/src/recorder/highlevel/init.d.ts +125 -0
- package/dist/src/recorder/highlevel/init.js +279 -0
- package/dist/src/recorder/highlevel/init.test.d.ts +1 -0
- package/dist/src/recorder/highlevel/verify.d.ts +73 -0
- package/dist/src/recorder/highlevel/verify.js +74 -0
- package/dist/src/recorder/http/analyze-runner.d.ts +28 -0
- package/dist/src/recorder/http/analyze-runner.js +78 -0
- package/dist/src/recorder/http/analyze-runner.test.d.ts +1 -0
- package/dist/src/recorder/http/handlers.d.ts +51 -0
- package/dist/src/recorder/http/handlers.js +219 -0
- package/dist/src/recorder/http/wrapper-config.d.ts +20 -0
- package/dist/src/recorder/http/wrapper-config.js +82 -0
- package/dist/src/recorder/http/wrapper-envelope.d.ts +31 -0
- package/dist/src/recorder/http/wrapper-envelope.js +51 -0
- package/dist/src/recorder/http/wrapper-gates.d.ts +16 -0
- package/dist/src/recorder/http/wrapper-gates.js +28 -0
- package/dist/src/recorder/http/wrapper-metrics.d.ts +1 -0
- package/dist/src/recorder/http/wrapper-metrics.js +5 -0
- package/dist/src/recorder/http/wrapper-registry.d.ts +50 -0
- package/dist/src/recorder/http/wrapper-registry.js +98 -0
- package/dist/src/recorder/http/wrapper-server.d.ts +59 -0
- package/dist/src/recorder/http/wrapper-server.js +240 -0
- package/dist/src/recorder/http/wrapper.test.d.ts +1 -0
- package/dist/src/recorder/observability/logger.d.ts +5 -0
- package/dist/src/recorder/observability/logger.js +13 -0
- package/dist/src/recorder/runner/config.d.ts +34 -0
- package/dist/src/recorder/runner/config.js +84 -0
- package/dist/src/recorder/runner/config.test.d.ts +1 -0
- package/dist/src/recorder/runner/reap.d.ts +79 -0
- package/dist/src/recorder/runner/reap.js +230 -0
- package/dist/src/recorder/runner/reap.test.d.ts +1 -0
- package/dist/src/recorder/runner/runner-port.d.ts +95 -0
- package/dist/src/recorder/runner/runner-port.js +518 -0
- package/dist/src/recorder/runner/runner-port.test.d.ts +1 -0
- package/dist/src/recorder/runner/session-keys.d.ts +28 -0
- package/dist/src/recorder/runner/session-keys.js +72 -0
- package/dist/src/recorder/runner/session-keys.test.d.ts +1 -0
- package/dist/src/recorder/runner/verify-runner-main.d.ts +96 -0
- package/dist/src/recorder/runner/verify-runner-main.js +292 -0
- package/dist/src/recorder/runner/verify-runner-main.test.d.ts +1 -0
- package/dist/src/registry-api.d.ts +1 -1
- package/dist/src/registry-api.types.test.d.ts +1 -0
- package/dist/src/registry-transaction.d.ts +42 -0
- package/dist/src/registry-transaction.js +194 -0
- package/dist/src/registry-transaction.test.d.ts +1 -0
- package/dist/src/registry.d.ts +58 -16
- package/dist/src/registry.js +131 -15
- package/dist/src/serialization.d.ts +1 -1
- package/dist/src/serialization.js +3 -3
- package/dist/src/types.d.ts +2 -0
- package/package.json +8 -5
- package/scripts/m1-daemon-navigate-drive.mjs +138 -0
- package/scripts/m1-extension-spike.mjs +237 -0
- package/scripts/m1-live-spike.mjs +156 -0
- package/scripts/m6b-connect-back-spike.sh +31 -0
- package/clis/12306/utils.test.js +0 -331
- package/clis/1688/assets.test.js +0 -39
- package/clis/1688/download.test.js +0 -31
- package/clis/1688/item.test.js +0 -67
- package/clis/1688/search.test.js +0 -75
- package/clis/1688/shared.test.js +0 -57
- package/clis/1688/store.test.js +0 -62
- package/clis/36kr/article.test.js +0 -46
- package/clis/36kr/hot.test.js +0 -15
- package/clis/36kr/news.test.js +0 -85
- package/clis/51job/utils.test.js +0 -69
- package/clis/_atlassian/shared.test.js +0 -170
- package/clis/aibase/news.test.js +0 -59
- package/clis/amazon/bestsellers.test.js +0 -29
- package/clis/amazon/discussion.test.js +0 -124
- package/clis/amazon/offer.test.js +0 -29
- package/clis/amazon/product.test.js +0 -24
- package/clis/amazon/rankings.test.js +0 -41
- package/clis/amazon/search.test.js +0 -22
- package/clis/amazon/shared.test.js +0 -44
- package/clis/apple-podcasts/commands.test.js +0 -119
- package/clis/apple-podcasts/utils.test.js +0 -57
- package/clis/arxiv/arxiv.test.js +0 -112
- package/clis/baidu-scholar/search.test.js +0 -23
- package/clis/barchart/greeks.test.js +0 -138
- package/clis/bilibili/comment.test.js +0 -153
- package/clis/bilibili/comments.test.js +0 -142
- package/clis/bilibili/dynamic.test.js +0 -68
- package/clis/bilibili/hot.test.js +0 -17
- package/clis/bilibili/subtitle.test.js +0 -196
- package/clis/bilibili/summary.test.js +0 -210
- package/clis/bilibili/utils.test.js +0 -61
- package/clis/bilibili/video.test.js +0 -132
- package/clis/binance/commands.test.js +0 -70
- package/clis/bloomberg/utils.test.js +0 -129
- package/clis/booking/booking.test.js +0 -356
- package/clis/boss/chatlist.test.js +0 -211
- package/clis/boss/chatmsg.test.js +0 -230
- package/clis/boss/search.test.js +0 -78
- package/clis/boss/utils.test.js +0 -34
- package/clis/brave/search.test.js +0 -76
- package/clis/chaoxing/utils.test.js +0 -45
- package/clis/chatgpt/commands.test.js +0 -45
- package/clis/chatgpt/envelope.test.js +0 -108
- package/clis/chatgpt/image.test.js +0 -188
- package/clis/chatgpt/utils.test.js +0 -330
- package/clis/chatgpt-app/ax.test.js +0 -35
- package/clis/chatwise/composer.test.js +0 -186
- package/clis/chess/analyze.test.js +0 -79
- package/clis/chess/game.test.js +0 -178
- package/clis/chess/games.test.js +0 -164
- package/clis/chess/stats.test.js +0 -79
- package/clis/chess/utils.test.js +0 -230
- package/clis/claude/ask.test.js +0 -338
- package/clis/claude/commands.test.js +0 -118
- package/clis/claude/utils.test.js +0 -148
- package/clis/cnki/search.test.js +0 -18
- package/clis/codex/sidebar.test.js +0 -329
- package/clis/coingecko/coingecko.test.js +0 -109
- package/clis/confluence/commands.test.js +0 -195
- package/clis/coupang/coupang.test.js +0 -159
- package/clis/coupang/utils.test.js +0 -62
- package/clis/ctrip/ctrip.test.js +0 -719
- package/clis/dblp/dblp.test.js +0 -397
- package/clis/deepseek/ask.test.js +0 -312
- package/clis/deepseek/detail.test.js +0 -81
- package/clis/deepseek/send.test.js +0 -107
- package/clis/deepseek/utils.test.js +0 -370
- package/clis/defillama/defillama.test.js +0 -99
- package/clis/devto/devto.test.js +0 -236
- package/clis/dianping/dianping.test.js +0 -578
- package/clis/douban/download.test.js +0 -170
- package/clis/douban/movie-hot.test.js +0 -14
- package/clis/douban/search.test.js +0 -11
- package/clis/douban/subject.test.js +0 -11
- package/clis/douban/utils.test.js +0 -438
- package/clis/doubao/detail.test.js +0 -42
- package/clis/doubao/history.test.js +0 -37
- package/clis/doubao/utils.test.js +0 -344
- package/clis/douyin/_shared/browser-fetch.test.js +0 -64
- package/clis/douyin/_shared/creation-id.test.js +0 -22
- package/clis/douyin/_shared/imagex-upload.test.js +0 -87
- package/clis/douyin/_shared/sts2.test.js +0 -27
- package/clis/douyin/_shared/text-extra.test.js +0 -37
- package/clis/douyin/_shared/timing.test.js +0 -28
- package/clis/douyin/_shared/tos-upload-short-read.test.js +0 -83
- package/clis/douyin/_shared/tos-upload.test.js +0 -229
- package/clis/douyin/_shared/transcode.test.js +0 -91
- package/clis/douyin/_shared/vod-upload.test.js +0 -38
- package/clis/douyin/activities.test.js +0 -55
- package/clis/douyin/collections.test.js +0 -45
- package/clis/douyin/delete.test.js +0 -100
- package/clis/douyin/draft.test.js +0 -335
- package/clis/douyin/drafts.test.js +0 -11
- package/clis/douyin/hashtag.test.js +0 -171
- package/clis/douyin/location.test.js +0 -23
- package/clis/douyin/profile.test.js +0 -46
- package/clis/douyin/publish-upload-id.test.js +0 -170
- package/clis/douyin/publish.test.js +0 -38
- package/clis/douyin/stats.test.js +0 -22
- package/clis/douyin/update.test.js +0 -11
- package/clis/douyin/user-videos.test.js +0 -151
- package/clis/douyin/videos.test.js +0 -54
- package/clis/duckduckgo/search.test.js +0 -128
- package/clis/duckduckgo/suggest.test.js +0 -66
- package/clis/eastmoney/hot-rank.test.js +0 -59
- package/clis/endoflife/endoflife.test.js +0 -51
- package/clis/facebook/feed.test.js +0 -169
- package/clis/facebook/marketplace.test.js +0 -91
- package/clis/facebook/notifications.test.js +0 -458
- package/clis/facebook/search.test.js +0 -55
- package/clis/flathub/flathub.test.js +0 -90
- package/clis/flomo/memos.test.js +0 -144
- package/clis/gemini/ask.test.js +0 -100
- package/clis/gemini/deep-research-result.test.js +0 -155
- package/clis/gemini/deep-research.test.js +0 -181
- package/clis/gemini/reply-state.test.js +0 -671
- package/clis/gemini/utils.test.js +0 -198
- package/clis/geogebra/geogebra.test.js +0 -175
- package/clis/gitee/search.test.js +0 -65
- package/clis/gitee/user.test.js +0 -63
- package/clis/google/utils.test.js +0 -75
- package/clis/google-scholar/cite.test.js +0 -47
- package/clis/google-scholar/profile.test.js +0 -49
- package/clis/google-scholar/search.test.js +0 -71
- package/clis/goproxy/goproxy.test.js +0 -103
- package/clis/gov-law/commands.test.js +0 -39
- package/clis/gov-policy/gov-policy.test.js +0 -224
- package/clis/grok/ask.test.js +0 -29
- package/clis/grok/utils.test.js +0 -103
- package/clis/hackernews/hackernews.test.js +0 -132
- package/clis/hf/hf.test.js +0 -16
- package/clis/hupu/hot.test.js +0 -224
- package/clis/imdb/utils.test.js +0 -88
- package/clis/indeed/indeed.test.js +0 -375
- package/clis/instagram/_shared/private-publish.test.js +0 -705
- package/clis/instagram/_shared/protocol-capture.test.js +0 -114
- package/clis/instagram/download.test.js +0 -118
- package/clis/instagram/note.test.js +0 -53
- package/clis/instagram/post.test.js +0 -1647
- package/clis/instagram/reel.test.js +0 -167
- package/clis/instagram/story.test.js +0 -134
- package/clis/jd/commands.test.js +0 -41
- package/clis/jd/item.test.js +0 -354
- package/clis/jianyu/search.test.js +0 -153
- package/clis/jianyu/shared/procurement-contract.test.js +0 -72
- package/clis/jianyu/shared/procurement-detail.test.js +0 -84
- package/clis/jike/read.test.js +0 -86
- package/clis/jira/commands.test.js +0 -287
- package/clis/juejin/search.js +0 -123
- package/clis/juejin/search.test.js +0 -98
- package/clis/lesswrong/frontpage.test.js +0 -37
- package/clis/lichess/lichess.test.js +0 -85
- package/clis/linkedin/connect.test.js +0 -213
- package/clis/linkedin/inbox.test.js +0 -152
- package/clis/linkedin/job-detail.test.js +0 -38
- package/clis/linkedin/jobs-preferences.test.js +0 -43
- package/clis/linkedin/people-search.test.js +0 -216
- package/clis/linkedin/post-analytics.test.js +0 -40
- package/clis/linkedin/posts.test.js +0 -40
- package/clis/linkedin/profile-analytics.test.js +0 -67
- package/clis/linkedin/profile-experience.test.js +0 -152
- package/clis/linkedin/profile-projects.test.js +0 -111
- package/clis/linkedin/profile-read.test.js +0 -77
- package/clis/linkedin/safe-send.test.js +0 -204
- package/clis/linkedin/salesnav-inbox.test.js +0 -113
- package/clis/linkedin/salesnav-message.test.js +0 -172
- package/clis/linkedin/salesnav-search.test.js +0 -76
- package/clis/linkedin/salesnav-thread.test.js +0 -79
- package/clis/linkedin/search.test.js +0 -222
- package/clis/linkedin/sent-invitations.test.js +0 -62
- package/clis/linkedin/services-read.test.js +0 -105
- package/clis/linkedin/thread-snapshot.test.js +0 -89
- package/clis/linkedin/timeline.test.js +0 -81
- package/clis/linkedin-learning/course.test.js +0 -114
- package/clis/linkedin-learning/search.test.js +0 -144
- package/clis/linkedin-learning/trending.test.js +0 -123
- package/clis/linux-do/feed.test.js +0 -153
- package/clis/linux-do/topic-content.test.js +0 -59
- package/clis/lobsters/lobsters.test.js +0 -169
- package/clis/notebooklm/add-source.test.js +0 -97
- package/clis/notebooklm/compat.test.js +0 -16
- package/clis/notebooklm/create.test.js +0 -58
- package/clis/notebooklm/generate-audio.test.js +0 -63
- package/clis/notebooklm/generate-slides.test.js +0 -75
- package/clis/notebooklm/history.test.js +0 -58
- package/clis/notebooklm/note-list.test.js +0 -56
- package/clis/notebooklm/notes-get.test.js +0 -72
- package/clis/notebooklm/open.test.js +0 -63
- package/clis/notebooklm/rpc.test.js +0 -131
- package/clis/notebooklm/source-fulltext.test.js +0 -106
- package/clis/notebooklm/source-get.test.js +0 -84
- package/clis/notebooklm/source-guide.test.js +0 -104
- package/clis/notebooklm/summary.test.js +0 -78
- package/clis/notebooklm/utils.test.js +0 -449
- package/clis/notebooklm/write-note.test.js +0 -70
- package/clis/nuget/nuget.test.js +0 -111
- package/clis/oeis/oeis.test.js +0 -88
- package/clis/ones/task-helpers.test.js +0 -12
- package/clis/ones/worklog.test.js +0 -20
- package/clis/openfda/openfda.test.js +0 -114
- package/clis/openreview/openreview.test.js +0 -427
- package/clis/osv/osv.test.js +0 -97
- package/clis/paperreview/commands.test.js +0 -243
- package/clis/paperreview/utils.test.js +0 -49
- package/clis/pixiv/download.test.js +0 -87
- package/clis/pixiv/illusts.test.js +0 -99
- package/clis/pixiv/search.test.js +0 -83
- package/clis/powerchina/search.test.js +0 -93
- package/clis/producthunt/utils.test.js +0 -64
- package/clis/pubmed/pubmed.test.js +0 -276
- package/clis/quark/utils.test.js +0 -58
- package/clis/qwen/utils.test.js +0 -45
- package/clis/reddit/extract-media.test.js +0 -149
- package/clis/reddit/frontpage.test.js +0 -34
- package/clis/reddit/home.test.js +0 -170
- package/clis/reddit/hot.test.js +0 -32
- package/clis/reddit/popular.test.js +0 -26
- package/clis/reddit/read.test.js +0 -335
- package/clis/reddit/reply.test.js +0 -89
- package/clis/reddit/search.test.js +0 -26
- package/clis/reddit/subreddit-info.test.js +0 -163
- package/clis/reddit/subreddit.test.js +0 -31
- package/clis/reddit/subscribed.test.js +0 -168
- package/clis/reddit/whoami.test.js +0 -105
- package/clis/rednote/navigation.test.js +0 -26
- package/clis/rednote/rednote.test.js +0 -222
- package/clis/rest-countries/rest-countries.test.js +0 -83
- package/clis/reuters/reuters.test.js +0 -299
- package/clis/rfc/rfc.test.js +0 -74
- package/clis/sinafinance/stock.test.js +0 -59
- package/clis/spotify/utils.test.js +0 -67
- package/clis/stackoverflow/stackoverflow.test.js +0 -404
- package/clis/steam/steam.test.js +0 -46
- package/clis/substack/utils.test.js +0 -44
- package/clis/suno/commands.test.js +0 -188
- package/clis/suno/download.test.js +0 -151
- package/clis/suno/generate.test.js +0 -252
- package/clis/suno/utils.test.js +0 -329
- package/clis/taobao/commands.test.js +0 -41
- package/clis/tdx/hot-rank.test.js +0 -59
- package/clis/ths/hot-rank.test.js +0 -64
- package/clis/tieba/commands.test.js +0 -79
- package/clis/tieba/utils.test.js +0 -290
- package/clis/tiktok/creator-videos.test.js +0 -113
- package/clis/tiktok/refactor.test.js +0 -389
- package/clis/tiktok/write-refactor.test.js +0 -370
- package/clis/toutiao/toutiao.test.js +0 -378
- package/clis/tvmaze/tvmaze.test.js +0 -93
- package/clis/twitter/bookmark-folder.test.js +0 -395
- package/clis/twitter/bookmark-folders.test.js +0 -152
- package/clis/twitter/bookmark.test.js +0 -74
- package/clis/twitter/bookmarks.test.js +0 -205
- package/clis/twitter/delete.test.js +0 -85
- package/clis/twitter/device-follow.test.js +0 -287
- package/clis/twitter/download.test.js +0 -457
- package/clis/twitter/followers.test.js +0 -62
- package/clis/twitter/following.test.js +0 -338
- package/clis/twitter/hide-reply.test.js +0 -76
- package/clis/twitter/like.test.js +0 -73
- package/clis/twitter/likes.test.js +0 -220
- package/clis/twitter/list-add.test.js +0 -133
- package/clis/twitter/list-create.test.js +0 -169
- package/clis/twitter/list-remove.test.js +0 -110
- package/clis/twitter/list-tweets.test.js +0 -196
- package/clis/twitter/lists.test.js +0 -253
- package/clis/twitter/post.test.js +0 -258
- package/clis/twitter/profile.test.js +0 -39
- package/clis/twitter/quote.test.js +0 -194
- package/clis/twitter/reply.test.js +0 -237
- package/clis/twitter/retweet.test.js +0 -73
- package/clis/twitter/search.test.js +0 -349
- package/clis/twitter/shared.test.js +0 -794
- package/clis/twitter/thread.test.js +0 -58
- package/clis/twitter/timeline.test.js +0 -104
- package/clis/twitter/trending.test.js +0 -15
- package/clis/twitter/tweets.test.js +0 -362
- package/clis/twitter/unbookmark.test.js +0 -73
- package/clis/twitter/unlike.test.js +0 -75
- package/clis/twitter/unretweet.test.js +0 -73
- package/clis/twitter/utils.test.js +0 -169
- package/clis/uisdc/news.test.js +0 -66
- package/clis/uiverse/_shared.test.js +0 -62
- package/clis/uiverse/navigation.test.js +0 -12
- package/clis/upwork/upwork.test.js +0 -566
- package/clis/wanfang/search.test.js +0 -23
- package/clis/web/read.test.js +0 -392
- package/clis/weibo/delete.test.js +0 -94
- package/clis/weibo/envelope.test.js +0 -85
- package/clis/weibo/favorites.test.js +0 -114
- package/clis/weibo/publish.test.js +0 -192
- package/clis/weibo/user-posts.test.js +0 -92
- package/clis/weibo/utils.test.js +0 -36
- package/clis/weixin/drafts.test.js +0 -69
- package/clis/weixin/search.test.js +0 -227
- package/clis/weread/ai-outline.test.js +0 -83
- package/clis/weread/book-search.test.js +0 -242
- package/clis/weread/commands.test.js +0 -398
- package/clis/weread/private-api-regression.test.js +0 -369
- package/clis/weread/search-regression.test.js +0 -494
- package/clis/weread/utils.test.js +0 -128
- package/clis/weread-official/commands.test.js +0 -385
- package/clis/weread-official/utils.test.js +0 -242
- package/clis/wikidata/wikidata.test.js +0 -83
- package/clis/wikipedia/trending.test.js +0 -57
- package/clis/wttr/wttr.test.js +0 -84
- package/clis/xianyu/chat.test.js +0 -84
- package/clis/xianyu/im.test.js +0 -253
- package/clis/xianyu/item.test.js +0 -56
- package/clis/xianyu/publish.test.js +0 -220
- package/clis/xianyu/search.test.js +0 -17
- package/clis/xiaoe/xiaoe.test.js +0 -486
- package/clis/xiaohongshu/comments.test.js +0 -258
- package/clis/xiaohongshu/creator-note-detail.test.js +0 -451
- package/clis/xiaohongshu/creator-notes-summary.test.js +0 -94
- package/clis/xiaohongshu/creator-notes.test.js +0 -281
- package/clis/xiaohongshu/creator-stats.test.js +0 -24
- package/clis/xiaohongshu/delete-note.test.js +0 -172
- package/clis/xiaohongshu/download.test.js +0 -316
- package/clis/xiaohongshu/navigation.test.js +0 -34
- package/clis/xiaohongshu/note.test.js +0 -249
- package/clis/xiaohongshu/publish.test.js +0 -608
- package/clis/xiaohongshu/search.test.js +0 -325
- package/clis/xiaohongshu/user-helpers.test.js +0 -160
- package/clis/xiaoyuzhou/auth.test.js +0 -124
- package/clis/xiaoyuzhou/download.test.js +0 -135
- package/clis/xiaoyuzhou/podcast-episodes.test.js +0 -78
- package/clis/xiaoyuzhou/transcript.test.js +0 -195
- package/clis/xiaoyuzhou/utils.test.js +0 -39
- package/clis/xueqiu/comments.test.js +0 -696
- package/clis/xueqiu/danjuan-utils.test.js +0 -41
- package/clis/xueqiu/utils.test.js +0 -26
- package/clis/yahoo/search.test.js +0 -94
- package/clis/youdao/note.test.js +0 -99
- package/clis/youtube/channel.test.js +0 -59
- package/clis/youtube/feed.test.js +0 -131
- package/clis/youtube/transcript-group.test.js +0 -99
- package/clis/youtube/transcript.test.js +0 -296
- package/clis/youtube/utils.test.js +0 -84
- package/clis/yuanbao/ask.test.js +0 -124
- package/clis/yuanbao/new.test.js +0 -30
- package/clis/yuanbao/shared.test.js +0 -80
- package/clis/zhihu/answer-comments.test.js +0 -287
- package/clis/zhihu/answer-detail.test.js +0 -338
- package/clis/zhihu/answer.test.js +0 -54
- package/clis/zhihu/collection.test.js +0 -337
- package/clis/zhihu/collections.test.js +0 -182
- package/clis/zhihu/comment.test.js +0 -50
- package/clis/zhihu/download.test.js +0 -12
- package/clis/zhihu/favorite.test.js +0 -59
- package/clis/zhihu/follow.test.js +0 -42
- package/clis/zhihu/like.test.js +0 -41
- package/clis/zhihu/question.test.js +0 -251
- package/clis/zhihu/recommend.test.js +0 -143
- package/clis/zhihu/search.test.js +0 -198
- package/clis/zhihu/target.test.js +0 -77
- package/clis/zhihu/text.test.js +0 -24
- package/clis/zhihu/write-shared.test.js +0 -176
- package/clis/zlibrary/commands.test.js +0 -65
- package/clis/zsxq/search.test.js +0 -24
- package/clis/zsxq/topic.test.js +0 -30
- package/clis/zsxq/topics.test.js +0 -24
- package/clis/zsxq/utils.test.js +0 -31
- package/dist/src/adapter-shadow.test.js +0 -49
- package/dist/src/adapter-source.test.js +0 -29
- package/dist/src/browser/analyze.test.js +0 -166
- package/dist/src/browser/article-extract.e2e.test.js +0 -105
- package/dist/src/browser/article-extract.test.js +0 -94
- package/dist/src/browser/ax-snapshot.test.js +0 -91
- package/dist/src/browser/base-page.test.js +0 -758
- package/dist/src/browser/cdp-click-fixture.test.js +0 -87
- package/dist/src/browser/cdp.test.js +0 -79
- package/dist/src/browser/compound.test.js +0 -175
- package/dist/src/browser/daemon-client.test.js +0 -199
- package/dist/src/browser/dom-helpers.test.js +0 -106
- package/dist/src/browser/dom-snapshot.test.js +0 -313
- package/dist/src/browser/errors.test.js +0 -60
- package/dist/src/browser/extract.test.js +0 -129
- package/dist/src/browser/find.test.js +0 -180
- package/dist/src/browser/html-tree.test.js +0 -181
- package/dist/src/browser/network-cache.test.js +0 -58
- package/dist/src/browser/network-key.test.js +0 -49
- package/dist/src/browser/page.test.js +0 -378
- package/dist/src/browser/shape-filter.test.js +0 -101
- package/dist/src/browser/shape.test.js +0 -82
- package/dist/src/browser/stealth.test.js +0 -134
- package/dist/src/browser/target-errors.test.js +0 -94
- package/dist/src/browser/target-resolver.test.js +0 -118
- package/dist/src/browser/utils.test.js +0 -29
- package/dist/src/browser/verify-fixture.test.js +0 -219
- package/dist/src/browser.test.js +0 -232
- package/dist/src/build-manifest.test.js +0 -341
- package/dist/src/capabilityRouting.test.js +0 -63
- package/dist/src/cli-argv-preprocess.test.js +0 -209
- package/dist/src/cli.test.js +0 -2803
- package/dist/src/commanderAdapter.test.js +0 -352
- package/dist/src/commands/daemon.test.js +0 -219
- package/dist/src/completion.test.js +0 -24
- package/dist/src/convention-audit.test.js +0 -247
- package/dist/src/daemon.test.js +0 -60
- package/dist/src/doctor.test.js +0 -263
- package/dist/src/download/article-download.test.js +0 -235
- package/dist/src/download/index.test.js +0 -140
- package/dist/src/download/media-download.test.js +0 -112
- package/dist/src/download/progress.test.js +0 -36
- package/dist/src/electron-apps.test.js +0 -49
- package/dist/src/engine.test.js +0 -312
- package/dist/src/errors.test.js +0 -109
- package/dist/src/execution.test.js +0 -623
- package/dist/src/extension-manifest-regression.test.js +0 -12
- package/dist/src/external.test.js +0 -146
- package/dist/src/help.test.js +0 -58
- package/dist/src/hooks.test.js +0 -92
- package/dist/src/interceptor.test.js +0 -81
- package/dist/src/launcher.test.js +0 -138
- package/dist/src/node-network.test.js +0 -55
- package/dist/src/observation/artifact.test.js +0 -121
- package/dist/src/observation/manager.test.js +0 -13
- package/dist/src/observation/redaction.test.js +0 -32
- package/dist/src/observation/retention.test.js +0 -118
- package/dist/src/observation/ring-buffer.test.js +0 -22
- package/dist/src/output.test.js +0 -53
- package/dist/src/package-exports.test.js +0 -112
- package/dist/src/pipeline/executor.test.js +0 -182
- package/dist/src/pipeline/steps/download.test.js +0 -102
- package/dist/src/pipeline/steps/fetch.test.js +0 -117
- package/dist/src/pipeline/template.test.js +0 -175
- package/dist/src/pipeline/transform.test.js +0 -133
- package/dist/src/plugin-manifest.test.js +0 -179
- package/dist/src/plugin-scaffold.test.js +0 -83
- package/dist/src/plugin.test.js +0 -1324
- package/dist/src/registry.test.js +0 -209
- package/dist/src/runtime-detect.test.js +0 -39
- package/dist/src/serialization.test.js +0 -78
- package/dist/src/snapshotFormatter.test.js +0 -521
- package/dist/src/tui.test.js +0 -19
- package/dist/src/update-check.test.js +0 -116
- package/dist/src/utils.test.js +0 -155
- package/dist/src/validate.test.js +0 -90
- package/dist/src/weixin-download.test.js +0 -45
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import os from 'node:os';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
-
import { ArgumentError } from '@sovovs/bycli/errors';
|
|
6
|
-
import {
|
|
7
|
-
selectModel,
|
|
8
|
-
sendWithFile,
|
|
9
|
-
parseThinkingResponse,
|
|
10
|
-
parseDeepSeekConversationId,
|
|
11
|
-
pickResumeUrl,
|
|
12
|
-
} from './utils.js';
|
|
13
|
-
|
|
14
|
-
describe('deepseek parseDeepSeekConversationId', () => {
|
|
15
|
-
const id = '749e6bbd-6a45-4440-beaa-ae5238bf06d8';
|
|
16
|
-
|
|
17
|
-
it('returns a bare UUID unchanged', () => {
|
|
18
|
-
expect(parseDeepSeekConversationId(id)).toBe(id);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('lowercases an upper-case UUID', () => {
|
|
22
|
-
expect(parseDeepSeekConversationId(id.toUpperCase())).toBe(id);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('extracts the UUID from a full /a/chat/s/<id> URL', () => {
|
|
26
|
-
expect(parseDeepSeekConversationId(`https://chat.deepseek.com/a/chat/s/${id}`)).toBe(id);
|
|
27
|
-
expect(parseDeepSeekConversationId(`https://chat.deepseek.com/a/chat/s/${id}?from=share`)).toBe(id);
|
|
28
|
-
expect(parseDeepSeekConversationId(`/a/chat/s/${id}`)).toBe(id);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('throws ArgumentError on empty input', () => {
|
|
32
|
-
expect(() => parseDeepSeekConversationId('')).toThrow(ArgumentError);
|
|
33
|
-
expect(() => parseDeepSeekConversationId(null)).toThrow(ArgumentError);
|
|
34
|
-
expect(() => parseDeepSeekConversationId(undefined)).toThrow(ArgumentError);
|
|
35
|
-
expect(() => parseDeepSeekConversationId(' ')).toThrow(ArgumentError);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('throws ArgumentError on non-UUID input', () => {
|
|
39
|
-
expect(() => parseDeepSeekConversationId('not-an-id')).toThrow(ArgumentError);
|
|
40
|
-
expect(() => parseDeepSeekConversationId('123')).toThrow(ArgumentError);
|
|
41
|
-
// URL with the wrong path shape must not silently fall through to "use raw input".
|
|
42
|
-
expect(() => parseDeepSeekConversationId('https://chat.deepseek.com/somewhere/else')).toThrow(ArgumentError);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe('deepseek parseThinkingResponse', () => {
|
|
47
|
-
it('returns plain response when no thinking header is present', () => {
|
|
48
|
-
const rawText = 'This is a regular response without thinking.';
|
|
49
|
-
const result = parseThinkingResponse(rawText);
|
|
50
|
-
|
|
51
|
-
expect(result).toEqual({
|
|
52
|
-
response: rawText,
|
|
53
|
-
thinking: null,
|
|
54
|
-
thinking_time: null,
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('parses English thinking header — all content after header is thinking', () => {
|
|
59
|
-
const rawText = 'Thought for 3.5 seconds\n\nLet me analyze this problem...\nFirst, I need to consider X.\nThen, Y.\n\nThe answer is 42.';
|
|
60
|
-
const result = parseThinkingResponse(rawText);
|
|
61
|
-
|
|
62
|
-
// Text-level parser no longer splits on \n\n; everything after header is thinking.
|
|
63
|
-
// DOM-level extraction in waitForResponse() handles the actual separation.
|
|
64
|
-
expect(result).toEqual({
|
|
65
|
-
response: '',
|
|
66
|
-
thinking: 'Let me analyze this problem...\nFirst, I need to consider X.\nThen, Y.\n\nThe answer is 42.',
|
|
67
|
-
thinking_time: '3.5',
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('parses Chinese thinking header — all content after header is thinking', () => {
|
|
72
|
-
const rawText = '已思考(用时 2.3 秒)\n\n让我分析这个问题...\n首先需要考虑X。\n然后是Y。\n\n答案是42。';
|
|
73
|
-
const result = parseThinkingResponse(rawText);
|
|
74
|
-
|
|
75
|
-
expect(result).toEqual({
|
|
76
|
-
response: '',
|
|
77
|
-
thinking: '让我分析这个问题...\n首先需要考虑X。\n然后是Y。\n\n答案是42。',
|
|
78
|
-
thinking_time: '2.3',
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('multi-paragraph thinking without final answer is not corrupted', () => {
|
|
83
|
-
const rawText = 'Thought for 1.2 seconds\n\nFirst paragraph.\n\nSecond paragraph.';
|
|
84
|
-
const result = parseThinkingResponse(rawText);
|
|
85
|
-
|
|
86
|
-
// Both paragraphs must stay in thinking; response is empty.
|
|
87
|
-
expect(result).toEqual({
|
|
88
|
-
response: '',
|
|
89
|
-
thinking: 'First paragraph.\n\nSecond paragraph.',
|
|
90
|
-
thinking_time: '1.2',
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('multi-paragraph final answer is not split by text parser', () => {
|
|
95
|
-
const rawText = 'Thought for 3 seconds\n\nreasoning\n\nAnswer para 1.\n\nAnswer para 2.';
|
|
96
|
-
const result = parseThinkingResponse(rawText);
|
|
97
|
-
|
|
98
|
-
// Text parser treats everything as thinking; DOM handles separation.
|
|
99
|
-
expect(result).toEqual({
|
|
100
|
-
response: '',
|
|
101
|
-
thinking: 'reasoning\n\nAnswer para 1.\n\nAnswer para 2.',
|
|
102
|
-
thinking_time: '3',
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('handles thinking without final response', () => {
|
|
107
|
-
const rawText = 'Thought for 1.2 seconds\n\nThinking process here...';
|
|
108
|
-
const result = parseThinkingResponse(rawText);
|
|
109
|
-
|
|
110
|
-
expect(result).toEqual({
|
|
111
|
-
response: '',
|
|
112
|
-
thinking: 'Thinking process here...',
|
|
113
|
-
thinking_time: '1.2',
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('returns null for empty input', () => {
|
|
118
|
-
const result = parseThinkingResponse('');
|
|
119
|
-
expect(result).toBeNull();
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('returns null for null input', () => {
|
|
123
|
-
const result = parseThinkingResponse(null);
|
|
124
|
-
expect(result).toBeNull();
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
describe('deepseek sendWithFile', () => {
|
|
130
|
-
const tempDirs = [];
|
|
131
|
-
|
|
132
|
-
afterEach(() => {
|
|
133
|
-
vi.restoreAllMocks();
|
|
134
|
-
while (tempDirs.length) {
|
|
135
|
-
fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('prefers page.setFileInput over base64-in-evaluate when supported', async () => {
|
|
140
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bycli-deepseek-'));
|
|
141
|
-
tempDirs.push(dir);
|
|
142
|
-
const filePath = path.join(dir, 'report.txt');
|
|
143
|
-
fs.writeFileSync(filePath, 'hello');
|
|
144
|
-
|
|
145
|
-
const page = {
|
|
146
|
-
setFileInput: vi.fn().mockResolvedValue(undefined),
|
|
147
|
-
wait: vi.fn().mockResolvedValue(undefined),
|
|
148
|
-
evaluate: vi.fn()
|
|
149
|
-
.mockResolvedValueOnce(undefined) // sidebar collapse
|
|
150
|
-
.mockResolvedValueOnce(true) // waitForFilePreview
|
|
151
|
-
.mockResolvedValueOnce(true) // send button enabled check
|
|
152
|
-
.mockResolvedValueOnce({ ok: true }), // sendMessage
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const result = await sendWithFile(page, filePath, 'summarize this');
|
|
156
|
-
|
|
157
|
-
expect(result).toEqual({ ok: true }); expect(page.setFileInput).toHaveBeenCalledWith([filePath], 'input[type="file"]');
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it('fails closed when upload preview appears but send button never enables', async () => {
|
|
161
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bycli-deepseek-'));
|
|
162
|
-
tempDirs.push(dir);
|
|
163
|
-
const filePath = path.join(dir, 'report.txt');
|
|
164
|
-
fs.writeFileSync(filePath, 'hello');
|
|
165
|
-
|
|
166
|
-
const page = {
|
|
167
|
-
setFileInput: vi.fn().mockResolvedValue(undefined),
|
|
168
|
-
wait: vi.fn().mockResolvedValue(undefined),
|
|
169
|
-
evaluate: vi.fn()
|
|
170
|
-
.mockResolvedValueOnce(undefined) // sidebar collapse
|
|
171
|
-
.mockResolvedValueOnce(true) // waitForFilePreview
|
|
172
|
-
.mockResolvedValue(false), // send button never enables
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const result = await sendWithFile(page, filePath, 'summarize this');
|
|
176
|
-
|
|
177
|
-
expect(result).toEqual({ ok: false, reason: 'send button did not enable after upload' });
|
|
178
|
-
expect(page.evaluate).toHaveBeenCalledTimes(17);
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
describe('deepseek selectModel', () => {
|
|
183
|
-
afterEach(() => {
|
|
184
|
-
vi.restoreAllMocks();
|
|
185
|
-
delete global.document;
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('fails expert selection when only one radio is present', async () => {
|
|
189
|
-
const instantRadio = {
|
|
190
|
-
getAttribute: vi.fn(() => 'true'),
|
|
191
|
-
click: vi.fn(),
|
|
192
|
-
};
|
|
193
|
-
global.document = {
|
|
194
|
-
querySelectorAll: vi.fn(() => [instantRadio]),
|
|
195
|
-
};
|
|
196
|
-
const page = {
|
|
197
|
-
evaluate: vi.fn(async (script) => eval(script)),
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const result = await selectModel(page, 'expert');
|
|
201
|
-
|
|
202
|
-
expect(result).toEqual({ ok: false });
|
|
203
|
-
expect(instantRadio.click).not.toHaveBeenCalled();
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it('selects the correct radio for each model', async () => {
|
|
207
|
-
const radios = [0, 1, 2].map(() => ({
|
|
208
|
-
getAttribute: vi.fn(() => 'false'),
|
|
209
|
-
click: vi.fn(),
|
|
210
|
-
}));
|
|
211
|
-
global.document = {
|
|
212
|
-
querySelectorAll: vi.fn(() => radios),
|
|
213
|
-
};
|
|
214
|
-
const page = {
|
|
215
|
-
evaluate: vi.fn(async (script) => eval(script)),
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
await selectModel(page, 'instant');
|
|
219
|
-
expect(radios[0].click).toHaveBeenCalled();
|
|
220
|
-
expect(radios[1].click).not.toHaveBeenCalled();
|
|
221
|
-
expect(radios[2].click).not.toHaveBeenCalled();
|
|
222
|
-
|
|
223
|
-
radios.forEach(r => r.click.mockClear());
|
|
224
|
-
await selectModel(page, 'expert');
|
|
225
|
-
expect(radios[1].click).toHaveBeenCalled();
|
|
226
|
-
|
|
227
|
-
radios.forEach(r => r.click.mockClear());
|
|
228
|
-
await selectModel(page, 'vision');
|
|
229
|
-
expect(radios[2].click).toHaveBeenCalled();
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('rejects unknown model names', async () => {
|
|
233
|
-
const radios = [0, 1, 2].map(() => ({
|
|
234
|
-
getAttribute: vi.fn(() => 'false'),
|
|
235
|
-
click: vi.fn(),
|
|
236
|
-
}));
|
|
237
|
-
global.document = {
|
|
238
|
-
querySelectorAll: vi.fn(() => radios),
|
|
239
|
-
};
|
|
240
|
-
const page = {
|
|
241
|
-
evaluate: vi.fn(async (script) => eval(script)),
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
const result = await selectModel(page, 'turbo');
|
|
245
|
-
expect(result).toEqual({ ok: false });
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe('deepseek sendWithFile Not allowed fallback', () => {
|
|
250
|
-
const tempDirs = [];
|
|
251
|
-
|
|
252
|
-
afterEach(() => {
|
|
253
|
-
vi.restoreAllMocks();
|
|
254
|
-
while (tempDirs.length) {
|
|
255
|
-
fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it('falls back to DataTransfer when setFileInput throws Not allowed', async () => {
|
|
260
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bycli-deepseek-'));
|
|
261
|
-
tempDirs.push(dir);
|
|
262
|
-
const filePath = path.join(dir, 'image.png');
|
|
263
|
-
fs.writeFileSync(filePath, 'fake-png');
|
|
264
|
-
|
|
265
|
-
const page = {
|
|
266
|
-
setFileInput: vi.fn().mockRejectedValue(new Error('Not allowed')),
|
|
267
|
-
wait: vi.fn().mockResolvedValue(undefined),
|
|
268
|
-
evaluate: vi.fn()
|
|
269
|
-
.mockResolvedValueOnce(undefined) // sidebar collapse
|
|
270
|
-
.mockResolvedValueOnce({ ok: true }) // DataTransfer fallback
|
|
271
|
-
.mockResolvedValueOnce(true) // waitForFilePreview
|
|
272
|
-
.mockResolvedValueOnce(true) // send button enabled
|
|
273
|
-
.mockResolvedValueOnce({ ok: true }),// sendMessage
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
const result = await sendWithFile(page, filePath, 'describe');
|
|
277
|
-
|
|
278
|
-
expect(page.setFileInput).toHaveBeenCalled();
|
|
279
|
-
expect(page.evaluate).toHaveBeenCalledTimes(5);
|
|
280
|
-
expect(result).toEqual({ ok: true });
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
it('does not treat send-button enablement alone as image upload proof', async () => {
|
|
284
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bycli-deepseek-'));
|
|
285
|
-
tempDirs.push(dir);
|
|
286
|
-
const filePath = path.join(dir, 'image.png');
|
|
287
|
-
fs.writeFileSync(filePath, 'fake-png');
|
|
288
|
-
|
|
289
|
-
const page = {
|
|
290
|
-
setFileInput: vi.fn().mockResolvedValue(undefined),
|
|
291
|
-
wait: vi.fn().mockResolvedValue(undefined),
|
|
292
|
-
evaluate: vi.fn()
|
|
293
|
-
.mockResolvedValueOnce(undefined) // sidebar collapse
|
|
294
|
-
.mockResolvedValue(false), // no filename / thumbnail preview
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
const result = await sendWithFile(page, filePath, 'describe');
|
|
298
|
-
|
|
299
|
-
expect(result).toEqual({ ok: false, reason: 'file preview did not appear' });
|
|
300
|
-
expect(page.evaluate.mock.calls[1][0]).toContain('img[src], canvas, video');
|
|
301
|
-
expect(page.evaluate.mock.calls[1][0]).not.toContain("aria-disabled') === 'false'");
|
|
302
|
-
});
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
describe('deepseek pickResumeUrl', () => {
|
|
306
|
-
function createPage() {
|
|
307
|
-
return {
|
|
308
|
-
wait: vi.fn().mockResolvedValue(undefined),
|
|
309
|
-
evaluate: vi.fn(),
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
it('returns the URL on the first attempt when the sidebar is already populated', async () => {
|
|
314
|
-
const page = createPage();
|
|
315
|
-
// First evaluate is the sidebar-expand no-op; subsequent ones look up the resume URL.
|
|
316
|
-
page.evaluate
|
|
317
|
-
.mockResolvedValueOnce(undefined)
|
|
318
|
-
.mockResolvedValueOnce('https://chat.deepseek.com/a/chat/s/recent-id');
|
|
319
|
-
|
|
320
|
-
const url = await pickResumeUrl(page);
|
|
321
|
-
|
|
322
|
-
expect(url).toBe('https://chat.deepseek.com/a/chat/s/recent-id');
|
|
323
|
-
// Sidebar expand + one resume lookup. No retry needed.
|
|
324
|
-
expect(page.evaluate).toHaveBeenCalledTimes(2);
|
|
325
|
-
expect(page.wait).toHaveBeenCalledTimes(1);
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
it('polls until the sidebar finishes loading and returns the late URL', async () => {
|
|
329
|
-
const page = createPage();
|
|
330
|
-
page.evaluate
|
|
331
|
-
.mockResolvedValueOnce(undefined) // sidebar-expand
|
|
332
|
-
.mockResolvedValueOnce(null) // attempt 1: nothing
|
|
333
|
-
.mockResolvedValueOnce(null) // attempt 2: nothing
|
|
334
|
-
.mockResolvedValueOnce('https://chat.deepseek.com/a/chat/s/late-id'); // attempt 3: ready
|
|
335
|
-
|
|
336
|
-
const url = await pickResumeUrl(page);
|
|
337
|
-
|
|
338
|
-
expect(url).toBe('https://chat.deepseek.com/a/chat/s/late-id');
|
|
339
|
-
expect(page.evaluate).toHaveBeenCalledTimes(4);
|
|
340
|
-
expect(page.wait).toHaveBeenCalledTimes(3);
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it('returns null after exhausting all retries instead of falling through silently', async () => {
|
|
344
|
-
const page = createPage();
|
|
345
|
-
// Sidebar expand + 5 polling attempts, each returning null.
|
|
346
|
-
page.evaluate.mockResolvedValue(null);
|
|
347
|
-
|
|
348
|
-
const url = await pickResumeUrl(page);
|
|
349
|
-
|
|
350
|
-
expect(url).toBeNull();
|
|
351
|
-
expect(page.evaluate).toHaveBeenCalledTimes(6);
|
|
352
|
-
expect(page.wait).toHaveBeenCalledTimes(5);
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it('embeds the pinned-section text matcher inside the resume lookup', async () => {
|
|
356
|
-
const page = createPage();
|
|
357
|
-
page.evaluate.mockResolvedValue(null);
|
|
358
|
-
|
|
359
|
-
await pickResumeUrl(page);
|
|
360
|
-
|
|
361
|
-
const lookupSrc = page.evaluate.mock.calls
|
|
362
|
-
.map(([js]) => js)
|
|
363
|
-
.find((js) => js.includes('firstElementChild'));
|
|
364
|
-
expect(lookupSrc, 'expected a resume-lookup evaluate call').toBeDefined();
|
|
365
|
-
// Pinned detection must be text-based on the section header (CSS-module class names are randomized per build).
|
|
366
|
-
expect(lookupSrc).toContain('置');
|
|
367
|
-
expect(lookupSrc).toContain('Pinned');
|
|
368
|
-
expect(lookupSrc).toContain('firstElementChild');
|
|
369
|
-
});
|
|
370
|
-
});
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { getRegistry } from '@sovovs/bycli/registry';
|
|
3
|
-
import { ArgumentError, CommandExecutionError, EmptyResultError } from '@sovovs/bycli/errors';
|
|
4
|
-
import './protocols.js';
|
|
5
|
-
import './protocol.js';
|
|
6
|
-
|
|
7
|
-
afterEach(() => {
|
|
8
|
-
vi.unstubAllGlobals();
|
|
9
|
-
vi.restoreAllMocks();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
describe('defillama protocols adapter', () => {
|
|
13
|
-
const cmd = getRegistry().get('defillama/protocols');
|
|
14
|
-
|
|
15
|
-
it('rejects bad limit before fetching', async () => {
|
|
16
|
-
const fetchMock = vi.fn();
|
|
17
|
-
vi.stubGlobal('fetch', fetchMock);
|
|
18
|
-
|
|
19
|
-
await expect(cmd.func({ limit: 0 })).rejects.toThrow(ArgumentError);
|
|
20
|
-
await expect(cmd.func({ limit: 1000 })).rejects.toThrow(ArgumentError);
|
|
21
|
-
expect(fetchMock).not.toHaveBeenCalled();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('maps HTTP 429 to CommandExecutionError', async () => {
|
|
25
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response('rate limited', { status: 429 })));
|
|
26
|
-
await expect(cmd.func({ limit: 5 })).rejects.toThrow(CommandExecutionError);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('throws EmptyResultError when API returns no protocols', async () => {
|
|
30
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response(JSON.stringify([]), { status: 200 })));
|
|
31
|
-
await expect(cmd.func({ limit: 5 })).rejects.toThrow(EmptyResultError);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('returns rows whose slug round-trips into defillama protocol <slug>', async () => {
|
|
35
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response(JSON.stringify([
|
|
36
|
-
{ name: 'Aave V3', slug: 'aave-v3', tvl: 1000, mcap: 500, category: 'Lending', chains: ['Ethereum', 'Polygon'], change_1d: 1, change_7d: 2, listedAt: 1668170565 },
|
|
37
|
-
{ name: 'Lido', slug: 'lido', tvl: 800, mcap: 200, category: 'Liquid Staking', chains: ['Ethereum'], change_1d: 0.5, change_7d: 1, listedAt: 1640000000 },
|
|
38
|
-
]), { status: 200 })));
|
|
39
|
-
|
|
40
|
-
const rows = await cmd.func({ limit: 10 });
|
|
41
|
-
expect(rows).toHaveLength(2);
|
|
42
|
-
expect(rows[0]).toMatchObject({
|
|
43
|
-
rank: 1, slug: 'aave-v3', name: 'Aave V3', category: 'Lending', tvl: 1000,
|
|
44
|
-
chains: 'Ethereum, Polygon', url: 'https://defillama.com/protocol/aave-v3',
|
|
45
|
-
});
|
|
46
|
-
// slug is the round-trip key into defillama protocol
|
|
47
|
-
expect(rows[0].slug).toMatch(/^[a-z0-9][a-z0-9._-]*$/);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('defillama protocol adapter', () => {
|
|
52
|
-
const cmd = getRegistry().get('defillama/protocol');
|
|
53
|
-
|
|
54
|
-
it('rejects empty / malformed slug before fetching', async () => {
|
|
55
|
-
const fetchMock = vi.fn();
|
|
56
|
-
vi.stubGlobal('fetch', fetchMock);
|
|
57
|
-
|
|
58
|
-
await expect(cmd.func({ slug: '' })).rejects.toThrow(ArgumentError);
|
|
59
|
-
await expect(cmd.func({ slug: 'BAD SLUG' })).rejects.toThrow(ArgumentError);
|
|
60
|
-
expect(fetchMock).not.toHaveBeenCalled();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('maps HTTP 400 "Protocol not found" to EmptyResultError', async () => {
|
|
64
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response('Protocol not found', { status: 400 })));
|
|
65
|
-
await expect(cmd.func({ slug: 'no-such-thing' })).rejects.toThrow(EmptyResultError);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('parent protocols aggregate chains from children in /protocols', async () => {
|
|
69
|
-
const detail = {
|
|
70
|
-
id: 'parent#aave',
|
|
71
|
-
name: 'Aave',
|
|
72
|
-
isParentProtocol: true,
|
|
73
|
-
chains: [],
|
|
74
|
-
tvl: [{ date: 1700000000, totalLiquidityUSD: 12345 }],
|
|
75
|
-
mcap: 1e9,
|
|
76
|
-
twitter: 'aave',
|
|
77
|
-
github: ['aave'],
|
|
78
|
-
description: 'lending',
|
|
79
|
-
url: 'https://aave.com',
|
|
80
|
-
};
|
|
81
|
-
const list = [
|
|
82
|
-
{ name: 'Aave V3', slug: 'aave-v3', parentProtocol: 'parent#aave', chains: ['Ethereum', 'Polygon'], category: 'Lending' },
|
|
83
|
-
{ name: 'Aave V2', slug: 'aave-v2', parentProtocol: 'parent#aave', chains: ['Ethereum'], category: 'Lending' },
|
|
84
|
-
{ name: 'Other', slug: 'other', chains: ['Solana'] },
|
|
85
|
-
];
|
|
86
|
-
const fetchMock = vi.fn()
|
|
87
|
-
.mockImplementationOnce(() => Promise.resolve(new Response(JSON.stringify(detail), { status: 200 })))
|
|
88
|
-
.mockImplementationOnce(() => Promise.resolve(new Response(JSON.stringify(list), { status: 200 })));
|
|
89
|
-
vi.stubGlobal('fetch', fetchMock);
|
|
90
|
-
|
|
91
|
-
const rows = await cmd.func({ slug: 'aave' });
|
|
92
|
-
expect(rows).toHaveLength(1);
|
|
93
|
-
expect(rows[0]).toMatchObject({
|
|
94
|
-
slug: 'aave', name: 'Aave', isParent: true, tvl: 12345, tvlAt: '2023-11-14',
|
|
95
|
-
});
|
|
96
|
-
// chains should include Ethereum + Polygon (children) but not Solana (unrelated)
|
|
97
|
-
expect(rows[0].chains.split(', ').sort()).toEqual(['Ethereum', 'Polygon']);
|
|
98
|
-
});
|
|
99
|
-
});
|