NotificationsPage.test.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /**
  2. * Tests for the NotificationsPage component.
  3. */
  4. import { describe, it, expect, beforeEach } from 'vitest';
  5. import { screen, waitFor } from '@testing-library/react';
  6. import userEvent from '@testing-library/user-event';
  7. import { render } from '../utils';
  8. import { NotificationsPage } from '../../pages/NotificationsPage';
  9. import { http, HttpResponse } from 'msw';
  10. import { server } from '../mocks/server';
  11. const mockPreferences = {
  12. notify_print_start: true,
  13. notify_print_complete: true,
  14. notify_print_failed: true,
  15. notify_print_stopped: true,
  16. };
  17. const mockAdvancedAuthEnabled = {
  18. advanced_auth_enabled: true,
  19. smtp_configured: true,
  20. local_login_enabled: true,
  21. autologin_provider_id: null,
  22. };
  23. const mockSettingsWithNotifications = {
  24. auto_archive: true,
  25. user_notifications_enabled: true,
  26. };
  27. describe('NotificationsPage', () => {
  28. beforeEach(() => {
  29. server.use(
  30. http.get('/api/v1/auth/advanced-auth/status', () => {
  31. return HttpResponse.json(mockAdvancedAuthEnabled);
  32. }),
  33. http.get('/api/v1/user-notifications/preferences', () => {
  34. return HttpResponse.json(mockPreferences);
  35. }),
  36. http.put('/api/v1/user-notifications/preferences', async ({ request }) => {
  37. const body = await request.json();
  38. return HttpResponse.json(body);
  39. }),
  40. http.get('/api/v1/settings/', () => {
  41. return HttpResponse.json(mockSettingsWithNotifications);
  42. }),
  43. http.get('*/api/v1/auth/status', () => {
  44. return HttpResponse.json({ auth_enabled: false, requires_setup: false });
  45. }),
  46. http.get('/api/v1/auth/me', () => {
  47. return HttpResponse.json({
  48. id: 1,
  49. username: 'testuser',
  50. email: 'test@example.com',
  51. role: 'admin',
  52. is_active: true,
  53. is_admin: true,
  54. groups: [{ id: 1, name: 'Administrators' }],
  55. permissions: [],
  56. created_at: '2024-01-01T00:00:00Z',
  57. });
  58. })
  59. );
  60. });
  61. describe('rendering', () => {
  62. it('renders the page heading', async () => {
  63. render(<NotificationsPage />);
  64. await waitFor(() => {
  65. expect(screen.getByText('Notifications')).toBeInTheDocument();
  66. });
  67. });
  68. it('renders all four notification toggle options', async () => {
  69. render(<NotificationsPage />);
  70. await waitFor(() => {
  71. expect(screen.getByText('Print Job Starts')).toBeInTheDocument();
  72. expect(screen.getByText('Print Job Finishes')).toBeInTheDocument();
  73. expect(screen.getByText('Print Errors')).toBeInTheDocument();
  74. expect(screen.getByText('Print Job Stops')).toBeInTheDocument();
  75. });
  76. });
  77. it('renders four toggle switches', async () => {
  78. render(<NotificationsPage />);
  79. await waitFor(() => {
  80. const switches = screen.getAllByRole('switch');
  81. expect(switches).toHaveLength(4);
  82. });
  83. });
  84. it('renders save button', async () => {
  85. render(<NotificationsPage />);
  86. await waitFor(() => {
  87. expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument();
  88. });
  89. });
  90. it('shows loading spinner initially', () => {
  91. render(<NotificationsPage />);
  92. expect(document.querySelector('.animate-spin')).toBeInTheDocument();
  93. });
  94. });
  95. describe('toggle interaction', () => {
  96. it('toggles switch state when clicked', async () => {
  97. const user = userEvent.setup();
  98. render(<NotificationsPage />);
  99. await waitFor(() => {
  100. expect(screen.getAllByRole('switch')).toHaveLength(4);
  101. });
  102. const switches = screen.getAllByRole('switch');
  103. // All should start checked (matching mock preferences)
  104. expect(switches[0]).toHaveAttribute('aria-checked', 'true');
  105. await user.click(switches[0]); // Toggle print start off
  106. expect(switches[0]).toHaveAttribute('aria-checked', 'false');
  107. });
  108. });
  109. describe('redirect behavior', () => {
  110. it('does not redirect when advanced auth is enabled and notifications are enabled', async () => {
  111. render(<NotificationsPage />);
  112. await waitFor(() => {
  113. expect(screen.getByText('Notifications')).toBeInTheDocument();
  114. });
  115. });
  116. });
  117. });