@jackwener/opencli 1.7.20 → 1.7.21
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 +233 -72
- package/clis/_shared/search-adapter.js +70 -0
- package/clis/boss/chatlist.js +96 -14
- package/clis/boss/chatlist.test.js +211 -0
- package/clis/boss/chatmsg.js +98 -24
- package/clis/boss/chatmsg.test.js +230 -0
- package/clis/boss/utils.js +240 -11
- package/clis/brave/search.js +80 -0
- package/clis/brave/search.test.js +76 -0
- package/clis/duckduckgo/search.js +131 -0
- package/clis/duckduckgo/search.test.js +128 -0
- package/clis/duckduckgo/suggest.js +45 -0
- package/clis/duckduckgo/suggest.test.js +66 -0
- package/clis/facebook/feed.js +301 -56
- package/clis/facebook/feed.test.js +169 -0
- package/clis/reddit/comment.js +0 -1
- package/clis/reddit/frontpage.js +0 -1
- package/clis/reddit/home.js +0 -1
- package/clis/reddit/popular.js +0 -1
- package/clis/reddit/read.js +0 -1
- package/clis/reddit/read.test.js +2 -2
- package/clis/reddit/save.js +0 -1
- package/clis/reddit/saved.js +0 -1
- package/clis/reddit/search.js +0 -1
- package/clis/reddit/subreddit-info.js +0 -1
- package/clis/reddit/subreddit.js +0 -1
- package/clis/reddit/subscribe.js +0 -1
- package/clis/reddit/upvote.js +0 -1
- package/clis/reddit/upvoted.js +0 -1
- package/clis/reddit/user-comments.js +0 -1
- package/clis/reddit/user-posts.js +0 -1
- package/clis/reddit/user.js +0 -1
- package/clis/reddit/whoami.js +0 -1
- package/clis/rednote/rednote.test.js +65 -0
- package/clis/rednote/search.js +11 -5
- package/clis/twitter/article.js +0 -1
- package/clis/twitter/bookmark-folder.js +0 -1
- package/clis/twitter/bookmark-folders.js +0 -1
- package/clis/twitter/bookmarks.js +0 -1
- package/clis/twitter/download.js +0 -1
- package/clis/twitter/followers.js +0 -1
- package/clis/twitter/following.js +0 -1
- package/clis/twitter/likes.js +0 -1
- package/clis/twitter/list-tweets.js +0 -1
- package/clis/twitter/lists.js +0 -1
- package/clis/twitter/notifications.js +0 -1
- package/clis/twitter/profile.js +0 -1
- package/clis/twitter/search.js +0 -1
- package/clis/twitter/thread.js +0 -1
- package/clis/twitter/timeline.js +0 -1
- package/clis/twitter/trending.js +0 -1
- package/clis/twitter/tweets.js +0 -1
- package/clis/xiaohongshu/search.js +34 -16
- package/clis/xiaohongshu/search.test.js +66 -11
- package/clis/yahoo/search.js +92 -0
- package/clis/yahoo/search.test.js +94 -0
- package/package.json +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
const { __test__ } = await import('./search.js');
|
|
4
|
+
const command = __test__.command;
|
|
5
|
+
|
|
6
|
+
function createPageMock(evaluateResult = []) {
|
|
7
|
+
return {
|
|
8
|
+
goto: vi.fn().mockResolvedValue(undefined),
|
|
9
|
+
wait: vi.fn().mockResolvedValue(undefined),
|
|
10
|
+
evaluate: vi.fn().mockResolvedValue(evaluateResult),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe('yahoo search', () => {
|
|
15
|
+
it('should register as a valid command', () => {
|
|
16
|
+
expect(command).toBeDefined();
|
|
17
|
+
expect(command.site).toBe('yahoo');
|
|
18
|
+
expect(command.name).toBe('search');
|
|
19
|
+
expect(command.access).toBe('read');
|
|
20
|
+
expect(command.browser).toBe(true);
|
|
21
|
+
expect(command.strategy).toBe('public');
|
|
22
|
+
expect(command.domain).toBe('search.yahoo.com');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should define keyword positional arg', () => {
|
|
26
|
+
const kwArg = command.args.find(a => a.name === 'keyword');
|
|
27
|
+
expect(kwArg).toBeDefined();
|
|
28
|
+
expect(kwArg.positional).toBe(true);
|
|
29
|
+
expect(kwArg.required).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should define limit arg with default 7', () => {
|
|
33
|
+
const limitArg = command.args.find(a => a.name === 'limit');
|
|
34
|
+
expect(limitArg).toBeDefined();
|
|
35
|
+
expect(limitArg.type).toBe('int');
|
|
36
|
+
expect(limitArg.default).toBe(7);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should define output columns', () => {
|
|
40
|
+
expect(command.columns).toContain('rank');
|
|
41
|
+
expect(command.columns).toContain('title');
|
|
42
|
+
expect(command.columns).toContain('url');
|
|
43
|
+
expect(command.columns).toContain('snippet');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('rejects empty query, invalid limit, and invalid page before navigation', async () => {
|
|
47
|
+
const page = createPageMock();
|
|
48
|
+
await expect(command.func(page, { keyword: ' ', limit: 5 })).rejects.toMatchObject({ code: 'ARGUMENT' });
|
|
49
|
+
await expect(command.func(page, { keyword: 'opencli', limit: 8 })).rejects.toMatchObject({ code: 'ARGUMENT' });
|
|
50
|
+
await expect(command.func(page, { keyword: 'opencli', limit: 5, page: 0 })).rejects.toMatchObject({ code: 'ARGUMENT' });
|
|
51
|
+
expect(page.goto).not.toHaveBeenCalled();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('decodes Yahoo redirect URLs and assigns listing rank', async () => {
|
|
55
|
+
const page = createPageMock({
|
|
56
|
+
session: 'site:yahoo',
|
|
57
|
+
data: [[
|
|
58
|
+
'OpenCLI',
|
|
59
|
+
'https://r.search.yahoo.com/_ylt=x/RU=https%3A%2F%2Fgithub.com%2Fjackwener%2FOpenCLI/RK=2/RS=x',
|
|
60
|
+
'CLI browser tooling',
|
|
61
|
+
]],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await expect(command.func(page, { keyword: 'opencli', limit: 1, page: 2 })).resolves.toEqual([{
|
|
65
|
+
rank: 8,
|
|
66
|
+
title: 'OpenCLI',
|
|
67
|
+
url: 'https://github.com/jackwener/OpenCLI',
|
|
68
|
+
snippet: 'CLI browser tooling',
|
|
69
|
+
}]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('drops decoded Yahoo redirect targets that are not http(s) URLs', async () => {
|
|
73
|
+
const page = createPageMock([
|
|
74
|
+
[
|
|
75
|
+
'Bad redirect',
|
|
76
|
+
'https://r.search.yahoo.com/_ylt=x/RU=javascript%3Aalert(1)/RK=2/RS=x',
|
|
77
|
+
'should not be emitted',
|
|
78
|
+
],
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
await expect(command.func(page, { keyword: 'opencli', limit: 1 })).rejects.toMatchObject({
|
|
82
|
+
code: 'EMPTY_RESULT',
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('fails typed instead of silently returning [] for malformed extraction payloads', async () => {
|
|
87
|
+
const page = createPageMock({ rows: [] });
|
|
88
|
+
|
|
89
|
+
await expect(command.func(page, { keyword: 'opencli', limit: 1 })).rejects.toMatchObject({
|
|
90
|
+
code: 'COMMAND_EXEC',
|
|
91
|
+
message: expect.stringContaining('payload shape'),
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|