PrintersPageBucketing.test.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /**
  2. * Regression tests for the printer-status bucketing logic in PrintersPage.tsx.
  3. *
  4. * The bug: a printer in gcode_state="FAILED" with no active HMS errors was
  5. * being counted as a "problem" in the header badge — this is the post-cancel
  6. * terminal state, not a real fault. After cancelling a print on h2d-1 the
  7. * printer card kept showing "1 problem" forever even after the HMS list was
  8. * empty, until the next print started.
  9. *
  10. * The fix: FAILED-without-HMS is bucketed as "finished" (same operator
  11. * meaning: print ended, plate may need clearing). FAILED-with-HMS still
  12. * counts as a problem because there's a real fault to investigate.
  13. *
  14. * Mirrors the classifyPrinterStatus helper in PrintersPage.tsx as an inline
  15. * copy so this test doesn't need it exported. The HMS filter is the real one:
  16. * a copy of it here once kept the old catalogue rule after the rule changed.
  17. */
  18. import { describe, it, expect } from 'vitest';
  19. import { filterKnownHMSErrors } from '../../components/HMSErrorModal';
  20. import type { HMSError } from '../../api/client';
  21. type Status = {
  22. connected: boolean;
  23. state: string | null;
  24. hms_errors?: HMSError[];
  25. };
  26. type Bucket = 'printing' | 'paused' | 'finished' | 'idle' | 'offline' | 'error';
  27. function classifyPrinterStatus(status: Status | undefined): Bucket {
  28. if (!status?.connected) return 'offline';
  29. const knownHms = filterKnownHMSErrors(status.hms_errors ?? []);
  30. if (knownHms.length > 0) return 'error';
  31. switch (status.state) {
  32. case 'RUNNING': return 'printing';
  33. case 'PAUSE': return 'paused';
  34. case 'FINISH': return 'finished';
  35. case 'FAILED': return 'finished';
  36. default: return 'idle';
  37. }
  38. }
  39. describe('FAILED-without-HMS bucketing', () => {
  40. it('classifies FAILED with no HMS errors as "finished" (post-cancel terminal state, not a problem)', () => {
  41. const cancelledPrinter: Status = {
  42. connected: true,
  43. state: 'FAILED',
  44. hms_errors: [],
  45. };
  46. expect(classifyPrinterStatus(cancelledPrinter)).toBe('finished');
  47. });
  48. it('classifies FAILED + active known HMS as "error"', () => {
  49. const reallyFailedPrinter: Status = {
  50. connected: true,
  51. state: 'FAILED',
  52. hms_errors: [{ code: '0x4057', attr: 0x0300_4057, severity: 1, full_code: '03004057', description: 'Z-axis step loss detected.' }],
  53. };
  54. expect(classifyPrinterStatus(reallyFailedPrinter)).toBe('error');
  55. });
  56. it('classifies FAILED + only unknown HMS as "finished" (unknown codes are not "real" problems by our taxonomy)', () => {
  57. const cancelEcho: Status = {
  58. connected: true,
  59. state: 'FAILED',
  60. // The H2S post-cancel echo 0C00-0100-0002-001B: Bambu lists it with no text.
  61. hms_errors: [{ code: '0x2001b', attr: 0x0C00_0100, severity: 2, full_code: '0C0001000002001B', description: null }],
  62. };
  63. expect(classifyPrinterStatus(cancelEcho)).toBe('finished');
  64. });
  65. it('classifies PAUSE + uncataloged HMS WITH actions as "error" (#1840: H2C 0500_809C carries actions but isnt in the bundled catalog)', () => {
  66. const h2cActionableFault: Status = {
  67. connected: true,
  68. state: 'PAUSE',
  69. hms_errors: [{
  70. code: '0x809c',
  71. attr: 0x0500_809C,
  72. severity: 3,
  73. actions: ['IGNORE_RESUME', 'PROBLEM_SOLVED_RESUME'],
  74. }],
  75. };
  76. expect(classifyPrinterStatus(h2cActionableFault)).toBe('error');
  77. });
  78. it('classifies FINISH as "finished" (unchanged baseline)', () => {
  79. const completedPrinter: Status = { connected: true, state: 'FINISH' };
  80. expect(classifyPrinterStatus(completedPrinter)).toBe('finished');
  81. });
  82. it('classifies disconnected printer as "offline" (HMS / state irrelevant)', () => {
  83. const offline: Status = {
  84. connected: false,
  85. state: 'FAILED',
  86. hms_errors: [{ code: '0x4057', attr: 0x0300_4057, severity: 1, full_code: '03004057', description: 'Z-axis step loss detected.' }],
  87. };
  88. expect(classifyPrinterStatus(offline)).toBe('offline');
  89. });
  90. });