/** * 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); }); }); });