ConnectionDiagnosticModal.test.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * Tests for the connection diagnostic modal.
  3. *
  4. * Covers the user-facing contract: the modal runs the diagnostic on mount,
  5. * renders each check's localized title and fix text keyed on id + status,
  6. * picks the right API for printer vs pre-add mode, and re-runs on retry.
  7. */
  8. import { describe, it, expect, vi } from 'vitest';
  9. import { render, screen, waitFor, fireEvent } from '@testing-library/react';
  10. import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
  11. import { I18nextProvider } from 'react-i18next';
  12. import i18n from '../../i18n';
  13. import { ConnectionDiagnosticModal } from '../../components/ConnectionDiagnostic';
  14. import { api, type PrinterDiagnosticResult } from '../../api/client';
  15. const PROBLEM_RESULT: PrinterDiagnosticResult = {
  16. printer_id: 1,
  17. ip_address: '192.168.1.50',
  18. overall: 'problems',
  19. checks: [
  20. { id: 'port_mqtt', status: 'pass', params: {} },
  21. { id: 'port_ftps', status: 'pass', params: {} },
  22. { id: 'port_rtsps', status: 'warn', params: {} },
  23. { id: 'network_mode', status: 'pass', params: { mode: 'host' } },
  24. { id: 'subnet', status: 'pass', params: {} },
  25. { id: 'mqtt_auth', status: 'pass', params: {} },
  26. { id: 'developer_mode', status: 'fail', params: {} },
  27. ],
  28. };
  29. function renderModal(props: Parameters<typeof ConnectionDiagnosticModal>[0]) {
  30. const queryClient = new QueryClient({
  31. defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
  32. });
  33. render(
  34. <QueryClientProvider client={queryClient}>
  35. <I18nextProvider i18n={i18n}>
  36. <ConnectionDiagnosticModal {...props} />
  37. </I18nextProvider>
  38. </QueryClientProvider>,
  39. );
  40. }
  41. describe('ConnectionDiagnosticModal', () => {
  42. it('runs the diagnostic on mount and renders check titles + the overall banner', async () => {
  43. const spy = vi.spyOn(api, 'diagnosePrinter').mockResolvedValue(PROBLEM_RESULT);
  44. renderModal({ printerId: 1, printerName: 'Test P1S', onClose: vi.fn() });
  45. await waitFor(() => expect(spy).toHaveBeenCalledTimes(1));
  46. expect(spy).toHaveBeenCalledWith(1);
  47. // Each check's localized title renders.
  48. expect(await screen.findByText(/Control port \(MQTT 8883\)/i)).toBeInTheDocument();
  49. expect(screen.getByText(/LAN Developer Mode/i)).toBeInTheDocument();
  50. // The failing developer_mode check shows its fix text.
  51. expect(screen.getByText(/Developer Mode is OFF/i)).toBeInTheDocument();
  52. // Overall banner reflects "problems".
  53. expect(
  54. screen.getByText(/Found problems that explain why the printer/i),
  55. ).toBeInTheDocument();
  56. spy.mockRestore();
  57. });
  58. it('uses the pre-add API when given a connection instead of a printerId', async () => {
  59. const spy = vi.spyOn(api, 'diagnoseConnection').mockResolvedValue({
  60. ...PROBLEM_RESULT,
  61. printer_id: null,
  62. });
  63. renderModal({
  64. connection: { ip_address: '192.168.1.99', serial_number: '01P', access_code: 'abc' },
  65. onClose: vi.fn(),
  66. });
  67. await waitFor(() => expect(spy).toHaveBeenCalledTimes(1));
  68. expect(spy).toHaveBeenCalledWith({
  69. ip_address: '192.168.1.99',
  70. serial_number: '01P',
  71. access_code: 'abc',
  72. });
  73. spy.mockRestore();
  74. });
  75. it('re-runs the diagnostic when the user clicks Run again', async () => {
  76. const spy = vi.spyOn(api, 'diagnosePrinter').mockResolvedValue(PROBLEM_RESULT);
  77. renderModal({ printerId: 1, printerName: 'Test P1S', onClose: vi.fn() });
  78. await waitFor(() => expect(spy).toHaveBeenCalledTimes(1));
  79. fireEvent.click(screen.getByText(/Run again/i));
  80. await waitFor(() => expect(spy).toHaveBeenCalledTimes(2));
  81. spy.mockRestore();
  82. });
  83. });