@jackwener/opencli 1.4.0 → 1.4.1

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 (209) hide show
  1. package/.github/actions/setup-chrome/action.yml +5 -4
  2. package/.github/workflows/ci.yml +17 -3
  3. package/.github/workflows/e2e-headed.yml +16 -3
  4. package/CHANGELOG.md +23 -0
  5. package/PRIVACY.md +57 -0
  6. package/README.md +1 -1
  7. package/README.zh-CN.md +1 -1
  8. package/SKILL.md +101 -2
  9. package/dist/cli-manifest.json +720 -32
  10. package/dist/clis/apple-podcasts/search.js +2 -1
  11. package/dist/clis/arxiv/search.js +2 -2
  12. package/dist/clis/bbc/news.js +0 -1
  13. package/dist/clis/ctrip/search.js +0 -1
  14. package/dist/clis/douyin/_shared/browser-fetch.d.ts +10 -0
  15. package/dist/clis/douyin/_shared/browser-fetch.js +30 -0
  16. package/dist/clis/douyin/_shared/browser-fetch.test.d.ts +1 -0
  17. package/dist/clis/douyin/_shared/browser-fetch.test.js +31 -0
  18. package/dist/clis/douyin/_shared/creation-id.d.ts +1 -0
  19. package/dist/clis/douyin/_shared/creation-id.js +5 -0
  20. package/dist/clis/douyin/_shared/creation-id.test.d.ts +1 -0
  21. package/dist/clis/douyin/_shared/creation-id.test.js +22 -0
  22. package/dist/clis/douyin/_shared/imagex-upload.d.ts +20 -0
  23. package/dist/clis/douyin/_shared/imagex-upload.js +53 -0
  24. package/dist/clis/douyin/_shared/imagex-upload.test.d.ts +1 -0
  25. package/dist/clis/douyin/_shared/imagex-upload.test.js +87 -0
  26. package/dist/clis/douyin/_shared/sts2.d.ts +8 -0
  27. package/dist/clis/douyin/_shared/sts2.js +15 -0
  28. package/dist/clis/douyin/_shared/text-extra.d.ts +18 -0
  29. package/dist/clis/douyin/_shared/text-extra.js +15 -0
  30. package/dist/clis/douyin/_shared/text-extra.test.d.ts +1 -0
  31. package/dist/clis/douyin/_shared/text-extra.test.js +37 -0
  32. package/dist/clis/douyin/_shared/timing.d.ts +2 -0
  33. package/dist/clis/douyin/_shared/timing.js +22 -0
  34. package/dist/clis/douyin/_shared/timing.test.d.ts +1 -0
  35. package/dist/clis/douyin/_shared/timing.test.js +28 -0
  36. package/dist/clis/douyin/_shared/tos-upload-short-read.test.d.ts +11 -0
  37. package/dist/clis/douyin/_shared/tos-upload-short-read.test.js +83 -0
  38. package/dist/clis/douyin/_shared/tos-upload.d.ts +53 -0
  39. package/dist/clis/douyin/_shared/tos-upload.js +295 -0
  40. package/dist/clis/douyin/_shared/tos-upload.test.d.ts +1 -0
  41. package/dist/clis/douyin/_shared/tos-upload.test.js +229 -0
  42. package/dist/clis/douyin/_shared/transcode.d.ts +27 -0
  43. package/dist/clis/douyin/_shared/transcode.js +45 -0
  44. package/dist/clis/douyin/_shared/transcode.test.d.ts +1 -0
  45. package/dist/clis/douyin/_shared/transcode.test.js +93 -0
  46. package/dist/clis/douyin/_shared/types.d.ts +26 -0
  47. package/dist/clis/douyin/_shared/types.js +1 -0
  48. package/dist/clis/douyin/activities.d.ts +1 -0
  49. package/dist/clis/douyin/activities.js +20 -0
  50. package/dist/clis/douyin/activities.test.d.ts +1 -0
  51. package/dist/clis/douyin/activities.test.js +22 -0
  52. package/dist/clis/douyin/collections.d.ts +1 -0
  53. package/dist/clis/douyin/collections.js +22 -0
  54. package/dist/clis/douyin/collections.test.d.ts +1 -0
  55. package/dist/clis/douyin/collections.test.js +23 -0
  56. package/dist/clis/douyin/delete.d.ts +1 -0
  57. package/dist/clis/douyin/delete.js +18 -0
  58. package/dist/clis/douyin/delete.test.d.ts +1 -0
  59. package/dist/clis/douyin/delete.test.js +11 -0
  60. package/dist/clis/douyin/draft.d.ts +14 -0
  61. package/dist/clis/douyin/draft.js +237 -0
  62. package/dist/clis/douyin/draft.test.d.ts +1 -0
  63. package/dist/clis/douyin/draft.test.js +11 -0
  64. package/dist/clis/douyin/drafts.d.ts +1 -0
  65. package/dist/clis/douyin/drafts.js +23 -0
  66. package/dist/clis/douyin/drafts.test.d.ts +1 -0
  67. package/dist/clis/douyin/drafts.test.js +11 -0
  68. package/dist/clis/douyin/hashtag.d.ts +1 -0
  69. package/dist/clis/douyin/hashtag.js +45 -0
  70. package/dist/clis/douyin/hashtag.test.d.ts +1 -0
  71. package/dist/clis/douyin/hashtag.test.js +25 -0
  72. package/dist/clis/douyin/location.d.ts +1 -0
  73. package/dist/clis/douyin/location.js +24 -0
  74. package/dist/clis/douyin/location.test.d.ts +1 -0
  75. package/dist/clis/douyin/location.test.js +23 -0
  76. package/dist/clis/douyin/profile.d.ts +1 -0
  77. package/dist/clis/douyin/profile.js +28 -0
  78. package/dist/clis/douyin/profile.test.d.ts +1 -0
  79. package/dist/clis/douyin/profile.test.js +11 -0
  80. package/dist/clis/douyin/publish.d.ts +14 -0
  81. package/dist/clis/douyin/publish.js +288 -0
  82. package/dist/clis/douyin/publish.test.d.ts +1 -0
  83. package/dist/clis/douyin/publish.test.js +38 -0
  84. package/dist/clis/douyin/stats.d.ts +1 -0
  85. package/dist/clis/douyin/stats.js +27 -0
  86. package/dist/clis/douyin/stats.test.d.ts +1 -0
  87. package/dist/clis/douyin/stats.test.js +22 -0
  88. package/dist/clis/douyin/update.d.ts +1 -0
  89. package/dist/clis/douyin/update.js +31 -0
  90. package/dist/clis/douyin/update.test.d.ts +1 -0
  91. package/dist/clis/douyin/update.test.js +11 -0
  92. package/dist/clis/douyin/videos.d.ts +1 -0
  93. package/dist/clis/douyin/videos.js +34 -0
  94. package/dist/clis/douyin/videos.test.d.ts +1 -0
  95. package/dist/clis/douyin/videos.test.js +11 -0
  96. package/dist/clis/hackernews/search.yaml +1 -1
  97. package/dist/clis/instagram/search.yaml +2 -1
  98. package/dist/clis/linux-do/search.yaml +3 -1
  99. package/dist/clis/medium/search.js +1 -1
  100. package/dist/clis/reuters/search.js +0 -1
  101. package/dist/clis/twitter/search.js +5 -3
  102. package/dist/clis/twitter/search.test.js +54 -2
  103. package/dist/clis/weibo/comments.d.ts +1 -0
  104. package/dist/clis/weibo/comments.js +53 -0
  105. package/dist/clis/weibo/feed.d.ts +1 -0
  106. package/dist/clis/weibo/feed.js +56 -0
  107. package/dist/clis/weibo/hot.js +0 -1
  108. package/dist/clis/weibo/me.d.ts +1 -0
  109. package/dist/clis/weibo/me.js +76 -0
  110. package/dist/clis/weibo/post.d.ts +1 -0
  111. package/dist/clis/weibo/post.js +75 -0
  112. package/dist/clis/weibo/user.d.ts +1 -0
  113. package/dist/clis/weibo/user.js +63 -0
  114. package/dist/clis/weibo/utils.d.ts +6 -0
  115. package/dist/clis/weibo/utils.js +30 -0
  116. package/dist/clis/weread/search.js +3 -2
  117. package/dist/clis/xueqiu/search.yaml +2 -1
  118. package/dist/clis/yahoo-finance/quote.js +0 -1
  119. package/dist/clis/youtube/channel.d.ts +1 -0
  120. package/dist/clis/youtube/channel.js +150 -0
  121. package/dist/clis/youtube/comments.d.ts +1 -0
  122. package/dist/clis/youtube/comments.js +95 -0
  123. package/dist/clis/youtube/search.js +0 -1
  124. package/dist/clis/zhihu/search.yaml +2 -1
  125. package/dist/external-clis.yaml +0 -17
  126. package/dist/weread-search-regression.test.d.ts +1 -0
  127. package/dist/weread-search-regression.test.js +39 -0
  128. package/docs/.vitepress/config.mts +13 -0
  129. package/docs/adapters/browser/douyin.md +75 -0
  130. package/docs/adapters/browser/twitter.md +6 -0
  131. package/docs/adapters/index.md +6 -1
  132. package/extension/dist/background.js +508 -518
  133. package/extension/manifest.json +6 -2
  134. package/extension/package.json +1 -1
  135. package/extension/popup.html +84 -0
  136. package/extension/popup.js +25 -0
  137. package/extension/src/background.ts +20 -1
  138. package/package.json +1 -1
  139. package/src/clis/apple-podcasts/search.ts +2 -1
  140. package/src/clis/arxiv/search.ts +2 -2
  141. package/src/clis/bbc/news.ts +0 -1
  142. package/src/clis/ctrip/search.ts +0 -1
  143. package/src/clis/douyin/_shared/browser-fetch.test.ts +38 -0
  144. package/src/clis/douyin/_shared/browser-fetch.ts +45 -0
  145. package/src/clis/douyin/_shared/creation-id.test.ts +26 -0
  146. package/src/clis/douyin/_shared/creation-id.ts +8 -0
  147. package/src/clis/douyin/_shared/imagex-upload.test.ts +113 -0
  148. package/src/clis/douyin/_shared/imagex-upload.ts +76 -0
  149. package/src/clis/douyin/_shared/sts2.ts +20 -0
  150. package/src/clis/douyin/_shared/text-extra.test.ts +42 -0
  151. package/src/clis/douyin/_shared/text-extra.ts +33 -0
  152. package/src/clis/douyin/_shared/timing.test.ts +38 -0
  153. package/src/clis/douyin/_shared/timing.ts +22 -0
  154. package/src/clis/douyin/_shared/tos-upload-short-read.test.ts +102 -0
  155. package/src/clis/douyin/_shared/tos-upload.test.ts +281 -0
  156. package/src/clis/douyin/_shared/tos-upload.ts +444 -0
  157. package/src/clis/douyin/_shared/transcode.test.ts +117 -0
  158. package/src/clis/douyin/_shared/transcode.ts +78 -0
  159. package/src/clis/douyin/_shared/types.ts +29 -0
  160. package/src/clis/douyin/activities.test.ts +25 -0
  161. package/src/clis/douyin/activities.ts +23 -0
  162. package/src/clis/douyin/collections.test.ts +26 -0
  163. package/src/clis/douyin/collections.ts +25 -0
  164. package/src/clis/douyin/delete.test.ts +12 -0
  165. package/src/clis/douyin/delete.ts +20 -0
  166. package/src/clis/douyin/draft.test.ts +12 -0
  167. package/src/clis/douyin/draft.ts +282 -0
  168. package/src/clis/douyin/drafts.test.ts +12 -0
  169. package/src/clis/douyin/drafts.ts +27 -0
  170. package/src/clis/douyin/hashtag.test.ts +28 -0
  171. package/src/clis/douyin/hashtag.ts +56 -0
  172. package/src/clis/douyin/location.test.ts +26 -0
  173. package/src/clis/douyin/location.ts +27 -0
  174. package/src/clis/douyin/profile.test.ts +12 -0
  175. package/src/clis/douyin/profile.ts +37 -0
  176. package/src/clis/douyin/publish.test.ts +45 -0
  177. package/src/clis/douyin/publish.ts +340 -0
  178. package/src/clis/douyin/stats.test.ts +25 -0
  179. package/src/clis/douyin/stats.ts +30 -0
  180. package/src/clis/douyin/update.test.ts +12 -0
  181. package/src/clis/douyin/update.ts +43 -0
  182. package/src/clis/douyin/videos.test.ts +12 -0
  183. package/src/clis/douyin/videos.ts +49 -0
  184. package/src/clis/hackernews/search.yaml +1 -1
  185. package/src/clis/instagram/search.yaml +2 -1
  186. package/src/clis/linux-do/search.yaml +3 -1
  187. package/src/clis/medium/search.ts +1 -1
  188. package/src/clis/reuters/search.ts +0 -1
  189. package/src/clis/twitter/search.test.ts +69 -2
  190. package/src/clis/twitter/search.ts +5 -3
  191. package/src/clis/weibo/comments.ts +54 -0
  192. package/src/clis/weibo/feed.ts +57 -0
  193. package/src/clis/weibo/hot.ts +0 -1
  194. package/src/clis/weibo/me.ts +77 -0
  195. package/src/clis/weibo/post.ts +77 -0
  196. package/src/clis/weibo/user.ts +64 -0
  197. package/src/clis/weibo/utils.ts +32 -0
  198. package/src/clis/weread/search.ts +3 -2
  199. package/src/clis/xueqiu/search.yaml +2 -1
  200. package/src/clis/yahoo-finance/quote.ts +0 -1
  201. package/src/clis/youtube/channel.ts +155 -0
  202. package/src/clis/youtube/comments.ts +97 -0
  203. package/src/clis/youtube/search.ts +0 -1
  204. package/src/clis/zhihu/search.yaml +2 -1
  205. package/src/external-clis.yaml +0 -17
  206. package/src/weread-search-regression.test.ts +44 -0
  207. package/tests/e2e/browser-public-extended.test.ts +162 -0
  208. package/tests/e2e/browser-public.test.ts +7 -146
  209. package/vitest.config.ts +24 -17
