84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { render, screen } from '@testing-library/react';
|
|
|
|
const { mockUsePathname } = vi.hoisted(() => ({
|
|
mockUsePathname: vi.fn(),
|
|
}));
|
|
|
|
const { mockUseApi } = vi.hoisted(() => ({
|
|
mockUseApi: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('next/navigation', () => ({
|
|
usePathname: mockUsePathname,
|
|
}));
|
|
|
|
vi.mock('next/link', () => ({
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
default: (props: any) => <a href={props.href}>{props.children}</a>,
|
|
}));
|
|
|
|
vi.mock('@/lib/useApi', () => ({ useApi: mockUseApi }));
|
|
|
|
import { Sidebar } from '../../src/components/layout/Sidebar';
|
|
|
|
describe('Sidebar', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mockUsePathname.mockReturnValue('/dashboard');
|
|
mockUseApi.mockReturnValue({ profile: { displayName: 'Alice' } });
|
|
});
|
|
|
|
it('renders brand name', () => {
|
|
render(<Sidebar />);
|
|
expect(screen.getByText('MeshiTrack')).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders navigation sections', () => {
|
|
render(<Sidebar />);
|
|
expect(screen.getByText('Dashboard')).toBeInTheDocument();
|
|
expect(screen.getByText('Medicines')).toBeInTheDocument();
|
|
expect(screen.getByText('Food')).toBeInTheDocument();
|
|
expect(screen.getByText('Settings')).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders medicines nav items', () => {
|
|
render(<Sidebar />);
|
|
expect(screen.getByText('Cabinet')).toBeInTheDocument();
|
|
expect(screen.getByText('Schedule & Log')).toBeInTheDocument();
|
|
expect(screen.getByText('Regimens')).toBeInTheDocument();
|
|
expect(screen.getByText('Library')).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders food nav items', () => {
|
|
render(<Sidebar />);
|
|
expect(screen.getByText('Recipes')).toBeInTheDocument();
|
|
expect(screen.getByText('Pantry')).toBeInTheDocument();
|
|
});
|
|
|
|
it('highlights active route', () => {
|
|
mockUsePathname.mockReturnValue('/medicines/cabinet');
|
|
render(<Sidebar />);
|
|
const cabinetLink = screen.getByText('Cabinet').closest('a');
|
|
expect(cabinetLink).toHaveAttribute('href', '/medicines/cabinet');
|
|
});
|
|
|
|
it('shows user avatar with display name', () => {
|
|
render(<Sidebar />);
|
|
expect(screen.getByLabelText('Alice')).toBeInTheDocument();
|
|
});
|
|
|
|
it('shows fallback name when no profile', () => {
|
|
mockUseApi.mockReturnValue({ profile: null });
|
|
render(<Sidebar />);
|
|
expect(screen.getByLabelText('User')).toBeInTheDocument();
|
|
});
|
|
|
|
it('highlights nested route', () => {
|
|
mockUsePathname.mockReturnValue('/medicines/cabinet/some-id');
|
|
render(<Sidebar />);
|
|
// Cabinet link should still match via startsWith
|
|
const cabinetLink = screen.getByText('Cabinet').closest('a');
|
|
expect(cabinetLink).toBeInTheDocument();
|
|
});
|
|
});
|