/ clis / linux-do / feed.test.js
feed.test.js
  1  import * as fs from 'node:fs';
  2  import * as os from 'node:os';
  3  import * as path from 'node:path';
  4  import { afterEach, describe, expect, it } from 'vitest';
  5  import { __test__ } from './feed.js';
  6  describe('linux-do feed metadata resolution', () => {
  7      afterEach(() => {
  8          __test__.resetMetadataCaches();
  9      });
 10      it('prefers live tag metadata over the bundled snapshot', async () => {
 11          __test__.setLiveMetadataForTests({
 12              tags: [{ id: 9999, slug: 'fresh-tag', name: 'Fresh Tag' }],
 13          });
 14          const request = await __test__.resolveFeedRequest(null, {
 15              tag: 'Fresh Tag',
 16              view: 'latest',
 17              limit: 20,
 18          });
 19          expect(request.url).toBe('/tag/fresh-tag/9999.json?per_page=20');
 20      });
 21      it('uses live category metadata with parent paths for subcategories', async () => {
 22          __test__.setLiveMetadataForTests({
 23              categories: [
 24                  {
 25                      id: 10,
 26                      name: 'Parent',
 27                      description: '',
 28                      slug: 'parent',
 29                      parentCategoryId: null,
 30                      parent: null,
 31                  },
 32                  {
 33                      id: 11,
 34                      name: 'Fresh Child',
 35                      description: '',
 36                      slug: 'fresh-child',
 37                      parentCategoryId: 10,
 38                      parent: {
 39                          id: 10,
 40                          name: 'Parent',
 41                          description: '',
 42                          slug: 'parent',
 43                          parentCategoryId: null,
 44                      },
 45                  },
 46              ],
 47          });
 48          const request = await __test__.resolveFeedRequest(null, {
 49              category: 'Fresh Child',
 50              view: 'hot',
 51              limit: 20,
 52          });
 53          expect(request.url).toBe('/c/parent/fresh-child/11/l/hot.json?per_page=20');
 54      });
 55      it('accepts parent/name category paths for subcategories', async () => {
 56          __test__.setLiveMetadataForTests({
 57              categories: [
 58                  {
 59                      id: 10,
 60                      name: 'Parent',
 61                      description: '',
 62                      slug: 'parent',
 63                      parentCategoryId: null,
 64                      parent: null,
 65                  },
 66                  {
 67                      id: 11,
 68                      name: 'Fresh Child',
 69                      description: '',
 70                      slug: 'fresh-child',
 71                      parentCategoryId: 10,
 72                      parent: {
 73                          id: 10,
 74                          name: 'Parent',
 75                          description: '',
 76                          slug: 'parent',
 77                          parentCategoryId: null,
 78                      },
 79                  },
 80              ],
 81          });
 82          const request = await __test__.resolveFeedRequest(null, {
 83              category: 'Parent / Fresh Child',
 84              view: 'latest',
 85              limit: 20,
 86          });
 87          expect(request.url).toBe('/c/parent/fresh-child/11.json?per_page=20');
 88      });
 89      it('falls back to cached metadata when live metadata is unavailable', async () => {
 90          const cacheDir = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-linux-do-cache-'));
 91          __test__.setCacheDirForTests(cacheDir);
 92          fs.writeFileSync(path.join(cacheDir, 'tags.json'), JSON.stringify({
 93              fetchedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
 94              data: [{ id: 3, slug: 'chatgpt', name: 'ChatGPT' }],
 95          }));
 96          fs.writeFileSync(path.join(cacheDir, 'categories.json'), JSON.stringify({
 97              fetchedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
 98              data: [{
 99                      id: 4,
100                      name: '开发调优',
101                      description: '',
102                      slug: 'develop',
103                      parentCategoryId: null,
104                      parent: null,
105                  }],
106          }));
107          const request = await __test__.resolveFeedRequest(null, {
108              tag: 'ChatGPT',
109              category: '开发调优',
110              view: 'top',
111              period: 'monthly',
112              limit: 20,
113          });
114          expect(request.url).toContain('/tags/c/develop/4/chatgpt/3/l/top.json');
115          expect(request.url).toContain('per_page=20');
116          expect(request.url).toContain('period=monthly');
117      });
118  });