/ clis / youtube / utils.test.js
utils.test.js
 1  import { describe, expect, it, vi } from 'vitest';
 2  import { extractJsonAssignmentFromHtml, extractSubscriptionChannel, prepareYoutubeApiPage } from './utils.js';
 3  describe('youtube utils', () => {
 4      it('extractJsonAssignmentFromHtml parses bootstrap objects with nested braces in strings', () => {
 5          const html = `
 6        <script>
 7          var ytInitialPlayerResponse = {
 8            "title": "brace { inside } string",
 9            "nested": { "count": 2, "text": "quote \\"value\\"" }
10          };
11        </script>
12      `;
13          expect(extractJsonAssignmentFromHtml(html, 'ytInitialPlayerResponse')).toEqual({
14              title: 'brace { inside } string',
15              nested: { count: 2, text: 'quote "value"' },
16          });
17      });
18      it('extractJsonAssignmentFromHtml supports window assignments', () => {
19          const html = `
20        <script>
21          window["ytInitialData"] = {"contents":{"items":[1,2,3]}};
22        </script>
23      `;
24          expect(extractJsonAssignmentFromHtml(html, 'ytInitialData')).toEqual({
25              contents: { items: [1, 2, 3] },
26          });
27      });
28      it('prepareYoutubeApiPage loads the quiet API bootstrap page', async () => {
29          const page = {
30              goto: vi.fn().mockResolvedValue(undefined),
31              wait: vi.fn().mockResolvedValue(undefined),
32          };
33          await expect(prepareYoutubeApiPage(page)).resolves.toBeUndefined();
34          expect(page.goto).toHaveBeenCalledWith('https://www.youtube.com', { waitUntil: 'none' });
35          expect(page.wait).toHaveBeenCalledWith(2);
36      });
37      it('extractSubscriptionChannel prefers explicit handle and subscriber count fields', () => {
38          expect(extractSubscriptionChannel({
39              title: { simpleText: 'OpenAI' },
40              channelHandleText: { runs: [{ text: '@openai' }] },
41              subscriberCountText: { simpleText: '1.23M subscribers' },
42              videoCountText: { simpleText: '123 videos' },
43              navigationEndpoint: { browseEndpoint: { canonicalBaseUrl: '/channel/UC123' } },
44              channelId: 'UC123',
45          })).toEqual({
46              name: 'OpenAI',
47              handle: '@openai',
48              subscribers: '1.23M subscribers',
49              url: 'https://www.youtube.com/channel/UC123',
50          });
51      });
52      it('extractSubscriptionChannel falls back when handle/count fields are overloaded', () => {
53          expect(extractSubscriptionChannel({
54              title: {
55                  runs: [{ text: 'OpenAI' }],
56              },
57              subscriberCountText: { simpleText: '@openai' },
58              videoCountText: { simpleText: '1.23M subscribers' },
59              navigationEndpoint: { browseEndpoint: { canonicalBaseUrl: '/@openai' } },
60              channelId: 'UC123',
61          })).toEqual({
62              name: 'OpenAI',
63              handle: '@openai',
64              subscribers: '1.23M subscribers',
65              url: 'https://www.youtube.com/@openai',
66          });
67      });
68  });