printhive/test/filaments.test.js
dlawler489 8814e79669 Count slots, not materials: four colours need four spools
Reported from the library: a four-colour AMS bookmark showed as "printable now"
against a single spool of Jade White. The matching collapsed the project's four
slots into the set of materials it used — {PLA} — and then asked only whether a
PLA spool existed. A sixteen-colour model would have passed the same way.

Ignoring colour is right: printing a bookmark in red instead of white still
prints. Ignoring slot count is not: four slots need four spools loaded. Matching
now counts slots per material and reports the shortfall — "needs 3 more PLA",
and on the model page "Needs 4 × PLA. You have 1 of 4 PLA."

The tests carried the same mistake, asserting that one spool satisfied a
multi-slot project, so they are rewritten around the reported case.

Also documents the feature in the README, which had no entry for it at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:41:40 +10:00

54 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const test = require('node:test');
const assert = require('node:assert/strict');
const filaments = require('../lib/filaments');
const spools = (...materials) => materials.map((m, i) => ({ id: i + 1, material: m, remaining_g: 500 }));
test('one spool per slot: a four-colour print needs four spools', () => {
// The case that caught this out: an AMS bookmark in four PLA colours, and one
// spool of white on the shelf. Owning "PLA" is not enough.
const fourColour = [
{ type: 'PLA', colour: '#000000' }, { type: 'PLA', colour: '#586579' },
{ type: 'PLA', colour: '#8E9089' }, { type: 'PLA', colour: '#FFFFFF' },
];
assert.equal(filaments.isPrintable(fourColour, spools('PLA')), false);
assert.deepEqual(filaments.shortfall(fourColour, spools('PLA')), [{ material: 'PLA', need: 4, have: 1 }]);
assert.equal(filaments.isPrintable(fourColour, spools('PLA', 'PLA', 'PLA', 'PLA')), true);
assert.deepEqual(filaments.shortfall(fourColour, spools('PLA', 'PLA', 'PLA', 'PLA')), []);
});
test('a single-filament model prints from a single spool', () => {
assert.equal(filaments.isPrintable([{ type: 'PLA', colour: '#FFF' }], spools('PLA')), true);
});
test('slots are counted per material', () => {
const mixed = [{ type: 'PLA' }, { type: 'PLA' }, { type: 'PETG' }];
assert.deepEqual(filaments.slotsNeeded(mixed), [{ material: 'PLA', count: 2 }, { material: 'PETG', count: 1 }]);
assert.deepEqual(filaments.shortfall(mixed, spools('PLA', 'PETG')), [{ material: 'PLA', need: 2, have: 1 }]);
assert.equal(filaments.isPrintable(mixed, spools('PLA', 'PLA', 'PETG')), true);
});
test('colour is ignored — a different colour still prints', () => {
const project = [{ type: 'PLA', colour: '#FF0000' }];
assert.equal(filaments.isPrintable(project, [{ material: 'PLA', colour_hex: '#0000FF', remaining_g: 200 }]), true);
});
test('case and spacing don’t matter, but a different material does', () => {
assert.equal(filaments.normalise(' pla basic '), 'PLA BASIC');
// PLA-CF is carbon filled: a plain PLA spool is not a substitute.
assert.deepEqual(filaments.shortfall([{ type: 'PLA-CF' }], spools('PLA')), [{ material: 'PLA-CF', need: 1, have: 0 }]);
assert.deepEqual(filaments.shortfall([{ type: 'pla' }], spools('PLA')), []);
});
test('an empty spool doesn’t count, but an unweighed one does', () => {
const project = [{ type: 'PLA' }];
assert.deepEqual(filaments.shortfall(project, [{ material: 'PLA', remaining_g: 0 }]), [{ material: 'PLA', need: 1, have: 0 }]);
assert.deepEqual(filaments.shortfall(project, [{ material: 'PLA', remaining_g: null }]), []);
assert.deepEqual(filaments.shortfall(project, [{ material: 'PLA' }]), []);
});
test('a model we know nothing about is not claimed to be printable', () => {
assert.equal(filaments.isPrintable(null, spools('PLA')), false);
assert.equal(filaments.isPrintable([], spools('PLA')), false);
assert.deepEqual(filaments.slotsNeeded(null), []);
});