SpoolBuddyInventorySearch.test.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /**
  2. * Regression test for #1738 — SpoolBuddy's inventory search must match by
  3. * numeric spool ID, just like Bambuddy's main InventoryPage. Both pages now
  4. * share `filterSpoolsByQuery` so behaviour stays in lockstep; this test fails
  5. * loudly if SpoolBuddyInventoryPage ever re-inlines its filter and drops
  6. * fields.
  7. */
  8. import { describe, it, expect, beforeEach } from 'vitest';
  9. import type { InventorySpool } from '../../api/client';
  10. import { filterSpoolsByQuery } from '../../utils/inventorySearch';
  11. import { setColorCatalog, __resetColorCatalogForTests } from '../../utils/colors';
  12. function makeSpool(overrides: Partial<InventorySpool> & { id: number }): InventorySpool {
  13. return {
  14. material: 'PLA',
  15. subtype: 'Basic',
  16. brand: 'Bambu Lab',
  17. color_name: 'White',
  18. rgba: 'FFFFFFFF',
  19. label_weight: 1000,
  20. core_weight: 250,
  21. core_weight_catalog_id: null,
  22. weight_used: 0,
  23. weight_locked: false,
  24. slicer_filament: null,
  25. slicer_filament_name: null,
  26. nozzle_temp_min: null,
  27. nozzle_temp_max: null,
  28. note: null,
  29. added_full: null,
  30. last_used: null,
  31. encode_time: null,
  32. tag_uid: null,
  33. tray_uuid: null,
  34. data_origin: null,
  35. tag_type: null,
  36. archived_at: null,
  37. created_at: '2025-01-01T00:00:00Z',
  38. updated_at: '2025-01-01T00:00:00Z',
  39. k_profiles: [],
  40. cost_per_kg: null,
  41. last_scale_weight: null,
  42. last_weighed_at: null,
  43. storage_location: null,
  44. ...overrides,
  45. };
  46. }
  47. describe('SpoolBuddyInventoryPage search filter (#1738)', () => {
  48. it('matches an exact spool ID', () => {
  49. const spools = [
  50. makeSpool({ id: 1336 }),
  51. makeSpool({ id: 1337 }),
  52. makeSpool({ id: 42 }),
  53. ];
  54. const result = filterSpoolsByQuery(spools, '1336');
  55. expect(result.map((s) => s.id)).toEqual([1336]);
  56. });
  57. it('matches a partial spool ID', () => {
  58. const spools = [
  59. makeSpool({ id: 100 }),
  60. makeSpool({ id: 200 }),
  61. makeSpool({ id: 1001 }),
  62. ];
  63. const result = filterSpoolsByQuery(spools, '00');
  64. expect(result.map((s) => s.id).sort((a, b) => a - b)).toEqual([100, 200, 1001]);
  65. });
  66. it('still matches by the existing fields SpoolBuddy supported pre-fix', () => {
  67. const spools = [
  68. makeSpool({ id: 1, material: 'PLA', brand: 'Bambu Lab', color_name: 'Red' }),
  69. makeSpool({ id: 2, material: 'PETG', brand: 'Polymaker', color_name: 'Blue' }),
  70. ];
  71. expect(filterSpoolsByQuery(spools, 'polymaker').map((s) => s.id)).toEqual([2]);
  72. expect(filterSpoolsByQuery(spools, 'PLA').map((s) => s.id)).toEqual([1]);
  73. expect(filterSpoolsByQuery(spools, 'red').map((s) => s.id)).toEqual([1]);
  74. });
  75. it('also matches by storage_location and slicer_filament_name (parity gain)', () => {
  76. const spools = [
  77. makeSpool({ id: 1, storage_location: 'IKEA Regal' }),
  78. makeSpool({ id: 2, slicer_filament_name: 'Generic PLA Matte' }),
  79. ];
  80. expect(filterSpoolsByQuery(spools, 'IKEA').map((s) => s.id)).toEqual([1]);
  81. expect(filterSpoolsByQuery(spools, 'Matte').map((s) => s.id)).toEqual([2]);
  82. });
  83. // #3090 — the list shows a name resolved from the swatch's hex whenever the
  84. // spool carries none of its own. Searching only the stored column meant
  85. // typing what was plainly on screen returned nothing.
  86. describe('the name on screen is the name you can search for (#3090)', () => {
  87. beforeEach(() => {
  88. __resetColorCatalogForTests();
  89. setColorCatalog({ d02727: 'Candy Red' });
  90. });
  91. it('matches a catalog name the spool does not store', () => {
  92. const spools = [
  93. makeSpool({ id: 1, color_name: null, rgba: 'D02727FF' }),
  94. makeSpool({ id: 2, color_name: null, rgba: '123456FF' }),
  95. ];
  96. expect(filterSpoolsByQuery(spools, 'candy').map((s) => s.id)).toEqual([1]);
  97. });
  98. it('matches a catalog name over a subtype Spoolman put in its place', () => {
  99. const spools = [
  100. makeSpool({ id: 1, color_name: 'Silk+', color_name_is_synthesized: true, rgba: 'D02727FF' }),
  101. ];
  102. expect(filterSpoolsByQuery(spools, 'candy red').map((s) => s.id)).toEqual([1]);
  103. });
  104. it('still matches the stored value, for anyone who knows the tag codes', () => {
  105. const spools = [makeSpool({ id: 1, color_name: 'A06-D0', rgba: 'D02727FF' })];
  106. expect(filterSpoolsByQuery(spools, 'a06-d0').map((s) => s.id)).toEqual([1]);
  107. });
  108. });
  109. });