source-fulltext.test.js
1 import { beforeEach, describe, expect, it, vi } from 'vitest'; 2 const { mockListNotebooklmSourcesViaRpc, mockListNotebooklmSourcesFromPage, mockGetNotebooklmSourceFulltextViaRpc, mockGetNotebooklmPageState, mockRequireNotebooklmSession, } = vi.hoisted(() => ({ 3 mockListNotebooklmSourcesViaRpc: vi.fn(), 4 mockListNotebooklmSourcesFromPage: vi.fn(), 5 mockGetNotebooklmSourceFulltextViaRpc: vi.fn(), 6 mockGetNotebooklmPageState: vi.fn(), 7 mockRequireNotebooklmSession: vi.fn(), 8 })); 9 vi.mock('./utils.js', async () => { 10 const actual = await vi.importActual('./utils.js'); 11 return { 12 ...actual, 13 listNotebooklmSourcesViaRpc: mockListNotebooklmSourcesViaRpc, 14 listNotebooklmSourcesFromPage: mockListNotebooklmSourcesFromPage, 15 getNotebooklmSourceFulltextViaRpc: mockGetNotebooklmSourceFulltextViaRpc, 16 getNotebooklmPageState: mockGetNotebooklmPageState, 17 requireNotebooklmSession: mockRequireNotebooklmSession, 18 }; 19 }); 20 import { getRegistry } from '@jackwener/opencli/registry'; 21 import './source-fulltext.js'; 22 describe('notebooklm source-fulltext', () => { 23 const command = getRegistry().get('notebooklm/source-fulltext'); 24 beforeEach(() => { 25 mockListNotebooklmSourcesViaRpc.mockReset(); 26 mockListNotebooklmSourcesFromPage.mockReset(); 27 mockGetNotebooklmSourceFulltextViaRpc.mockReset(); 28 mockGetNotebooklmPageState.mockReset(); 29 mockRequireNotebooklmSession.mockReset(); 30 mockRequireNotebooklmSession.mockResolvedValue(undefined); 31 mockGetNotebooklmPageState.mockResolvedValue({ 32 url: 'https://notebooklm.google.com/notebook/nb-demo', 33 title: 'Browser Automation', 34 hostname: 'notebooklm.google.com', 35 kind: 'notebook', 36 notebookId: 'nb-demo', 37 loginRequired: false, 38 notebookCount: 1, 39 }); 40 }); 41 it('returns fulltext for a source matched from rpc source rows', async () => { 42 mockListNotebooklmSourcesViaRpc.mockResolvedValue([ 43 { 44 id: 'src-1', 45 notebook_id: 'nb-demo', 46 title: '粘贴的文字', 47 url: 'https://notebooklm.google.com/notebook/nb-demo', 48 source: 'rpc', 49 type: 'pasted-text', 50 }, 51 ]); 52 mockGetNotebooklmSourceFulltextViaRpc.mockResolvedValue({ 53 source_id: 'src-1', 54 notebook_id: 'nb-demo', 55 title: '粘贴的文字', 56 kind: 'generated-text', 57 content: '第一段\n第二段', 58 char_count: 7, 59 url: 'https://example.com/source', 60 source: 'rpc', 61 }); 62 const result = await command.func({}, { source: 'src-1' }); 63 expect(result).toEqual([ 64 { 65 source_id: 'src-1', 66 notebook_id: 'nb-demo', 67 title: '粘贴的文字', 68 kind: 'generated-text', 69 content: '第一段\n第二段', 70 char_count: 7, 71 url: 'https://example.com/source', 72 source: 'rpc', 73 }, 74 ]); 75 }); 76 it('matches by title from dom rows when rpc source list is unavailable', async () => { 77 mockListNotebooklmSourcesViaRpc.mockResolvedValue([]); 78 mockListNotebooklmSourcesFromPage.mockResolvedValue([ 79 { 80 id: 'src-1', 81 notebook_id: 'nb-demo', 82 title: '粘贴的文字', 83 url: 'https://notebooklm.google.com/notebook/nb-demo', 84 source: 'current-page', 85 }, 86 ]); 87 mockGetNotebooklmSourceFulltextViaRpc.mockResolvedValue({ 88 source_id: 'src-1', 89 notebook_id: 'nb-demo', 90 title: '粘贴的文字', 91 kind: 'generated-text', 92 content: '第一段\n第二段', 93 char_count: 7, 94 url: 'https://example.com/source', 95 source: 'rpc', 96 }); 97 const result = await command.func({}, { source: '粘贴的文字' }); 98 expect(result).toEqual([ 99 expect.objectContaining({ 100 source_id: 'src-1', 101 title: '粘贴的文字', 102 content: '第一段\n第二段', 103 }), 104 ]); 105 }); 106 });