/**
* Tests for the HeaterHistoryModal component.
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { screen, waitFor, fireEvent } from '@testing-library/react';
import { render } from '../utils';
import { HeaterHistoryModal } from '../../components/HeaterHistoryModal';
import { api } from '../../api/client';
vi.mock('../../api/client', () => ({
api: {
getPrinterSensorHistory: vi.fn(),
getSettings: vi.fn().mockResolvedValue({}),
updateSettings: vi.fn().mockResolvedValue({}),
},
}));
vi.mock('recharts', () => ({
LineChart: ({ children }: { children: React.ReactNode }) =>
{children}
,
Line: () => null,
XAxis: () => null,
YAxis: () => null,
CartesianGrid: () => null,
Tooltip: () => null,
ResponsiveContainer: ({ children }: { children: React.ReactNode }) => {children}
,
Legend: () => null,
}));
const mockResponse = {
printer_id: 1,
series: [
{
sensor_kind: 'nozzle' as const,
data: [
{ recorded_at: '2024-12-11T10:00:00Z', value: 210, target: 220 },
{ recorded_at: '2024-12-11T10:05:00Z', value: 215, target: 220 },
{ recorded_at: '2024-12-11T10:10:00Z', value: 220, target: 220 },
],
min_value: 210,
max_value: 220,
avg_value: 215,
},
{
sensor_kind: 'bed' as const,
data: [
{ recorded_at: '2024-12-11T10:00:00Z', value: 55, target: 60 },
{ recorded_at: '2024-12-11T10:05:00Z', value: 60, target: 60 },
],
min_value: 55,
max_value: 60,
avg_value: 57.5,
},
{
sensor_kind: 'chamber' as const,
data: [],
min_value: null,
max_value: null,
avg_value: null,
},
],
};
const defaultProps = {
isOpen: true,
onClose: vi.fn(),
printerId: 1,
printerName: 'Test Printer',
initialKind: 'nozzle' as const,
availableKinds: ['nozzle', 'bed', 'chamber'] as const,
};
describe('HeaterHistoryModal', () => {
beforeEach(() => {
vi.clearAllMocks();
(api.getPrinterSensorHistory as ReturnType).mockResolvedValue(mockResponse);
});
it('renders nothing when closed', () => {
render();
expect(screen.queryByText(/Heater History/i)).not.toBeInTheDocument();
});
it('renders title + printer name when open', async () => {
render();
await waitFor(() => {
expect(screen.getByText(/Heater History/i)).toBeInTheDocument();
expect(screen.getByText('Test Printer')).toBeInTheDocument();
});
});
it('shows current nozzle value from last data point', async () => {
render();
await waitFor(() => {
// current=220, target=220, max=220 — multiple matches are expected.
expect(screen.getAllByText(/220°C/).length).toBeGreaterThan(0);
});
});
it('switches series when bed mode button clicked', async () => {
render();
await waitFor(() => {
expect(screen.getByText('Test Printer')).toBeInTheDocument();
});
const bedButtons = screen.getAllByText(/^Bed$/);
fireEvent.click(bedButtons[0]);
await waitFor(() => {
// 60 = current bed value (and max, and target).
expect(screen.getAllByText(/60°C/).length).toBeGreaterThan(0);
});
});
it('shows empty state when series has no data', async () => {
render();
await waitFor(() => {
expect(screen.getByText(/No data recorded yet/i)).toBeInTheDocument();
});
});
it('close button triggers onClose', async () => {
const onClose = vi.fn();
render();
await waitFor(() => {
expect(screen.getByText('Test Printer')).toBeInTheDocument();
});
fireEvent.click(screen.getByLabelText(/Close/i));
expect(onClose).toHaveBeenCalled();
});
});