Recover related videos with bounded discovery and retryable fallbacks
This commit is contained in:
@@ -47,3 +47,16 @@ test('searchDeep follows continuation tokens, de-duplicates and stops at the lim
|
||||
test('parseContinuation of an empty response is empty', () => {
|
||||
expect(parseContinuation({})).toEqual({ cards: [], next: '' });
|
||||
});
|
||||
|
||||
test('related parser reads compact and modern lockup cards, excluding playlists and ads', async () => {
|
||||
const { parseRelated } = await import('./innertube.js');
|
||||
const compact = { compactVideoRenderer: { videoId: 'aaaaaaaaaaa', title: { simpleText: 'First' }, shortBylineText: { runs: [{ text: 'Artist' }] }, lengthText: { simpleText: '3:12' } } };
|
||||
const modern = { lockupViewModel: { contentId: 'bbbbbbbbbbb', contentType: 'LOCKUP_CONTENT_TYPE_VIDEO', metadata: { lockupMetadataViewModel: { title: { content: 'Second' }, metadata: { contentMetadataViewModel: { metadataRows: [{ metadataParts: [{ text: { content: 'Band' } }] }] } } } } } };
|
||||
const result = parseRelated({ contents: { twoColumnWatchNextResults: { secondaryResults: { secondaryResults: { results: [compact, modern, compact, { lockupViewModel: { ...modern.lockupViewModel, contentType: 'LOCKUP_CONTENT_TYPE_PLAYLIST' } }, { adSlotRenderer: { contents: compact } }] } } } } });
|
||||
expect(result.map(c => [c.id, c.title, c.channel])).toEqual([['aaaaaaaaaaa', 'First', 'Artist'], ['bbbbbbbbbbb', 'Second', 'Band']]);expect(result[0].duration).toBe(192);
|
||||
});
|
||||
test('related HTTP failures and unsupported shapes throw for search fallback', async () => {
|
||||
const { related, parseRelated } = await import('./innertube.js');
|
||||
expect(() => parseRelated({ error: {} })).toThrow('response shape');
|
||||
await expect(related('aaaaaaaaaaa', { fetchImpl: async () => ({ ok: false, status: 429 }) })).rejects.toThrow('429');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user