EditPrinterWearCost.test.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * Wear cost per printing hour in the Edit Printer dialog (#694).
  3. *
  4. * The rate is optional: a number turns it on for the printer, and an empty
  5. * field sends null so the printer stops adding wear to its prints.
  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 basePrinter = {
  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. is_active: true,
  27. wear_cost_per_hour: null as number | null,
  28. created_at: '2024-01-01T00:00:00Z',
  29. updated_at: '2024-01-01T00:00:00Z',
  30. };
  31. const mockStatus = {
  32. connected: true,
  33. state: 'IDLE',
  34. progress: 0,
  35. layer_num: 0,
  36. total_layers: 0,
  37. temperatures: { nozzle: 25, bed: 25, chamber: 25 },
  38. remaining_time: 0,
  39. filename: null,
  40. wifi_signal: -50,
  41. vt_tray: [],
  42. };
  43. let saved: Record<string, unknown> | null = null;
  44. function mockPrinter(printer: typeof basePrinter) {
  45. server.use(
  46. http.get('/api/v1/printers/', () => HttpResponse.json([printer])),
  47. http.get('/api/v1/printers/:id/status', () => HttpResponse.json(mockStatus)),
  48. http.get('/api/v1/queue/', () => HttpResponse.json([])),
  49. http.post('/api/v1/printers/diagnostic', () =>
  50. HttpResponse.json({ printer_id: null, ip_address: printer.ip_address, overall: 'ok', checks: [] }),
  51. ),
  52. http.patch('/api/v1/printers/:id', async ({ request }) => {
  53. saved = (await request.json()) as Record<string, unknown>;
  54. return HttpResponse.json({ ...printer, ...saved });
  55. }),
  56. );
  57. }
  58. async function openEditModal() {
  59. render(<PrintersPage />);
  60. await waitFor(() => expect(screen.getByText('X1 Carbon')).toBeInTheDocument());
  61. const menuBtn = [...document.querySelectorAll('button')].find((b) =>
  62. b.querySelector('.lucide-ellipsis-vertical'),
  63. )!;
  64. await userEvent.click(menuBtn);
  65. await userEvent.click(await screen.findByRole('button', { name: /^edit$/i }));
  66. await screen.findByText('Edit Printer');
  67. }
  68. describe('EditPrinterModal wear cost', () => {
  69. beforeEach(() => {
  70. saved = null;
  71. });
  72. it('saves a rate the user enters', async () => {
  73. mockPrinter(basePrinter);
  74. await openEditModal();
  75. await userEvent.type(screen.getByLabelText(/Wear cost per printing hour/i), '0.35');
  76. await userEvent.click(screen.getByRole('button', { name: /save changes/i }));
  77. await waitFor(() => expect(saved).not.toBeNull());
  78. expect(saved!.wear_cost_per_hour).toBe(0.35);
  79. });
  80. it('turns wear cost off when the field is cleared', async () => {
  81. mockPrinter({ ...basePrinter, wear_cost_per_hour: 0.5 });
  82. await openEditModal();
  83. const field = screen.getByLabelText(/Wear cost per printing hour/i);
  84. expect(field).toHaveValue(0.5);
  85. await userEvent.clear(field);
  86. await userEvent.click(screen.getByRole('button', { name: /save changes/i }));
  87. await waitFor(() => expect(saved).not.toBeNull());
  88. expect(saved!.wear_cost_per_hour).toBeNull();
  89. });
  90. });