mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-09 15:35:39 +02:00
490 lines
16 KiB
TypeScript
490 lines
16 KiB
TypeScript
/**
|
|
* 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);
|
|
});
|
|
});
|
|
});
|