| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- /**
- * 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;
- }) => (
- <div data-testid="notification-provider-card">
- <span data-testid="provider-name">{provider.name}</span>
- <span data-testid="provider-type">{provider.provider_type}</span>
- <span data-testid="provider-enabled">
- {provider.enabled ? 'Enabled' : 'Disabled'}
- </span>
- <span data-testid="on-print-start">
- {provider.on_print_start ? 'Yes' : 'No'}
- </span>
- <span data-testid="on-print-complete">
- {provider.on_print_complete ? 'Yes' : 'No'}
- </span>
- <button onClick={onEdit}>Edit</button>
- </div>
- ),
- }));
- // Import after mocking
- const { NotificationProviderCard } = await import(
- '../../components/NotificationProviderCard'
- );
- // Mock data
- const createMockProvider = (
- overrides: Partial<NotificationProvider> = {}
- ): 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(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- expect(screen.getByTestId('provider-name')).toHaveTextContent(
- 'My Notifications'
- );
- });
- it('renders provider type', () => {
- const provider = createMockProvider({ provider_type: 'telegram' });
- render(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- expect(screen.getByTestId('provider-type')).toHaveTextContent('telegram');
- });
- it('shows enabled status', () => {
- const provider = createMockProvider({ enabled: true });
- render(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- expect(screen.getByTestId('provider-enabled')).toHaveTextContent(
- 'Enabled'
- );
- });
- it('shows disabled status', () => {
- const provider = createMockProvider({ enabled: false });
- render(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- 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(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- expect(screen.getByTestId('on-print-start')).toHaveTextContent('Yes');
- });
- it('shows on_print_start correctly when disabled', () => {
- const provider = createMockProvider({ on_print_start: false });
- render(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- expect(screen.getByTestId('on-print-start')).toHaveTextContent('No');
- });
- it('shows on_print_complete correctly', () => {
- const provider = createMockProvider({ on_print_complete: true });
- render(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- 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(
- <NotificationProviderCard provider={provider} onEdit={mockOnEdit} />
- );
- 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(
- <NotificationProviderCard provider={provider} onEdit={vi.fn()} />
- );
- 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);
- });
- });
- });
|