@@ -1,5 +1,5 @@
1
1
  /**
2
- * E2E tests for browser commands that access PUBLIC data (no login required).
2
+ * E2E tests for core browser commands (bilibili, zhihu, v2ex).
3
3
  * These use OPENCLI_HEADLESS=1 to launch a headless Chromium.
4
4
  *
5
5
  * NOTE: Some sites may block headless browsers with bot detection.
@@ -9,9 +9,6 @@
9
9
  import { describe, it, expect } from 'vitest';
10
10
  import { runCli, parseJsonOutput } from './helpers.js';
11
11
 
12
- /**
13
- * Run a browser command — returns parsed data or null on failure.
14
- */
15
12
  async function tryBrowserCommand(args: string[]): Promise<any[] | null> {
16
13
  const { stdout, code } = await runCli(args, { timeout: 60_000 });
17
14
  if (code !== 0) return null;
@@ -23,10 +20,6 @@ async function tryBrowserCommand(args: string[]): Promise<any[] | null> {
23
20
  }
24
21
  }
25
22
 
26
- /**
27
- * Assert browser command returns data OR log a warning if blocked.
28
- * Empty results (bot detection, geo-blocking) are treated as a warning, not a failure.
29
- */
30
23
  function expectDataOrSkip(data: any[] | null, label: string) {
31
24
  if (data === null || data.length === 0) {
32
25
  console.warn(`${label}: skipped — no data returned (likely bot detection or geo-blocking)`);
@@ -37,47 +30,7 @@ function expectDataOrSkip(data: any[] | null, label: string) {
37
30
 
38
31
  describe('browser public-data commands E2E', () => {
39
32
 
40
- // ── bbc (browser: true, strategy: public) ──
41
- it('bbc news returns headlines', async () => {
42
- const data = await tryBrowserCommand(['bbc', 'news', '--limit', '3', '-f', 'json']);
43
- expectDataOrSkip(data, 'bbc news');
44
- if (data) {
45
- expect(data[0]).toHaveProperty('title');
46
- }
47
- }, 60_000);
48
-
49
- it('bloomberg news returns article detail when the article page is accessible', async () => {
50
- const feedResult = await runCli(['bloomberg', 'tech', '--limit', '1', '-f', 'json']);
51
- if (feedResult.code !== 0) {
52
- console.warn('bloomberg news: skipped — could not load Bloomberg tech feed');
53
- return;
54
- }
55
-
56
- const feedItems = parseJsonOutput(feedResult.stdout);
57
- const link = Array.isArray(feedItems) ? feedItems[0]?.link : null;
58
- if (!link) {
59
- console.warn('bloomberg news: skipped — tech feed returned no link');
60
- return;
61
- }
62
-
63
- const data = await tryBrowserCommand(['bloomberg', 'news', link, '-f', 'json']);
64
- expectDataOrSkip(data, 'bloomberg news');
65
- if (data) {
66
- expect(data[0]).toHaveProperty('title');
67
- expect(data[0]).toHaveProperty('summary');
68
- expect(data[0]).toHaveProperty('link');
69
- expect(data[0]).toHaveProperty('mediaLinks');
70
- expect(data[0]).toHaveProperty('content');
71
- }
72
- }, 60_000);
73
-
74
- // ── v2ex daily (browser: true) ──
75
- it('v2ex daily returns topics', async () => {
76
- const data = await tryBrowserCommand(['v2ex', 'daily', '--limit', '3', '-f', 'json']);
77
- expectDataOrSkip(data, 'v2ex daily');
78
- }, 60_000);
79
-
80
- // ── bilibili (browser: true, cookie strategy) ──
33
+ // ── bilibili ──
81
34
  it('bilibili hot returns trending videos', async () => {
82
35
  const data = await tryBrowserCommand(['bilibili', 'hot', '--limit', '5', '-f', 'json']);
83
36
  expectDataOrSkip(data, 'bilibili hot');
@@ -96,18 +49,7 @@ describe('browser public-data commands E2E', () => {
96
49
  expectDataOrSkip(data, 'bilibili search');
97
50
  }, 60_000);
98
51
 
99
- // ── weibo (browser: true, cookie strategy) ──
100
- it('weibo hot returns trending topics', async () => {
101
- const data = await tryBrowserCommand(['weibo', 'hot', '--limit', '5', '-f', 'json']);
102
- expectDataOrSkip(data, 'weibo hot');
103
- }, 60_000);
104
-
105
- it('weibo search returns results', async () => {
106
- const data = await tryBrowserCommand(['weibo', 'search', 'openai', '--limit', '3', '-f', 'json']);
107
- expectDataOrSkip(data, 'weibo search');
108
- }, 60_000);
109
-
110
- // ── zhihu (browser: true, cookie strategy) ──
52
+ // ── zhihu ──
111
53
  it('zhihu hot returns trending questions', async () => {
112
54
  const data = await tryBrowserCommand(['zhihu', 'hot', '--limit', '5', '-f', 'json']);
113
55
  expectDataOrSkip(data, 'zhihu hot');
@@ -121,90 +63,9 @@ describe('browser public-data commands E2E', () => {
121
63
  expectDataOrSkip(data, 'zhihu search');
122
64
  }, 60_000);
123
65
 
124
- // ── reddit (browser: true, cookie strategy) ──
125
- it('reddit hot returns posts', async () => {
126
- const data = await tryBrowserCommand(['reddit', 'hot', '--limit', '5', '-f', 'json']);
127
- expectDataOrSkip(data, 'reddit hot');
128
- }, 60_000);
129
-
130
- it('reddit frontpage returns posts', async () => {
131
- const data = await tryBrowserCommand(['reddit', 'frontpage', '--limit', '5', '-f', 'json']);
132
- expectDataOrSkip(data, 'reddit frontpage');
133
- }, 60_000);
134
-
135
- // ── twitter (browser: true) ──
136
- it('twitter trending returns trends', async () => {
137
- const data = await tryBrowserCommand(['twitter', 'trending', '--limit', '5', '-f', 'json']);
138
- expectDataOrSkip(data, 'twitter trending');
139
- }, 60_000);
140
-
141
- // ── xueqiu (browser: true, cookie strategy) ──
142
- it('xueqiu hot returns hot posts', async () => {
143
- const data = await tryBrowserCommand(['xueqiu', 'hot', '--limit', '5', '-f', 'json']);
144
- expectDataOrSkip(data, 'xueqiu hot');
145
- }, 60_000);
146
-
147
- it('xueqiu hot-stock returns stocks', async () => {
148
- const data = await tryBrowserCommand(['xueqiu', 'hot-stock', '--limit', '5', '-f', 'json']);
149
- expectDataOrSkip(data, 'xueqiu hot-stock');
150
- }, 60_000);
151
-
152
- // ── reuters (browser: true) ──
153
- it('reuters search returns articles', async () => {
154
- const data = await tryBrowserCommand(['reuters', 'search', 'technology', '--limit', '3', '-f', 'json']);
155
- expectDataOrSkip(data, 'reuters search');
156
- }, 60_000);
157
-
158
- // ── youtube (browser: true) ──
159
- it('youtube search returns videos', async () => {
160
- const data = await tryBrowserCommand(['youtube', 'search', 'typescript tutorial', '--limit', '3', '-f', 'json']);
161
- expectDataOrSkip(data, 'youtube search');
162
- }, 60_000);
163
-
164
- // ── smzdm (browser: true) ──
165
- it('smzdm search returns deals', async () => {
166
- const data = await tryBrowserCommand(['smzdm', 'search', '键盘', '--limit', '3', '-f', 'json']);
167
- expectDataOrSkip(data, 'smzdm search');
168
- }, 60_000);
169
-
170
- // ── boss (browser: true) ──
171
- it('boss search returns jobs', async () => {
172
- const data = await tryBrowserCommand(['boss', 'search', 'golang', '--limit', '3', '-f', 'json']);
173
- expectDataOrSkip(data, 'boss search');
174
- }, 60_000);
175
-
176
- // ── ctrip (browser: true) ──
177
- it('ctrip search returns flights', async () => {
178
- const data = await tryBrowserCommand(['ctrip', 'search', '-f', 'json']);
179
- expectDataOrSkip(data, 'ctrip search');
180
- }, 60_000);
181
-
182
- // ── coupang (browser: true) ──
183
- it('coupang search returns products', async () => {
184
- const data = await tryBrowserCommand(['coupang', 'search', 'laptop', '--limit', '3', '-f', 'json']);
185
- expectDataOrSkip(data, 'coupang search');
186
- }, 60_000);
187
-
188
- // ── xiaohongshu (browser: true) ──
189
- it('xiaohongshu search returns notes', async () => {
190
- const data = await tryBrowserCommand(['xiaohongshu', 'search', '美食', '--limit', '3', '-f', 'json']);
191
- expectDataOrSkip(data, 'xiaohongshu search');
192
- }, 60_000);
193
-
194
- // ── google search (browser: true, public strategy) ──
195
- it('google search returns results', async () => {
196
- const data = await tryBrowserCommand(['google', 'search', 'typescript', '--limit', '5', '-f', 'json']);
197
- expectDataOrSkip(data, 'google search');
198
- if (data) {
199
- expect(data[0]).toHaveProperty('type');
200
- expect(data[0]).toHaveProperty('title');
201
- expect(data[0]).toHaveProperty('url');
202
- }
203
- }, 60_000);
204
-
205
- // ── yahoo-finance (browser: true) ──
206
- it('yahoo-finance quote returns stock data', async () => {
207
- const data = await tryBrowserCommand(['yahoo-finance', 'quote', '--symbol', 'AAPL', '-f', 'json']);
208
- expectDataOrSkip(data, 'yahoo-finance quote');
66
+ // ── v2ex ──
67
+ it('v2ex daily returns topics', async () => {
68
+ const data = await tryBrowserCommand(['v2ex', 'daily', '--limit', '3', '-f', 'json']);
69
+ expectDataOrSkip(data, 'v2ex daily');
209
70
  }, 60_000);
210
71
  });
package/vitest.config.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { defineConfig } from 'vitest/config';
2
2
 
3
+ const includeExtendedE2e = process.env.OPENCLI_E2E === '1';
4
+
3
5
  export default defineConfig({
4
6
  test: {
5
7
  projects: [
@@ -8,37 +10,42 @@ export default defineConfig({
8
10
  name: 'unit',
9
11
  include: ['src/**/*.test.ts'],
10
12
  exclude: ['src/clis/**/*.test.ts'],
11
- // Run unit tests before e2e tests to avoid project-level contention in CI.
12
- sequence: {
13
- groupOrder: 0,
14
- },
13
+ sequence: { groupOrder: 0 },
15
14
  },
16
15
  },
17
16
  {
18
17
  test: {
19
18
  name: 'adapter',
20
19
  include: [
21
- 'src/clis/zhihu/**/*.test.ts',
22
- 'src/clis/twitter/**/*.test.ts',
23
- 'src/clis/reddit/**/*.test.ts',
24
20
  'src/clis/bilibili/**/*.test.ts',
25
- 'src/clis/linkedin/**/*.test.ts',
26
- 'src/clis/grok/**/*.test.ts',
27
- 'src/clis/pixiv/**/*.test.ts',
21
+ 'src/clis/zhihu/**/*.test.ts',
22
+ 'src/clis/v2ex/**/*.test.ts',
28
23
  ],
29
- sequence: {
30
- groupOrder: 1,
31
- },
24
+ sequence: { groupOrder: 1 },
32
25
  },
33
26
  },
34
27
  {
35
28
  test: {
36
29
  name: 'e2e',
37
- include: ['tests/**/*.test.ts'],
30
+ include: [
31
+ 'tests/e2e/browser-public.test.ts',
32
+ 'tests/e2e/public-commands.test.ts',
33
+ 'tests/e2e/management.test.ts',
34
+ 'tests/e2e/output-formats.test.ts',
35
+ 'tests/e2e/plugin-management.test.ts',
36
+ // Extended browser tests (20+ sites) — opt-in only:
37
+ // OPENCLI_E2E=1 npx vitest run
38
+ ...(includeExtendedE2e ? ['tests/e2e/browser-public-extended.test.ts', 'tests/e2e/browser-auth.test.ts'] : []),
39
+ ],
38
40
  maxWorkers: 2,
39
- sequence: {
40
- groupOrder: 2,
41
- },
41
+ sequence: { groupOrder: 2 },
42
+ },
43
+ },
44
+ {
45
+ test: {
46
+ name: 'smoke',
47
+ include: ['tests/smoke/**/*.test.ts'],
48
+ sequence: { groupOrder: 3 },
42
49
  },
43
50
  },
44
51
  ],