import { User } from '@/prisma/generated/client'; import { cleanup, render, screen } from '@testing-library/react'; import type { ReactNode } from 'react'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import FormField from './FormField'; import Loader from './Loader'; import NavBar from './NavBar'; import NavHeader from './NavHeader'; import OTPInputWrapper from './OTPInputWrapper'; import Page from './Page'; import PageBody from './PageBody'; import PageContainer from './PageContainer'; import PageFooter from './PageFooter'; import PageFooterSponsor from './PageFooterSponsor'; import PageHeader from './PageHeader'; import Placeholder from './Placeholder'; import TimeDiff from './TimeDiff'; import NavSidebar from './NavSidebar'; import UserAvatar from './UserAvatar'; import { renderWithIntl } from '@/utils/test/renderWithIntl'; vi.mock('next-intl/server', () => ({ getTranslations: vi.fn(async () => { return (key: string) => { if (key === 'madeWith') return 'Made with'; if (key === 'by') return 'by'; if (key === 'sourceCode') return 'Source code'; if (key === 'buyMeCoffee') return 'Buy me a Coffee'; return key; }; }), })); vi.mock('input-otp', () => ({ __esModule: true, OTPInput: ({ onChange }: { onChange: (value: string) => void }) => ( onChange(e.target.value)} /> ), SlotProps: ({ char, isActive }: { char: string; isActive: boolean }) => (
{char}
), })); vi.mock('@/app/login/lib/actions', () => ({ getCurrentSession: () => { return { user: { id: 1, name: 'Test User', role: 'user', }, }; }, })); const mockUsePathname = vi.fn(() => '/'); vi.mock('next/navigation', () => ({ usePathname: () => mockUsePathname(), useSearchParams: () => new URLSearchParams(), })); type OTPInputRenderProps = { slots: []; }; vi.mock('input-otp', () => ({ __esModule: true, OTPInput: ({ render, }: { render: (props: OTPInputRenderProps) => ReactNode; }) => { return
{render({ slots: [] })}
; }, SlotProps: ({ char, isActive }: { char: string; isActive: boolean }) => (
{char}q
), })); describe('Component Tests', () => { beforeEach(() => { cleanup(); }); it('renders TimeDiff component', () => { const { container } = render(); expect(container).toBeInTheDocument(); }); it('renders Placeholder component', () => { const { container } = render(); expect(container).toBeInTheDocument(); }); it('renders Placeholder component with only background', () => { const { container } = render(); expect(container).toBeInTheDocument(); expect(container.querySelector('.card-body')).not.toBeInTheDocument(); }); it('renders PageHeader component', () => { const { container } = render( , ); expect(container).toBeInTheDocument(); }); it('renders PageHeader component with breadcrumbs', () => { const { container } = render( , ); expect(container).toBeInTheDocument(); expect(screen.getByText('Home')).toBeInTheDocument(); expect(screen.getByText('Dashboard')).toBeInTheDocument(); }); // TODO: implement image in the new ui // it('renders PageHeader component with imageUrl', () => { // const { container } = render( // // ); // expect(container).toBeInTheDocument(); // expect(container.querySelector('img')).toBeInTheDocument(); // }); it('renders PageFooterSponsor component', async () => { const pageFooterSponsor = await PageFooterSponsor(); const { container } = render(pageFooterSponsor); expect(container).toBeInTheDocument(); }); it('renders PageFooter component', async () => { const pageFooter = await PageFooter(); const { container } = render(pageFooter); expect(container).toBeInTheDocument(); }); it('renders PageFooterSponsor component inside PageFooter', async () => { vi.stubEnv('SHOW_SPONSOR_FOOTER', 'true'); const pageFooter = await PageFooter(); const { container } = render(pageFooter); expect(container).toBeInTheDocument(); expect(screen.getByText('Buy me a Coffee')).toBeInTheDocument(); }); it('does not render PageFooterSponsor component inside PageFooter when env is false', async () => { vi.stubEnv('SHOW_SPONSOR_FOOTER', 'false'); const pageFooter = await PageFooter(); const { container } = render(pageFooter); expect(container).toBeInTheDocument(); expect(screen.queryByText('Buy me a Coffee')).not.toBeInTheDocument(); }); it('renders PageContainer component', async () => { const pageContainer = await PageContainer({ children:
Test
}); const { container } = render(pageContainer); expect(container).toBeInTheDocument(); }); it('renders PageBody component', () => { const { container } = render(Test Content); expect(container).toBeInTheDocument(); }); it('renders Page component', async () => { const page = await Page({ children:
Test
}); const { container } = render(page); expect(container).toBeInTheDocument(); }); it('renders OTPInputWrapper component', () => { const { container } = render( {}} />); expect(container).toBeInTheDocument(); }); it('renders OTPInputWrapper component with slots', () => { const { container } = render( {}} />); expect(container).toBeInTheDocument(); expect(screen.getByText('-')).toBeInTheDocument(); }); it('renders NavHeader component', async () => { const { container } = renderWithIntl( , ); expect(container).toBeInTheDocument(); }); it('renders up to two user initials', () => { render(); expect(screen.getByText('AQ')).toBeInTheDocument(); }); it('renders NavBar component', () => { const { container } = renderWithIntl( , ); expect(container).toBeInTheDocument(); }); it('renders NavBar component with admin role', () => { const { container } = renderWithIntl( , ); expect(container).toBeInTheDocument(); expect(screen.getByText('Admin')).toBeInTheDocument(); }); it('not shows admin nav for non-admin users', () => { const { container } = renderWithIntl( , ); expect(container).toBeInTheDocument(); expect(screen.queryByText('Admin')).not.toBeInTheDocument(); }); it('shows favorites and recent nav icons only when collapsed', () => { const user = { id: 1, role: 'user' } as User; const { rerender } = renderWithIntl(); expect(document.querySelector('a[href="/favorites"]')).toBeNull(); rerender(); expect(document.querySelector('a[href="/favorites"]')).not.toBeNull(); expect(document.querySelector('a[href="/recent"]')).not.toBeNull(); }); it('renders expanded quick links with see more in NavBar', () => { renderWithIntl( , ); expect(screen.getByText('My fav note').closest('a')).toHaveAttribute( 'href', '/boards/1/notes/2', ); expect(screen.getByText('My recent board')).toBeInTheDocument(); const seeMore = screen.getAllByText('See more').map((a) => a.getAttribute('href')); expect(seeMore).toEqual(['/favorites', '/recent']); }); it('renders Loader component', () => { const { container } = render(); expect(container).toBeInTheDocument(); }); it('renders FormField component', () => { const { container } = render(); expect(container).toBeInTheDocument(); }); it('renders NavSidebar component', () => { const { container } = renderWithIntl( , ); expect(container).toBeInTheDocument(); }); it('renders Loader component', () => { const { container } = render(); expect(container).toBeInTheDocument(); }); });