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>
54 lines
2.9 KiB
JavaScript
54 lines
2.9 KiB
JavaScript
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), []);
|
||
});
|