| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /**
- * HMSErrorModal wiring: the requests behind "Clear Errors" and the per-fault
- * action buttons (Resume / Retry / Ignore ...).
- *
- * HMSErrorModal.test.tsx covers rendering and the clear button's visibility;
- * this pins what is actually sent and to which printer.
- */
- import { describe, it, expect, vi } from 'vitest';
- import { screen, waitFor } from '@testing-library/react';
- import userEvent from '@testing-library/user-event';
- import { http, HttpResponse } from 'msw';
- import { server } from '../mocks/server';
- import { render } from '../utils';
- import { HMSErrorModal } from '../../components/HMSErrorModal';
- import type { HMSError } from '../../api/client';
- const PRINTER_ID = 42;
- // A 16-char hms[] fault with actions and a job id.
- const actionable: HMSError = {
- attr: 0x07000700,
- code: '0x20009',
- module: 7,
- severity: 2,
- full_code: '0700070000020009',
- description: 'AMS filament ran out.',
- actions: ['IGNORE_RESUME', 'RETRY_PROBLEM_SOLVED'],
- job_id: 'job-777',
- };
- // A print_error-style fault without full_code: the 8-char short code is sent.
- const shortOnly: HMSError = {
- attr: 0x0300,
- code: '0x400C',
- module: 3,
- severity: 1,
- description: 'The task was canceled.',
- actions: ['DBL_CHECK_RETRY'],
- };
- type Captured = { url: string; body: unknown };
- function capture() {
- const clears: string[] = [];
- const actions: Captured[] = [];
- server.use(
- http.post('/api/v1/printers/:id/hms/clear', ({ params }) => {
- clears.push(params.id as string);
- return HttpResponse.json({ success: true, message: 'ok' });
- }),
- http.post('/api/v1/printers/:id/hms/execute-action', async ({ request, params }) => {
- actions.push({ url: params.id as string, body: await request.json() });
- return HttpResponse.json({ success: true, message: 'ok' });
- }),
- );
- return { clears, actions };
- }
- const allow = (granted: boolean) =>
- vi.fn().mockReturnValue(granted) as unknown as (permission: 'printers:control') => boolean;
- function renderModal(errors: HMSError[], granted = true) {
- const onClose = vi.fn();
- const hasPermission = allow(granted);
- render(
- <HMSErrorModal
- printerName="Shop H2D"
- printerId={PRINTER_ID}
- errors={errors}
- onClose={onClose}
- hasPermission={hasPermission}
- />,
- );
- return { onClose, hasPermission };
- }
- describe('HMSErrorModal wiring', () => {
- it('Clear Errors posts hms/clear for this printer only', async () => {
- const user = userEvent.setup();
- const { clears, actions } = capture();
- const { onClose } = renderModal([actionable]);
- await user.click(screen.getByRole('button', { name: 'Clear Errors' }));
- await waitFor(() => expect(clears).toEqual([String(PRINTER_ID)]));
- expect(actions).toEqual([]);
- await waitFor(() => expect(onClose).toHaveBeenCalledTimes(1));
- });
- it('an action button sends the action, the full code and the job id', async () => {
- const user = userEvent.setup();
- const { clears, actions } = capture();
- const { onClose } = renderModal([actionable]);
- await user.click(screen.getByRole('button', { name: 'Ignore this and Resume' }));
- await waitFor(() => expect(actions).toHaveLength(1));
- expect(actions[0]).toEqual({
- url: String(PRINTER_ID),
- body: { action: 'IGNORE_RESUME', print_error: '0700070000020009', job_id: 'job-777' },
- });
- expect(clears).toEqual([]);
- await waitFor(() => expect(onClose).toHaveBeenCalledTimes(1));
- });
- it('falls back to the 8-char short code and a null job id', async () => {
- const user = userEvent.setup();
- const { actions } = capture();
- renderModal([shortOnly]);
- await user.click(screen.getByRole('button', { name: 'Retry' }));
- await waitFor(() => expect(actions).toHaveLength(1));
- expect(actions[0].body).toEqual({ action: 'DBL_CHECK_RETRY', print_error: '0300400C', job_id: null });
- });
- it('sends the action of the fault whose button was clicked', async () => {
- const user = userEvent.setup();
- const { actions } = capture();
- renderModal([actionable]);
- // Two buttons on the same fault: Retry, not Ignore.
- await user.click(screen.getByRole('button', { name: 'Retry (problem solved)' }));
- await waitFor(() => expect(actions).toHaveLength(1));
- expect((actions[0].body as { action: string }).action).toBe('RETRY_PROBLEM_SOLVED');
- });
- it('without printers:control, action and clear buttons are disabled and send nothing', async () => {
- const user = userEvent.setup();
- const { clears, actions } = capture();
- const { hasPermission } = renderModal([actionable], false);
- const ignore = screen.getByRole('button', { name: 'Ignore this and Resume' });
- const clear = screen.getByRole('button', { name: 'Clear Errors' });
- expect(ignore).toBeDisabled();
- expect(clear).toBeDisabled();
- expect(hasPermission).toHaveBeenCalledWith('printers:control');
- await user.click(ignore);
- await user.click(clear);
- // Give any stray request a chance to land.
- await new Promise((r) => setTimeout(r, 20));
- expect(actions).toEqual([]);
- expect(clears).toEqual([]);
- });
- });
|