/** * Tests for K-profile matching helpers (#1688 + #1689). * * `isMatchingCalibration` is the predicate used by both the spool form's * PA-profile suggester and ConfigureAmsSlotModal's K-profile filter. The * #1688 enhancement adds a filament_id-first match path with id * normalisation; the old name-parsing logic stays as the fallback. */ import { describe, it, expect } from 'vitest'; import { isMatchingCalibration, toFilamentId, isGenericFilamentId, materialForGenericFilamentId, genericFilamentIdMatchesMaterial, } from '../../../components/spool-form/utils'; describe('toFilamentId', () => { it('strips the variant suffix', () => { expect(toFilamentId('GFG98_09')).toBe('GFG98'); }); it('strips the "S" infix from a setting_id', () => { // Spool stores setting_id "GFSG98", K-profile stores filament_id "GFG98". // Normalisation has to drop the "S" so both sides agree. expect(toFilamentId('GFSG98')).toBe('GFG98'); }); it('strips both the "S" infix and the variant suffix', () => { expect(toFilamentId('GFSG98_09')).toBe('GFG98'); }); it('returns bare filament_id unchanged', () => { expect(toFilamentId('GFL05')).toBe('GFL05'); }); it('uppercases the result', () => { expect(toFilamentId('gfsg98_09')).toBe('GFG98'); }); it('returns empty string for null/undefined/empty', () => { expect(toFilamentId(null)).toBe(''); expect(toFilamentId(undefined)).toBe(''); expect(toFilamentId('')).toBe(''); }); it('passes through non-Bambu IDs (numeric local-preset, Orca UUID) without crashing', () => { // Numeric local-preset ID — caller falls through to name match, no crash. expect(toFilamentId('42')).toBe('42'); // Orca UUID — same. expect(toFilamentId('orca-uuid-abc')).toBe('ORCA-UUID-ABC'); }); }); describe('isGenericFilamentId', () => { it('flags GFx99 patterns as generic', () => { expect(isGenericFilamentId('GFL99')).toBe(true); expect(isGenericFilamentId('GFG99')).toBe(true); expect(isGenericFilamentId('GFB99')).toBe(true); }); it('does not flag non-generic IDs', () => { expect(isGenericFilamentId('GFL05')).toBe(false); expect(isGenericFilamentId('GFG98')).toBe(false); }); it('returns false for null/undefined/empty', () => { expect(isGenericFilamentId(null)).toBe(false); expect(isGenericFilamentId(undefined)).toBe(false); expect(isGenericFilamentId('')).toBe(false); }); }); describe('materialForGenericFilamentId (#2710)', () => { it('resolves the material each generic id stands for', () => { expect(materialForGenericFilamentId('GFL99')).toBe('PLA'); expect(materialForGenericFilamentId('GFG99')).toBe('PETG'); expect(materialForGenericFilamentId('gfu99')).toBe('TPU'); }); it('returns empty for specific ids and for nothing', () => { expect(materialForGenericFilamentId('GFL05')).toBe(''); expect(materialForGenericFilamentId(null)).toBe(''); expect(materialForGenericFilamentId('')).toBe(''); }); }); describe('genericFilamentIdMatchesMaterial (#2710)', () => { it('agrees when the generic id describes that material', () => { expect(genericFilamentIdMatchesMaterial('GFL99', 'PLA')).toBe(true); expect(genericFilamentIdMatchesMaterial('GFL99', 'pla')).toBe(true); }); it('treats Nylon and PA as the same material', () => { expect(genericFilamentIdMatchesMaterial('GFN99', 'Nylon')).toBe(true); }); it('rejects a mismatched material, a specific id, or a missing material', () => { expect(genericFilamentIdMatchesMaterial('GFL99', 'PETG')).toBe(false); expect(genericFilamentIdMatchesMaterial('GFL05', 'PLA')).toBe(false); expect(genericFilamentIdMatchesMaterial('GFL99', '')).toBe(false); }); }); describe('isMatchingCalibration (#1688)', () => { const formData = { material: 'PETG', brand: 'Generic', subtype: '', slicer_filament: 'GFSG98_09', // spool's setting_id form }; it('matches by filament_id when ids agree after normalisation', () => { // K-profile stores bare filament_id; spool stores setting_id. Both // normalise to "GFG98" — match without any name parsing. expect( isMatchingCalibration( { name: 'My Custom K Profile', filament_id: 'GFG98' }, formData, ), ).toBe(true); }); it('id-match wins even when the K-profile name would not parse to anything sensible', () => { expect( isMatchingCalibration( { name: 'literal-garbage-no-material', filament_id: 'GFG98' }, formData, ), ).toBe(true); }); it('skips id-match when a generic id contradicts the spool material', () => { // GFL99 is generic *PLA* but the spool says PETG — the ids agreeing is not // enough, the material has to agree too. Name parsing then drives the // decision and rejects it. const result = isMatchingCalibration( { name: 'Random thing with no PETG in it', filament_id: 'GFL99' }, { ...formData, slicer_filament: 'GFL99' }, ); expect(result).toBe(false); }); it('matches a generic id when the material agrees and the spool claims no brand (#2710)', () => { // Reporter's printer: every K-profile calibrated under Generic PLA and // named after the colour. No name parsing can tie "Dark Brown" to PLA, so // the shared GFL99 is the only signal there is. expect( isMatchingCalibration( { name: 'Dark Brown', filament_id: 'GFL99' }, { material: 'PLA', brand: '', subtype: '', slicer_filament: 'GFL99' }, ), ).toBe(true); }); it('treats "Generic" as no brand on the generic id path', () => { expect( isMatchingCalibration( { name: 'Marble', filament_id: 'GFL99' }, { material: 'PLA', brand: 'Generic', subtype: '', slicer_filament: 'GFL99' }, ), ).toBe(true); }); it('keeps generic id matches brand-specific when the spool names a brand', () => { // A spool that says "Sunlu" should still get Sunlu-specific suggestions // rather than the printer's whole generic-PLA table. expect( isMatchingCalibration( { name: 'Dark Brown', filament_id: 'GFL99' }, { material: 'PLA', brand: 'Sunlu', subtype: '', slicer_filament: 'GFL99' }, ), ).toBe(false); }); it('accepts Nylon/PA as the same material on the generic id path', () => { expect( isMatchingCalibration( { name: 'spool-of-doom', filament_id: 'GFN99' }, { material: 'Nylon', brand: '', subtype: '', slicer_filament: 'GFN99' }, ), ).toBe(true); }); it('falls through to name match when spool has no slicer_filament', () => { expect( isMatchingCalibration( { name: 'Generic PETG', filament_id: 'GFG98' }, { material: 'PETG', brand: 'Generic', subtype: '' }, ), ).toBe(true); }); it('falls through to name match when K-profile has no filament_id', () => { expect( isMatchingCalibration( { name: 'Generic PETG' }, formData, ), ).toBe(true); }); it('falls through to name match when normalised ids differ', () => { // Spool says GFG98, K-profile says GFL05 — id-match fails, fall to name. expect( isMatchingCalibration( { name: 'Generic PETG', filament_id: 'GFL05' }, formData, ), ).toBe(true); expect( isMatchingCalibration( { name: 'Bambu PLA Basic', filament_id: 'GFL05' }, formData, ), ).toBe(false); }); it('rejects calibrations whose material does not match (name fallback path)', () => { expect( isMatchingCalibration( { name: 'Bambu PLA Basic', filament_id: 'GFL05' }, { material: 'PETG', brand: '', subtype: '' }, ), ).toBe(false); }); it('returns false when formData has no material', () => { expect( isMatchingCalibration( { name: 'PETG', filament_id: 'GFG98' }, { material: '', brand: '', subtype: '' }, ), ).toBe(false); }); });