/** * @vitest-environment happy-dom */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { render } from '@testing-library/react'; import React from 'react'; import { PRCleanupScreen } from '../../../components/screens/PRCleanupScreen.js'; import { Window } from 'happy-dom'; import type { CleanupTarget } from '../../../types.js'; describe('PRCleanupScreen', () => { beforeEach(() => { // Setup happy-dom const window = new Window(); globalThis.window = window as any; globalThis.document = window.document as any; }); const mockTargets: CleanupTarget[] = [ { branch: 'feature/add-new-feature', cleanupType: 'worktree-and-branch', pullRequest: { number: 123, title: 'Add new feature', branch: 'feature/add-new-feature', mergedAt: '2025-01-20T10:00:00Z', author: 'user1', }, worktreePath: '/workspace/feature-add-new-feature', hasUncommittedChanges: false, hasUnpushedCommits: false, hasRemoteBranch: true, isAccessible: true, }, { branch: 'hotfix/fix-bug', cleanupType: 'branch-only', pullRequest: { number: 124, title: 'Fix bug', branch: 'hotfix/fix-bug', mergedAt: '2025-01-21T15:30:00Z', author: 'user2', }, worktreePath: null, hasUncommittedChanges: false, hasUnpushedCommits: false, hasRemoteBranch: false, }, ]; it('should render header with title', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { getByText } = render( ); expect(getByText(/Branch Cleanup/i)).toBeDefined(); }); it('should render PR list', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { getByText } = render( ); expect(getByText(/feature\/add-new-feature/i)).toBeDefined(); expect(getByText(/hotfix\/fix-bug/i)).toBeDefined(); }); it('should render footer with actions', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { getAllByText } = render( ); expect(getAllByText(/enter/i).length).toBeGreaterThan(0); expect(getAllByText(/esc/i).length).toBeGreaterThan(0); }); it('should handle empty PR list', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { getByText } = render( ); expect(getByText(/No cleanup targets found/i)).toBeDefined(); }); it('should display PR count in stats', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { getByText, getAllByText } = render( ); expect(getByText(/Total:/i)).toBeDefined(); expect(getAllByText(/^2$/).length).toBeGreaterThan(0); }); it('should use terminal height for layout calculation', () => { const originalRows = process.stdout.rows; process.stdout.rows = 30; const onBack = vi.fn(); const onCleanup = vi.fn(); const { container } = render( ); expect(container).toBeDefined(); process.stdout.rows = originalRows; }); it('should handle back navigation with ESC key', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { container } = render( ); // Test will verify onBack is called when ESC is pressed expect(container).toBeDefined(); }); it('should render status message when provided', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { getByText } = render( ); expect(getByText(/Cleanup completed/i)).toBeDefined(); }); it('should render loading message when loading', () => { const onBack = vi.fn(); const onCleanup = vi.fn(); const { getByText } = render( ); expect(getByText(/Loading cleanup targets/i)).toBeDefined(); }); });