/ clis / tieba / commands.test.js
commands.test.js
 1  import { describe, expect, it } from 'vitest';
 2  import { Strategy, getRegistry } from '@jackwener/opencli/registry';
 3  import './hot.js';
 4  import './posts.js';
 5  import './read.js';
 6  import './search.js';
 7  describe('tieba commands', () => {
 8      it('registers all tieba commands as TypeScript adapters', () => {
 9          const hot = getRegistry().get('tieba/hot');
10          const posts = getRegistry().get('tieba/posts');
11          const search = getRegistry().get('tieba/search');
12          const read = getRegistry().get('tieba/read');
13          expect(hot).toBeDefined();
14          expect(posts).toBeDefined();
15          expect(search).toBeDefined();
16          expect(read).toBeDefined();
17          expect(typeof hot?.func).toBe('function');
18          expect(typeof posts?.func).toBe('function');
19          expect(typeof search?.func).toBe('function');
20          expect(typeof read?.func).toBe('function');
21      });
22      it('keeps the intended browser strategies', () => {
23          const hot = getRegistry().get('tieba/hot');
24          const posts = getRegistry().get('tieba/posts');
25          const search = getRegistry().get('tieba/search');
26          const read = getRegistry().get('tieba/read');
27          expect(hot?.strategy).toBe(Strategy.PUBLIC);
28          expect(posts?.strategy).toBe(Strategy.COOKIE);
29          expect(search?.strategy).toBe(Strategy.COOKIE);
30          expect(read?.strategy).toBe(Strategy.COOKIE);
31          expect(hot?.browser).toBe(true);
32          expect(posts?.browser).toBe(true);
33          expect(search?.browser).toBe(true);
34          expect(read?.browser).toBe(true);
35      });
36      it('keeps the public limit contract at 20 items for list commands', () => {
37          const hot = getRegistry().get('tieba/hot');
38          const posts = getRegistry().get('tieba/posts');
39          const search = getRegistry().get('tieba/search');
40          expect(hot?.args.find((arg) => arg.name === 'limit')?.default).toBe(20);
41          expect(posts?.args.find((arg) => arg.name === 'limit')?.default).toBe(20);
42          expect(search?.args.find((arg) => arg.name === 'limit')?.default).toBe(20);
43      });
44      it('rejects tieba read results when navigation lands on the wrong page number', async () => {
45          const read = getRegistry().get('tieba/read');
46          expect(read).toBeDefined();
47          expect(typeof read?.func).toBe('function');
48          const run = read?.func;
49          if (!run)
50              throw new Error('tieba/read did not register a handler');
51          const page = {
52              goto: async () => undefined,
53              evaluate: async () => ({
54                  pageMeta: {
55                      pathname: '/p/10163164720',
56                      pn: '1',
57                  },
58                  mainPost: {
59                      title: '测试帖子',
60                      author: '作者',
61                      contentText: '正文',
62                      structuredText: '',
63                      visibleTime: '2026-03-29 12:00',
64                      structuredTime: 0,
65                      hasMedia: false,
66                  },
67                  replies: [],
68              }),
69          };
70          await expect(run(page, {
71              id: '10163164720',
72              page: 2,
73              limit: 5,
74          })).rejects.toMatchObject({
75              code: 'EMPTY_RESULT',
76              hint: expect.stringMatching(/requested page/i),
77          });
78      });
79  });