From e541d904f2a85cabc0826c7353c9a05d2da5390c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 1 Jan 2026 09:13:41 +0100 Subject: [PATCH] test: cover bookmark folder parsing and count fallback --- tests/cli.test.ts | 5 +++ tests/twitter-client.test.ts | 75 ++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/tests/cli.test.ts b/tests/cli.test.ts index d483106..a3f5a9d 100644 --- a/tests/cli.test.ts +++ b/tests/cli.test.ts @@ -50,5 +50,10 @@ describe('CLI utilities', () => { it('should return null for invalid values', () => { expect(extractBookmarkFolderId('not-an-id')).toBeNull(); }); + + it('should return null for folder_id query URLs', () => { + const url = 'https://x.com/i/bookmarks?folder_id=1976792203235119344'; + expect(extractBookmarkFolderId(url)).toBeNull(); + }); }); }); diff --git a/tests/twitter-client.test.ts b/tests/twitter-client.test.ts index 9c722ab..941b101 100644 --- a/tests/twitter-client.test.ts +++ b/tests/twitter-client.test.ts @@ -1215,6 +1215,81 @@ describe('TwitterClient', () => { const parsedFeatures = JSON.parse(new URL(url as string).searchParams.get('features') as string); expect(parsedFeatures.graphql_timeline_v2_bookmark_timeline).toBe(true); }); + + it('retries without count when API rejects the count variable', async () => { + mockFetch + .mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => ({ + errors: [{ message: 'Variable "$count" is not defined by operation' }], + }), + }) + .mockResolvedValueOnce({ + ok: true, + status: 200, + json: async () => ({ + data: { + bookmark_collection_timeline: { + timeline: { + instructions: [ + { + entries: [ + { + content: { + itemContent: { + tweet_results: { + result: { + rest_id: '9', + legacy: { + full_text: 'saved in folder', + created_at: '2024-01-01T00:00:00Z', + reply_count: 0, + retweet_count: 0, + favorite_count: 0, + conversation_id_str: '9', + }, + core: { + user_results: { + result: { + rest_id: 'u9', + legacy: { screen_name: 'folder', name: 'Folder' }, + }, + }, + }, + }, + }, + }, + }, + }, + ], + }, + ], + }, + }, + }, + }), + }); + + const client = new TwitterClient({ cookies: validCookies }); + const clientPrivate = client as TwitterClient & { getBookmarkFolderQueryIds: () => Promise }; + clientPrivate.getBookmarkFolderQueryIds = async () => ['test']; + + const result = await client.getBookmarkFolderTimeline('123', 2); + + expect(result.success).toBe(true); + expect(mockFetch).toHaveBeenCalledTimes(2); + + const firstVars = JSON.parse( + new URL(mockFetch.mock.calls[0][0] as string).searchParams.get('variables') as string, + ); + const secondVars = JSON.parse( + new URL(mockFetch.mock.calls[1][0] as string).searchParams.get('variables') as string, + ); + + expect(firstVars.count).toBe(2); + expect(secondVars.count).toBeUndefined(); + }); }); describe('conversation helpers', () => {