/**
* Bulk edit: the field list must only offer fields the active inventory
* backend can actually store (#2870).
*
* In Spoolman mode a spool has no material number, category or low-stock
* override of its own — SpoolmanInventoryUpdate has no such fields, so the
* payload dumps to {} and the route answers 400 "update must include at
* least one field". The user ticks a box, types a value, clicks Apply and
* gets an error. Filtering the list is the fix.
*/
import React from 'react';
import { describe, it, expect, vi } from 'vitest';
import { screen } from '@testing-library/react';
import { render } from '../utils';
import { BulkEditSpoolsModal } from '../../components/BulkEditSpoolsModal';
vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => key,
}),
}));
const baseProps = {
isOpen: true,
selectedCount: 3,
isPending: false,
availableLocations: [],
availableMaterials: [],
availableSubtypes: [],
availableBrands: [],
availableCategories: [],
availableMaterialNumbers: [],
availableSlicerFilaments: [],
availableSlicerFilamentNames: [],
onClose: vi.fn(),
onApply: vi.fn(),
};
const INTERNAL_ONLY = [
'inventory.materialNumber',
'inventory.category',
'inventory.lowStockThresholdOverride',
];
describe('BulkEditSpoolsModal field list', () => {
it('offers the internal-only fields in internal mode', () => {
render();
for (const key of INTERNAL_ONLY) {
expect(screen.getByText(key)).toBeTruthy();
}
});
it('hides every field Spoolman cannot store in Spoolman mode', () => {
render();
for (const key of INTERNAL_ONLY) {
expect(screen.queryByText(key)).toBeNull();
}
// The fields Spoolman does accept stay.
expect(screen.getByText('inventory.material')).toBeTruthy();
expect(screen.getByText('inventory.note')).toBeTruthy();
expect(screen.getByText('inventory.costPerKg')).toBeTruthy();
});
it('defaults to internal mode when the prop is omitted', () => {
render();
expect(screen.getByText('inventory.materialNumber')).toBeTruthy();
});
});