feat: Unify print dispatch through the scheduler (#1625)

This commit is contained in:
Ed
2026-06-26 12:31:48 +02:00
committed by GitHub
parent 0b43ac0d25
commit 4c67d8a4e1
63 changed files with 1704 additions and 5049 deletions
@@ -1,6 +1,5 @@
/**
* Test that reprint mode does not show the "Print queued for printer" toast.
* The background dispatch websocket toast handles feedback instead.
* Test that create mode now goes through the queue-backed create path.
*
* Separate file because vi.mock(ToastContext) must be module-scoped
* and would interfere with the main PrintModal test suite.
@@ -48,17 +47,17 @@ describe('PrintModal dispatch toast', () => {
http.get('/api/v1/printers/:id/status', () => {
return HttpResponse.json({ connected: true, state: 'IDLE', ams: [], vt_tray: [] });
}),
http.post('/api/v1/archives/:id/reprint', () => {
return HttpResponse.json({ status: 'dispatched', dispatch_job_id: 1 });
http.post('/api/v1/queue/', () => {
return HttpResponse.json({ id: 1, status: 'pending' });
}),
);
});
it('does not show "queued" toast in reprint mode (dispatch toast handles it)', async () => {
it('shows queued toast in create mode', async () => {
const user = userEvent.setup();
render(
<PrintModal
mode="reprint"
mode="create"
archiveId={1}
archiveName="Benchy"
onClose={mockOnClose}
@@ -81,8 +80,116 @@ describe('PrintModal dispatch toast', () => {
expect(mockOnClose).toHaveBeenCalled();
});
// showToast should NOT have been called with "Print queued for printer"
const toastMessages = mockShowToast.mock.calls.map(call => call[0]);
expect(toastMessages).not.toContain('Print queued for printer');
expect(toastMessages).toContain('Print queued');
});
it('uses wait-for-idle copy when an ASAP target is offline', async () => {
server.use(
http.get('/api/v1/printers/:id/status', () => {
return HttpResponse.json({ connected: false, state: null, ams: [], vt_tray: [] });
}),
);
const user = userEvent.setup();
render(
<PrintModal
mode="create"
archiveId={1}
archiveName="Benchy"
initialSelectedPrinterIds={[1]}
onClose={mockOnClose}
onSuccess={mockOnSuccess}
/>
);
await waitFor(() => {
expect(screen.getByRole('button', { name: /^print$/i })).toBeInTheDocument();
});
await user.click(screen.getByRole('button', { name: /^print$/i }));
await waitFor(() => {
expect(mockOnClose).toHaveBeenCalled();
});
const toastMessages = mockShowToast.mock.calls.map(call => call[0]);
expect(toastMessages).toContain('Will start when printer is idle');
expect(toastMessages).not.toContain('Print queued');
});
it('uses wait-for-idle copy when an ASAP target is held for plate clear', async () => {
server.use(
http.get('/api/v1/printers/:id/status', () => {
return HttpResponse.json({
connected: true,
state: 'FINISH',
awaiting_plate_clear: true,
ams: [],
vt_tray: [],
});
}),
);
const user = userEvent.setup();
render(
<PrintModal
mode="create"
archiveId={1}
archiveName="Benchy"
initialSelectedPrinterIds={[1]}
onClose={mockOnClose}
onSuccess={mockOnSuccess}
/>
);
await waitFor(() => {
expect(screen.getByRole('button', { name: /^print$/i })).toBeInTheDocument();
});
await user.click(screen.getByRole('button', { name: /^print$/i }));
await waitFor(() => {
expect(mockOnClose).toHaveBeenCalled();
});
const toastMessages = mockShowToast.mock.calls.map(call => call[0]);
expect(toastMessages).toContain('Will start when printer is idle');
});
it('uses wait-for-idle copy when an ASAP target is drying filament', async () => {
server.use(
http.get('/api/v1/printers/:id/status', () => {
return HttpResponse.json({
connected: true,
state: 'IDLE',
awaiting_plate_clear: false,
ams: [{ id: 0, dry_time: 25, tray: [] }],
vt_tray: [],
});
}),
);
const user = userEvent.setup();
render(
<PrintModal
mode="create"
archiveId={1}
archiveName="Benchy"
initialSelectedPrinterIds={[1]}
onClose={mockOnClose}
onSuccess={mockOnSuccess}
/>
);
await waitFor(() => {
expect(screen.getByRole('button', { name: /^print$/i })).toBeInTheDocument();
});
await user.click(screen.getByRole('button', { name: /^print$/i }));
await waitFor(() => {
expect(mockOnClose).toHaveBeenCalled();
});
const toastMessages = mockShowToast.mock.calls.map(call => call[0]);
expect(toastMessages).toContain('Will start when printer is idle');
});
});