EditPrinterPreflight.test.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /**
  2. * Tests for the Edit-Printer setup-time pre-flight.
  3. *
  4. * Editing a printer runs the same connection diagnostic on save as the
  5. * Add-Printer dialog, and warns (rather than blocks) when a check fails.
  6. */
  7. import { describe, it, expect, beforeEach } from 'vitest';
  8. import { screen, waitFor } from '@testing-library/react';
  9. import userEvent from '@testing-library/user-event';
  10. import { render } from '../utils';
  11. import { PrintersPage } from '../../pages/PrintersPage';
  12. import { http, HttpResponse } from 'msw';
  13. import { server } from '../mocks/server';
  14. const mockPrinter = {
  15. id: 1,
  16. name: 'X1 Carbon',
  17. ip_address: '192.168.1.100',
  18. serial_number: '00M09A350100001',
  19. access_code: '12345678',
  20. model: 'X1C',
  21. enabled: true,
  22. nozzle_diameter: 0.4,
  23. nozzle_type: 'hardened_steel',
  24. location: null,
  25. auto_archive: true,
  26. created_at: '2024-01-01T00:00:00Z',
  27. updated_at: '2024-01-01T00:00:00Z',
  28. };
  29. const mockStatus = {
  30. connected: true,
  31. state: 'IDLE',
  32. progress: 0,
  33. layer_num: 0,
  34. total_layers: 0,
  35. temperatures: { nozzle: 25, bed: 25, chamber: 25 },
  36. remaining_time: 0,
  37. filename: null,
  38. wifi_signal: -50,
  39. vt_tray: [],
  40. };
  41. async function openEditModal() {
  42. render(<PrintersPage />);
  43. await waitFor(() => expect(screen.getByText('X1 Carbon')).toBeInTheDocument());
  44. // Open the per-printer actions menu (kebab button), then click Edit.
  45. const menuBtn = [...document.querySelectorAll('button')].find((b) =>
  46. b.querySelector('.lucide-ellipsis-vertical'),
  47. )!;
  48. await userEvent.click(menuBtn);
  49. await userEvent.click(await screen.findByRole('button', { name: /^edit$/i }));
  50. await screen.findByText('Edit Printer');
  51. }
  52. describe('EditPrinterModal pre-flight', () => {
  53. beforeEach(() => {
  54. server.use(
  55. http.get('/api/v1/printers/', () => HttpResponse.json([mockPrinter])),
  56. http.get('/api/v1/printers/:id/status', () => HttpResponse.json(mockStatus)),
  57. http.get('/api/v1/queue/', () => HttpResponse.json([])),
  58. );
  59. });
  60. it('warns instead of saving when a connection check fails', async () => {
  61. server.use(
  62. http.post('/api/v1/printers/diagnostic', () =>
  63. HttpResponse.json({
  64. printer_id: null,
  65. ip_address: '192.168.1.100',
  66. overall: 'problems',
  67. checks: [{ id: 'developer_mode', status: 'fail', params: {} }],
  68. }),
  69. ),
  70. );
  71. await openEditModal();
  72. await userEvent.click(screen.getByRole('button', { name: /save changes/i }));
  73. expect(await screen.findByText(/Some connection checks failed/i)).toBeInTheDocument();
  74. expect(screen.getByRole('button', { name: /save anyway/i })).toBeInTheDocument();
  75. });
  76. it('saves directly when all connection checks pass', async () => {
  77. let updated = false;
  78. server.use(
  79. http.post('/api/v1/printers/diagnostic', () =>
  80. HttpResponse.json({
  81. printer_id: null,
  82. ip_address: '192.168.1.100',
  83. overall: 'ok',
  84. checks: [{ id: 'developer_mode', status: 'pass', params: {} }],
  85. }),
  86. ),
  87. http.patch('/api/v1/printers/:id', async () => {
  88. updated = true;
  89. return HttpResponse.json({ ...mockPrinter, name: 'X1 Carbon' });
  90. }),
  91. );
  92. await openEditModal();
  93. await userEvent.click(screen.getByRole('button', { name: /save changes/i }));
  94. await waitFor(() => expect(updated).toBe(true));
  95. expect(screen.queryByText(/Some connection checks failed/i)).not.toBeInTheDocument();
  96. });
  97. });