2026-05-14 14:47:23 +09:00
|
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
|
import { render, screen } from '@testing-library/react';
|
|
|
|
|
import { Avatar } from '../ui/Avatar';
|
|
|
|
|
import { IconButton } from '../ui/IconButton';
|
|
|
|
|
import { Ring } from '../ui/Ring';
|
|
|
|
|
import { SparkBars } from '../ui/SparkBars';
|
|
|
|
|
import { SupplyBar } from '../ui/SupplyBar';
|
2026-05-19 10:13:40 +09:00
|
|
|
import { Card, CardHeader, CardBody } from '../ui/Card';
|
2026-05-14 14:47:23 +09:00
|
|
|
|
|
|
|
|
describe('Avatar', () => {
|
|
|
|
|
it('renders initial from name', () => {
|
|
|
|
|
render(<Avatar name="Alice" />);
|
|
|
|
|
expect(screen.getByLabelText('Alice')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByText('A')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('uses custom size', () => {
|
|
|
|
|
render(<Avatar name="Bob" size={48} />);
|
|
|
|
|
const el = screen.getByLabelText('Bob');
|
|
|
|
|
expect(el).toHaveStyle({ width: '48px', height: '48px' });
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('IconButton', () => {
|
|
|
|
|
it('renders with label and icon', () => {
|
|
|
|
|
render(<IconButton icon="settings" label="Settings" />);
|
|
|
|
|
expect(screen.getByLabelText('Settings')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders notification dot when dot=true', () => {
|
|
|
|
|
render(<IconButton icon="bell" label="Notifications" dot />);
|
|
|
|
|
// dot is a span inside the button
|
|
|
|
|
const btn = screen.getByLabelText('Notifications');
|
|
|
|
|
expect(btn.querySelectorAll('span').length).toBeGreaterThanOrEqual(1);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Ring', () => {
|
|
|
|
|
it('renders value and total', () => {
|
|
|
|
|
render(<Ring value={5} total={10} />);
|
|
|
|
|
expect(screen.getByLabelText('5 of 10 doses taken')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByText('5')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('handles zero total', () => {
|
|
|
|
|
render(<Ring value={0} total={0} />);
|
|
|
|
|
expect(screen.getByText('0')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('SparkBars', () => {
|
|
|
|
|
it('renders bars with labels', () => {
|
|
|
|
|
const data = [
|
|
|
|
|
{ label: 'Jan', amount: 100 },
|
|
|
|
|
{ label: 'Feb', amount: 200 },
|
|
|
|
|
];
|
|
|
|
|
render(<SparkBars data={data} />);
|
|
|
|
|
expect(screen.getByText('Jan')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByText('Feb')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders formatted amounts', () => {
|
|
|
|
|
const data = [{ label: 'Mar', amount: 5000 }];
|
|
|
|
|
render(<SparkBars data={data} />);
|
|
|
|
|
expect(screen.getByText('5k')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('SupplyBar', () => {
|
|
|
|
|
it('renders days value', () => {
|
|
|
|
|
render(<SupplyBar days={30} />);
|
|
|
|
|
expect(screen.getByText('30')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByText('d')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders for critical days', () => {
|
|
|
|
|
render(<SupplyBar days={5} />);
|
|
|
|
|
expect(screen.getByText('5')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders for medium days', () => {
|
|
|
|
|
render(<SupplyBar days={10} />);
|
|
|
|
|
expect(screen.getByText('10')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-05-19 10:13:40 +09:00
|
|
|
|
|
|
|
|
describe('Card', () => {
|
|
|
|
|
it('renders children and applies custom styles', () => {
|
|
|
|
|
render(
|
|
|
|
|
<Card className="custom-card" style={{ margin: '20px' }}>
|
|
|
|
|
<div>Card Content</div>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
|
|
|
|
expect(screen.getByText('Card Content')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders header with title, subtitle and action', () => {
|
|
|
|
|
render(
|
|
|
|
|
<CardHeader
|
|
|
|
|
title="My Card"
|
|
|
|
|
subtitle="My Subtitle"
|
|
|
|
|
action={<button>Click Me</button>}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
expect(screen.getByText('My Card')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByText('My Subtitle')).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByRole('button', { name: 'Click Me' })).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('renders body with children', () => {
|
|
|
|
|
render(
|
|
|
|
|
<CardBody>
|
|
|
|
|
<div>Body Content</div>
|
|
|
|
|
</CardBody>
|
|
|
|
|
);
|
|
|
|
|
expect(screen.getByText('Body Content')).toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
});
|