import { Command } from 'commander'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import type { CliContext } from '../src/cli/shared.js'; import { registerHomeCommand } from '../src/commands/home.js'; import { TwitterClient } from '../src/lib/twitter-client.js'; describe('home command', () => { let program: Command; let mockContext: Partial; beforeEach(() => { program = new Command(); mockContext = { resolveTimeoutFromOptions: () => undefined, resolveRelayBaseUrlFromOptions: () => 'https://relay.example', resolveProfileNameFromOptions: () => undefined, p: () => '', printTweetsResult: vi.fn(), }; }); it('uses cursor pagination when --cursor is set', async () => { registerHomeCommand(program, mockContext as CliContext); const timelineSpy = vi .spyOn(TwitterClient.prototype, 'getHomeLatestTimeline') .mockResolvedValue({ success: true, tweets: [], nextCursor: 'next-1' }); try { await program.parseAsync(['node', 'bird', 'home', '--following', '--cursor', 'cursor-1']); expect(timelineSpy).toHaveBeenCalledWith(20, expect.objectContaining({ cursor: 'cursor-1' })); expect(mockContext.printTweetsResult).toHaveBeenCalledWith(expect.objectContaining({ nextCursor: 'next-1' }), { json: false, usePagination: true, emptyMessage: 'No tweets found in Following timeline.', }); } finally { timelineSpy.mockRestore(); } }); it('uses paged home timeline when --max-pages is set', async () => { registerHomeCommand(program, mockContext as CliContext); const timelineSpy = vi.spyOn(TwitterClient.prototype, 'getHomeTimeline').mockResolvedValue({ success: true, tweets: [], nextCursor: 'next-2', }); try { await program.parseAsync(['node', 'bird', 'home', '--max-pages', '3', '--json']); expect(timelineSpy).toHaveBeenCalledWith(20, expect.objectContaining({ maxPages: 3 })); expect(mockContext.printTweetsResult).toHaveBeenCalledWith(expect.objectContaining({ nextCursor: 'next-2' }), { json: true, usePagination: true, emptyMessage: 'No tweets found in For You timeline.', }); } finally { timelineSpy.mockRestore(); } }); });