test: raise coverage above 70%

This commit is contained in:
Peter Steinberger
2025-12-05 23:44:08 +01:00
parent 29913c7e06
commit 80c1ada374
2 changed files with 152 additions and 0 deletions
+40
View File
@@ -136,4 +136,44 @@ describe('cookies', () => {
);
});
});
describe('extractCookiesFromChrome', () => {
it('returns cookies when sqlite yields hex values', async () => {
const fs = await import('node:fs');
const { execSync } = await import('node:child_process');
// Pretend Chrome cookie DB exists
(fs.existsSync as unknown as vi.Mock).mockImplementation((path: string) => path.includes('Cookies'));
(fs.copyFileSync as unknown as vi.Mock).mockImplementation(() => {});
// sqlite output with hex strings ("test_auth", "test_ct0")
(execSync as unknown as vi.Mock).mockImplementation((cmd: string) => {
if (cmd.includes('sqlite3')) {
return 'auth_token|746573745f61757468\nct0|746573745f637430';
}
return '';
});
const { extractCookiesFromChrome } = await import('../src/lib/cookies.js');
const result = await extractCookiesFromChrome('Default');
expect(result.cookies.authToken).toBe('test_auth');
expect(result.cookies.ct0).toBe('test_ct0');
expect(result.cookies.source).toContain('Chrome');
expect(result.warnings).toHaveLength(0);
});
it('warns when Chrome DB exists but contains no cookies', async () => {
const fs = await import('node:fs');
const { execSync } = await import('node:child_process');
(fs.existsSync as unknown as vi.Mock).mockImplementation((path: string) => path.includes('Cookies'));
(fs.copyFileSync as unknown as vi.Mock).mockImplementation(() => {});
(execSync as unknown as vi.Mock).mockReturnValue('');
const { extractCookiesFromChrome } = await import('../src/lib/cookies.js');
const result = await extractCookiesFromChrome('Default');
expect(result.cookies.authToken).toBeNull();
expect(result.cookies.ct0).toBeNull();
expect(result.warnings.some((w) => w.includes('No Twitter cookies found in Chrome'))).toBe(true);
});
});
});
+112
View File
@@ -374,4 +374,116 @@ describe('TwitterClient', () => {
expect(mockFetch).toHaveBeenCalledTimes(5);
});
});
describe('conversation helpers', () => {
let mockFetch: ReturnType<typeof vi.fn>;
beforeEach(() => {
mockFetch = vi.fn();
global.fetch = mockFetch as unknown as typeof fetch;
});
const makeConversationPayload = () => ({
data: {
threaded_conversation_with_injections_v2: {
instructions: [
{
entries: [
{
content: {
itemContent: {
tweet_results: {
result: {
rest_id: '1',
legacy: {
full_text: 'root',
created_at: '2024-01-01T00:00:00Z',
reply_count: 0,
retweet_count: 0,
favorite_count: 0,
conversation_id_str: '1',
},
core: { user_results: { result: { legacy: { screen_name: 'root', name: 'Root' } } } },
},
},
},
},
},
{
content: {
itemContent: {
tweet_results: {
result: {
rest_id: '2',
legacy: {
full_text: 'child reply',
created_at: '2024-01-02T00:00:00Z',
reply_count: 0,
retweet_count: 0,
favorite_count: 0,
conversation_id_str: '1',
in_reply_to_status_id_str: '1',
},
core: { user_results: { result: { legacy: { screen_name: 'child', name: 'Child' } } } },
},
},
},
},
},
],
},
],
},
},
});
it('getReplies returns only replies to tweet', async () => {
mockFetch.mockResolvedValue({
ok: true,
status: 200,
json: async () => makeConversationPayload(),
});
const client = new TwitterClient({ cookies: validCookies });
const result = await client.getReplies('1');
expect(result.success).toBe(true);
expect(result.tweets?.length).toBe(1);
expect(result.tweets?.[0].id).toBe('2');
});
it('getThread returns sorted thread by createdAt', async () => {
const payload = makeConversationPayload();
// swap dates to verify sorting
payload.data.threaded_conversation_with_injections_v2.instructions[0]?.entries?.[0]?.content?.itemContent?.tweet_results?.result?.legacy &&
((payload.data.threaded_conversation_with_injections_v2.instructions[0]!.entries![0]!.content!.itemContent!
.tweet_results!.result!.legacy!.created_at = '2024-01-03T00:00:00Z'));
mockFetch.mockResolvedValue({
ok: true,
status: 200,
json: async () => payload,
});
const client = new TwitterClient({ cookies: validCookies });
const result = await client.getThread('2');
expect(result.success).toBe(true);
expect(result.tweets?.map((t) => t.id)).toEqual(['2', '1']); // sorted by createdAt asc
});
it('propagates fetchTweetDetail errors', async () => {
mockFetch.mockResolvedValue({
ok: false,
status: 500,
text: async () => 'oops',
});
const client = new TwitterClient({ cookies: validCookies });
const result = await client.getThread('1');
expect(result.success).toBe(false);
expect(result.error).toContain('HTTP 500');
});
});
});