AddSmartPlugModalSecrets.test.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /**
  2. * A saved plug's password and REST headers come back as a placeholder. The
  3. * dialog keeps it, tests a saved plug by its id so the backend fills it in,
  4. * and asks for it again when the plug's address changes.
  5. */
  6. import { describe, it, expect, afterEach } from 'vitest';
  7. import { screen, waitFor } from '@testing-library/react';
  8. import userEvent from '@testing-library/user-event';
  9. import { http, HttpResponse } from 'msw';
  10. import { render } from '../utils';
  11. import { server } from '../mocks/server';
  12. import { AddSmartPlugModal } from '../../components/AddSmartPlugModal';
  13. import type { SmartPlug } from '../../api/client';
  14. const M = '********';
  15. afterEach(() => server.resetHandlers());
  16. function plug(overrides: Partial<SmartPlug>): SmartPlug {
  17. return {
  18. id: 5,
  19. name: 'Plug',
  20. plug_type: 'tasmota',
  21. ip_address: '10.0.0.5',
  22. username: 'admin',
  23. password: M,
  24. enabled: true,
  25. printer_id: null,
  26. ...overrides,
  27. } as unknown as SmartPlug;
  28. }
  29. describe('AddSmartPlugModal saved secrets', () => {
  30. it('tests a saved Tasmota plug by its id', async () => {
  31. let body: Record<string, unknown> | null = null;
  32. server.use(
  33. http.post('*/api/v1/smart-plugs/test-connection', async ({ request }) => {
  34. body = (await request.json()) as Record<string, unknown>;
  35. return HttpResponse.json({ success: true, state: 'ON', device_name: 'x' });
  36. }),
  37. );
  38. const user = userEvent.setup();
  39. render(<AddSmartPlugModal plug={plug({})} onClose={() => undefined} />);
  40. await user.click(await screen.findByRole('button', { name: /^test$/i }));
  41. await waitFor(() => expect(body).not.toBeNull());
  42. expect(body).toMatchObject({ ip_address: '10.0.0.5', password: M, plug_id: 5 });
  43. });
  44. it('says the saved password is kept, and asks for it again for a new address', async () => {
  45. const user = userEvent.setup();
  46. render(<AddSmartPlugModal plug={plug({})} onClose={() => undefined} />);
  47. expect(await screen.findByText(/leave it as is to keep it/i)).toBeInTheDocument();
  48. const ip = screen.getByDisplayValue('10.0.0.5');
  49. await user.clear(ip);
  50. await user.type(ip, '10.0.0.66');
  51. expect(screen.getByText(/the address changed: enter it again/i)).toBeInTheDocument();
  52. });
  53. it('tests a saved REST plug by its id, and asks for the headers again for a new URL', async () => {
  54. let body: Record<string, unknown> | null = null;
  55. server.use(
  56. http.post('*/api/v1/smart-plugs/rest/test-connection', async ({ request }) => {
  57. body = (await request.json()) as Record<string, unknown>;
  58. return HttpResponse.json({ success: true, error: null });
  59. }),
  60. );
  61. const user = userEvent.setup();
  62. const rest = plug({
  63. plug_type: 'rest',
  64. ip_address: null,
  65. password: null,
  66. rest_on_url: 'http://plug.example/on',
  67. rest_off_url: 'http://plug.example/off',
  68. rest_headers: M,
  69. } as Partial<SmartPlug>);
  70. render(<AddSmartPlugModal plug={rest} onClose={() => undefined} />);
  71. await user.click(await screen.findByRole('button', { name: /test connection/i }));
  72. await waitFor(() => expect(body).not.toBeNull());
  73. expect(body).toMatchObject({ url: 'http://plug.example/on', headers: M, plug_id: 5 });
  74. const on = screen.getByDisplayValue('http://plug.example/on');
  75. await user.clear(on);
  76. await user.type(on, 'http://elsewhere.example/on');
  77. expect(screen.getByText(/the address changed: enter it again/i)).toBeInTheDocument();
  78. });
  79. });