fix(labels): replace incorrect ams_30x15 preset with correct AMS holder sizes (#1426)

Reporter — the same person who originally requested the labels
  feature in #809 — discovered that the ams_30x15 preset's 30x15 mm
  dimension didn't actually fit any variant of the MakerWorld AMS
  Filament Label Holder (model 752566) it advertised. Two new
  presets replace it:

  - ams_holder_74x33 (74 x 33 mm) matches the printable label STL
    bundled in the MakerWorld project
  - ams_holder_75x55 (75 x 55 mm) fits the cardstock-insert variant
    the reporter validated on bench

  Both cross the 20 mm height threshold so they land in the roomy
  layout branch — swatch on the left, QR on the right, multi-line
  text (brand, material, hex code, spool ID) in the middle. The
  old 30x15 mm preset couldn't fit a QR code; the new ones do.

  No DB migration: the preset name was never persisted. Callers
  scripting the old ams_30x15 value get a clean 422 at the route's
  Literal validator with the new valid values listed.

  i18n: replaced inventory.labels.templates.ams.{label,hint} with
  amsHolderSmall and amsHolderLarge across all 8 locales with real
  translations; parity guard cleaned of the stale English-fallback
  cognate entries. Parity holds at 4856 leaves per locale.

  Tests: backend label renderer + integration tests cover both new
  presets; LabelTemplatePickerModal test updated for the 6-button
  grid and the new template value in the API-call assertion.
This commit is contained in:
maziggy
2026-05-19 13:14:03 +02:00
parent 0b33862ae9
commit 1677efb2c6
19 changed files with 175 additions and 82 deletions
@@ -176,7 +176,13 @@ describe('LabelTemplatePickerModal', () => {
spoolmanMode={false}
/>,
);
expect(screen.getByText(/AMS holder/i).closest('button')).toBeDisabled();
// Two AMS holder variants exist (#1426). Both must be disabled when no
// spools are selected — the empty-selection guard is global, not per-template.
const amsButtons = screen.getAllByText(/AMS holder/i).map((el) => el.closest('button'));
expect(amsButtons).toHaveLength(2);
for (const btn of amsButtons) {
expect(btn).toBeDisabled();
}
});
it('sends only the currently checked IDs to the local endpoint', async () => {
@@ -218,12 +224,14 @@ describe('LabelTemplatePickerModal', () => {
/>,
);
fireEvent.click(screen.getByText(/AMS holder/i));
// Pick the larger AMS holder variant explicitly (#1426: two AMS templates
// exist now — pin which one the test sends so the assertion stays meaningful).
fireEvent.click(screen.getByText(/AMS holder — large \(75 × 55 mm\)/i));
await waitFor(() => {
expect(api.printSpoolmanSpoolLabels).toHaveBeenCalledWith({
spool_ids: [1],
template: 'ams_30x15',
template: 'ams_holder_75x55',
});
});
expect(api.printSpoolLabels).not.toHaveBeenCalled();
@@ -296,9 +304,10 @@ describe('LabelTemplatePickerModal', () => {
/>,
);
// All five templates must be in the DOM. Use the dimension suffix to
// disambiguate the two "Box label …" entries.
expect(screen.getByText(/AMS holder/i)).toBeInTheDocument();
// All six templates must be in the DOM (#1426 added two AMS variants).
// Use the dimension suffix to disambiguate same-family entries.
expect(screen.getByText(/AMS holder — small \(74 × 33 mm\)/i)).toBeInTheDocument();
expect(screen.getByText(/AMS holder — large \(75 × 55 mm\)/i)).toBeInTheDocument();
expect(screen.getByText(/Box label \(40 × 30 mm\)/i)).toBeInTheDocument();
expect(screen.getByText(/Box label \(62 × 29 mm\)/i)).toBeInTheDocument();
expect(screen.getByText(/Avery L7160/i)).toBeInTheDocument();
@@ -311,7 +320,7 @@ describe('LabelTemplatePickerModal', () => {
const templatesSection = container.querySelector('div.grid.sm\\:grid-cols-2');
expect(templatesSection).not.toBeNull();
expect(templatesSection!.className).toContain('grid-cols-1');
expect(templatesSection!.querySelectorAll('button').length).toBe(5);
expect(templatesSection!.querySelectorAll('button').length).toBe(6);
// Spool list still uses min-h-0 so it can yield further on very tight viewports.
const spoolListScroller = container.querySelector('div.flex-1.overflow-y-auto');