/**
* Tests for the NotificationProviderCard component.
*
* These tests cover notification provider display and toggle functionality.
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render } from '../utils';
import type { NotificationProvider } from '../../api/client';
// Mock the component if it exists
vi.mock('../../components/NotificationProviderCard', () => ({
NotificationProviderCard: ({
provider,
onEdit,
}: {
provider: NotificationProvider;
onEdit: () => void;
}) => (
{provider.name}
{provider.provider_type}
{provider.enabled ? 'Enabled' : 'Disabled'}
{provider.on_print_start ? 'Yes' : 'No'}
{provider.on_print_complete ? 'Yes' : 'No'}
),
}));
// Import after mocking
const { NotificationProviderCard } = await import(
'../../components/NotificationProviderCard'
);
// Mock data
const createMockProvider = (
overrides: Partial = {}
): NotificationProvider => ({
id: 1,
name: 'Test Provider',
provider_type: 'ntfy',
enabled: true,
config: { server: 'https://ntfy.sh', topic: 'test' },
on_print_start: true,
on_print_complete: true,
on_print_failed: true,
on_print_stopped: false,
on_print_progress: false,
on_printer_offline: false,
on_printer_error: false,
on_filament_low: false,
on_maintenance_due: false,
on_ams_humidity_high: false,
on_ams_temperature_high: false,
on_ams_ht_humidity_high: false,
on_ams_ht_temperature_high: false,
on_plate_not_empty: true,
on_bed_cooled: false,
on_first_layer_complete: false,
on_queue_job_added: false,
on_queue_job_assigned: false,
on_queue_job_started: false,
on_queue_job_waiting: true,
on_queue_job_skipped: true,
on_queue_job_failed: true,
on_queue_completed: false,
on_stock_reorder_alert: false,
on_stock_break_alert: false,
quiet_hours_enabled: false,
quiet_hours_start: null,
quiet_hours_end: null,
daily_digest_enabled: false,
daily_digest_time: null,
printer_id: null,
last_success: null,
last_error: null,
last_error_at: null,
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-01T00:00:00Z',
...overrides,
});
describe('NotificationProviderCard', () => {
const mockOnEdit = vi.fn();
beforeEach(() => {
vi.clearAllMocks();
});
describe('rendering', () => {
it('renders provider name', () => {
const provider = createMockProvider({ name: 'My Notifications' });
render(
);
expect(screen.getByTestId('provider-name')).toHaveTextContent(
'My Notifications'
);
});
it('renders provider type', () => {
const provider = createMockProvider({ provider_type: 'telegram' });
render(
);
expect(screen.getByTestId('provider-type')).toHaveTextContent('telegram');
});
it('shows enabled status', () => {
const provider = createMockProvider({ enabled: true });
render(
);
expect(screen.getByTestId('provider-enabled')).toHaveTextContent(
'Enabled'
);
});
it('shows disabled status', () => {
const provider = createMockProvider({ enabled: false });
render(
);
expect(screen.getByTestId('provider-enabled')).toHaveTextContent(
'Disabled'
);
});
});
describe('event toggles', () => {
it('shows on_print_start correctly when enabled', () => {
const provider = createMockProvider({ on_print_start: true });
render(
);
expect(screen.getByTestId('on-print-start')).toHaveTextContent('Yes');
});
it('shows on_print_start correctly when disabled', () => {
const provider = createMockProvider({ on_print_start: false });
render(
);
expect(screen.getByTestId('on-print-start')).toHaveTextContent('No');
});
it('shows on_print_complete correctly', () => {
const provider = createMockProvider({ on_print_complete: true });
render(
);
expect(screen.getByTestId('on-print-complete')).toHaveTextContent('Yes');
});
});
describe('edit functionality', () => {
it('calls onEdit when edit button is clicked', async () => {
const user = userEvent.setup();
const provider = createMockProvider();
render(
);
await user.click(screen.getByRole('button', { name: /edit/i }));
expect(mockOnEdit).toHaveBeenCalled();
});
});
});
describe('NotificationProviderCard AMS toggles', () => {
describe('AMS humidity notifications', () => {
it('includes on_ams_humidity_high in provider data', () => {
const provider = createMockProvider({ on_ams_humidity_high: true });
expect(provider.on_ams_humidity_high).toBe(true);
});
it('includes on_ams_humidity_high when disabled', () => {
const provider = createMockProvider({ on_ams_humidity_high: false });
expect(provider.on_ams_humidity_high).toBe(false);
});
});
describe('AMS temperature notifications', () => {
it('includes on_ams_temperature_high in provider data', () => {
const provider = createMockProvider({ on_ams_temperature_high: true });
expect(provider.on_ams_temperature_high).toBe(true);
});
it('includes on_ams_temperature_high when disabled', () => {
const provider = createMockProvider({ on_ams_temperature_high: false });
expect(provider.on_ams_temperature_high).toBe(false);
});
});
describe('AMS-HT humidity notifications (separate from AMS)', () => {
it('includes on_ams_ht_humidity_high in provider data', () => {
const provider = createMockProvider({ on_ams_ht_humidity_high: true });
expect(provider.on_ams_ht_humidity_high).toBe(true);
});
it('AMS and AMS-HT humidity toggles are independent', () => {
const provider = createMockProvider({
on_ams_humidity_high: true,
on_ams_ht_humidity_high: false,
});
expect(provider.on_ams_humidity_high).toBe(true);
expect(provider.on_ams_ht_humidity_high).toBe(false);
});
it('can enable both AMS and AMS-HT humidity notifications', () => {
const provider = createMockProvider({
on_ams_humidity_high: true,
on_ams_ht_humidity_high: true,
});
expect(provider.on_ams_humidity_high).toBe(true);
expect(provider.on_ams_ht_humidity_high).toBe(true);
});
});
describe('AMS-HT temperature notifications (separate from AMS)', () => {
it('includes on_ams_ht_temperature_high in provider data', () => {
const provider = createMockProvider({ on_ams_ht_temperature_high: true });
expect(provider.on_ams_ht_temperature_high).toBe(true);
});
it('AMS and AMS-HT temperature toggles are independent', () => {
const provider = createMockProvider({
on_ams_temperature_high: true,
on_ams_ht_temperature_high: false,
});
expect(provider.on_ams_temperature_high).toBe(true);
expect(provider.on_ams_ht_temperature_high).toBe(false);
});
it('can enable both AMS and AMS-HT temperature notifications', () => {
const provider = createMockProvider({
on_ams_temperature_high: true,
on_ams_ht_temperature_high: true,
});
expect(provider.on_ams_temperature_high).toBe(true);
expect(provider.on_ams_ht_temperature_high).toBe(true);
});
});
describe('all AMS notification combinations', () => {
it('supports all four AMS toggles independently', () => {
const provider = createMockProvider({
on_ams_humidity_high: true,
on_ams_temperature_high: false,
on_ams_ht_humidity_high: false,
on_ams_ht_temperature_high: true,
});
expect(provider.on_ams_humidity_high).toBe(true);
expect(provider.on_ams_temperature_high).toBe(false);
expect(provider.on_ams_ht_humidity_high).toBe(false);
expect(provider.on_ams_ht_temperature_high).toBe(true);
});
it('defaults all AMS toggles to false', () => {
const provider = createMockProvider();
expect(provider.on_ams_humidity_high).toBe(false);
expect(provider.on_ams_temperature_high).toBe(false);
expect(provider.on_ams_ht_humidity_high).toBe(false);
expect(provider.on_ams_ht_temperature_high).toBe(false);
});
});
});
describe('NotificationProviderCard Queue notifications', () => {
describe('queue job notifications', () => {
it('includes on_queue_job_added in provider data', () => {
const provider = createMockProvider({ on_queue_job_added: true });
expect(provider.on_queue_job_added).toBe(true);
});
it('includes on_queue_job_assigned in provider data', () => {
const provider = createMockProvider({ on_queue_job_assigned: true });
expect(provider.on_queue_job_assigned).toBe(true);
});
it('includes on_queue_job_started in provider data', () => {
const provider = createMockProvider({ on_queue_job_started: true });
expect(provider.on_queue_job_started).toBe(true);
});
it('includes on_queue_job_waiting in provider data', () => {
const provider = createMockProvider({ on_queue_job_waiting: true });
expect(provider.on_queue_job_waiting).toBe(true);
});
it('includes on_queue_job_skipped in provider data', () => {
const provider = createMockProvider({ on_queue_job_skipped: true });
expect(provider.on_queue_job_skipped).toBe(true);
});
it('includes on_queue_job_failed in provider data', () => {
const provider = createMockProvider({ on_queue_job_failed: true });
expect(provider.on_queue_job_failed).toBe(true);
});
it('includes on_queue_completed in provider data', () => {
const provider = createMockProvider({ on_queue_completed: true });
expect(provider.on_queue_completed).toBe(true);
});
});
describe('queue notification defaults', () => {
it('defaults actionable notifications to true', () => {
const provider = createMockProvider();
// These should default to true (actionable - user needs to do something)
expect(provider.on_queue_job_waiting).toBe(true);
expect(provider.on_queue_job_skipped).toBe(true);
expect(provider.on_queue_job_failed).toBe(true);
});
it('defaults informational notifications to false', () => {
const provider = createMockProvider();
// These should default to false (informational only)
expect(provider.on_queue_job_added).toBe(false);
expect(provider.on_queue_job_assigned).toBe(false);
expect(provider.on_queue_job_started).toBe(false);
expect(provider.on_queue_completed).toBe(false);
});
});
describe('queue notification combinations', () => {
it('supports all queue toggles independently', () => {
const provider = createMockProvider({
on_queue_job_added: true,
on_queue_job_assigned: false,
on_queue_job_started: true,
on_queue_job_waiting: false,
on_queue_job_skipped: true,
on_queue_job_failed: false,
on_queue_completed: true,
});
expect(provider.on_queue_job_added).toBe(true);
expect(provider.on_queue_job_assigned).toBe(false);
expect(provider.on_queue_job_started).toBe(true);
expect(provider.on_queue_job_waiting).toBe(false);
expect(provider.on_queue_job_skipped).toBe(true);
expect(provider.on_queue_job_failed).toBe(false);
expect(provider.on_queue_completed).toBe(true);
});
});
});
describe('NotificationProviderCard Bed Cooled notifications', () => {
describe('bed cooled toggle', () => {
it('includes on_bed_cooled in provider data when enabled', () => {
const provider = createMockProvider({ on_bed_cooled: true });
expect(provider.on_bed_cooled).toBe(true);
});
it('includes on_bed_cooled in provider data when disabled', () => {
const provider = createMockProvider({ on_bed_cooled: false });
expect(provider.on_bed_cooled).toBe(false);
});
it('defaults on_bed_cooled to false', () => {
const provider = createMockProvider();
expect(provider.on_bed_cooled).toBe(false);
});
it('bed cooled is independent from other print event toggles', () => {
const provider = createMockProvider({
on_print_complete: true,
on_bed_cooled: true,
on_plate_not_empty: false,
});
expect(provider.on_print_complete).toBe(true);
expect(provider.on_bed_cooled).toBe(true);
expect(provider.on_plate_not_empty).toBe(false);
});
});
});
describe('NotificationProviderCard First Layer Complete notifications', () => {
describe('first layer complete toggle', () => {
it('includes on_first_layer_complete in provider data when enabled', () => {
const provider = createMockProvider({ on_first_layer_complete: true });
expect(provider.on_first_layer_complete).toBe(true);
});
it('includes on_first_layer_complete in provider data when disabled', () => {
const provider = createMockProvider({ on_first_layer_complete: false });
expect(provider.on_first_layer_complete).toBe(false);
});
it('defaults on_first_layer_complete to false', () => {
const provider = createMockProvider();
expect(provider.on_first_layer_complete).toBe(false);
});
it('first layer complete is independent from other print event toggles', () => {
const provider = createMockProvider({
on_print_complete: true,
on_bed_cooled: true,
on_first_layer_complete: false,
});
expect(provider.on_print_complete).toBe(true);
expect(provider.on_bed_cooled).toBe(true);
expect(provider.on_first_layer_complete).toBe(false);
});
it('can enable first layer complete independently', () => {
const provider = createMockProvider({
on_print_complete: false,
on_bed_cooled: false,
on_first_layer_complete: true,
});
expect(provider.on_print_complete).toBe(false);
expect(provider.on_bed_cooled).toBe(false);
expect(provider.on_first_layer_complete).toBe(true);
});
});
});
describe('NotificationProviderCard Home Assistant provider', () => {
describe('homeassistant provider type', () => {
it('renders homeassistant provider type', () => {
const provider = createMockProvider({ provider_type: 'homeassistant' });
render(
);
expect(screen.getByTestId('provider-type')).toHaveTextContent('homeassistant');
});
it('creates homeassistant provider with empty config', () => {
const provider = createMockProvider({
provider_type: 'homeassistant',
config: {},
});
expect(provider.provider_type).toBe('homeassistant');
expect(provider.config).toEqual({});
});
it('homeassistant provider supports all event toggles', () => {
const provider = createMockProvider({
provider_type: 'homeassistant',
config: {},
on_print_complete: true,
on_print_failed: true,
on_filament_low: true,
on_queue_job_waiting: true,
});
expect(provider.on_print_complete).toBe(true);
expect(provider.on_print_failed).toBe(true);
expect(provider.on_filament_low).toBe(true);
expect(provider.on_queue_job_waiting).toBe(true);
});
});
});