import { describe, it, expect } from 'vitest'; import { validateForm, defaultFormData } from '../../components/spool-form/types'; describe('validateForm', () => { describe('standard mode', () => { it('requires slicer_filament, material, brand, and subtype', () => { const result = validateForm(defaultFormData); expect(result.isValid).toBe(false); expect(result.errors.slicer_filament).toBeDefined(); expect(result.errors.material).toBeDefined(); expect(result.errors.brand).toBeDefined(); expect(result.errors.subtype).toBeDefined(); }); it('passes when all required fields are filled', () => { const data = { ...defaultFormData, slicer_filament: 'Bambu PLA Basic @BBL', material: 'PLA', brand: 'Bambu Lab', subtype: 'Basic', }; const result = validateForm(data); expect(result.isValid).toBe(true); expect(Object.keys(result.errors)).toHaveLength(0); }); }); describe('quickAdd mode', () => { it('only requires material', () => { const result = validateForm(defaultFormData, true); expect(result.isValid).toBe(false); expect(result.errors.material).toBeDefined(); expect(result.errors.slicer_filament).toBeUndefined(); expect(result.errors.brand).toBeUndefined(); }); it('passes with only material set', () => { const data = { ...defaultFormData, material: 'PETG' }; const result = validateForm(data, true); expect(result.isValid).toBe(true); }); }); describe('spoolmanMode', () => { it('only requires material (same as quickAdd)', () => { const result = validateForm(defaultFormData, false, true); expect(result.isValid).toBe(false); expect(result.errors.material).toBeDefined(); expect(result.errors.slicer_filament).toBeUndefined(); expect(result.errors.brand).toBeUndefined(); expect(result.errors.subtype).toBeUndefined(); }); it('passes with only material set', () => { const data = { ...defaultFormData, material: 'PLA' }; const result = validateForm(data, false, true); expect(result.isValid).toBe(true); expect(Object.keys(result.errors)).toHaveLength(0); }); it('does not require slicer_filament even when present', () => { const data = { ...defaultFormData, material: 'ABS' }; const result = validateForm(data, false, true); expect(result.isValid).toBe(true); }); it('fails when material is empty string', () => { const data = { ...defaultFormData, material: '' }; const result = validateForm(data, false, true); expect(result.isValid).toBe(false); expect(result.errors.material).toBeDefined(); }); it('quickAdd takes precedence over spoolmanMode', () => { const data = { ...defaultFormData, material: 'PLA' }; const result = validateForm(data, true, true); expect(result.isValid).toBe(true); }); it('passes when spoolman_filament_id is set and material is empty', () => { // When a catalog entry is pre-selected, material is not required const data = { ...defaultFormData, material: '', spoolman_filament_id: 7 }; const result = validateForm(data, false, true); expect(result.isValid).toBe(true); expect(result.errors.material).toBeUndefined(); }); it('fails when both material and spoolman_filament_id are absent', () => { const data = { ...defaultFormData, material: '', spoolman_filament_id: null }; const result = validateForm(data, false, true); expect(result.isValid).toBe(false); expect(result.errors.material).toBeDefined(); }); }); // #1905: a spool created by quick-add / CSV import / RFID scan has no preset, // brand or subtype. Demanding them on every later edit blocked changes to // unrelated fields, and the forced preset pick then rewrote the spool's // manufacturer. Edit and copy now match what the backend requires: material. describe('edit and copy modes', () => { it('only requires material when editing', () => { const result = validateForm(defaultFormData, false, false, 'edit'); expect(result.isValid).toBe(false); expect(result.errors.material).toBeDefined(); expect(result.errors.slicer_filament).toBeUndefined(); expect(result.errors.brand).toBeUndefined(); expect(result.errors.subtype).toBeUndefined(); }); it('passes when editing a spool that only has material', () => { const data = { ...defaultFormData, material: 'ASA' }; const result = validateForm(data, false, false, 'edit'); expect(result.isValid).toBe(true); expect(Object.keys(result.errors)).toHaveLength(0); }); it('passes when copying a spool that only has material', () => { const data = { ...defaultFormData, material: 'ASA' }; const result = validateForm(data, false, false, 'copy'); expect(result.isValid).toBe(true); }); it('still requires the full details in create mode', () => { const data = { ...defaultFormData, material: 'ASA' }; const result = validateForm(data, false, false, 'create'); expect(result.isValid).toBe(false); expect(result.errors.slicer_filament).toBeDefined(); expect(result.errors.brand).toBeDefined(); expect(result.errors.subtype).toBeDefined(); }); it('defaults to create mode when no mode is given', () => { const data = { ...defaultFormData, material: 'ASA' }; expect(validateForm(data).isValid).toBe(false); }); }); });