← back to NationalPaperHangers

tests/measure-kit.test.js

104 lines

'use strict';
// Unit tests for the AR Measurement Kit roll/panel calculator (/measure).
// Pure arithmetic — no server, no DOM. Run: node --test tests/measure-kit.test.js
const test = require('node:test');
const assert = require('node:assert/strict');
const MK = require('../public/js/measure-kit');

test('wallArea: gross with no deductions', () => {
  const a = MK.wallArea({ width_ft: 10, height_ft: 8 });
  assert.equal(a.gross, 80);
  assert.equal(a.deduct, 0);
  assert.equal(a.net, 80);
});

test('wallArea: subtracts a door + window', () => {
  const a = MK.wallArea({
    width_ft: 12, height_ft: 9,
    deductions: [{ w_ft: 3, h_ft: 7 }, { w_ft: 4, h_ft: 3 }]
  });
  assert.equal(a.gross, 108);
  assert.equal(a.deduct, 33); // 21 + 12
  assert.equal(a.net, 75);
});

test('wallArea: clamps garbage/negative input to 0', () => {
  const a = MK.wallArea({ width_ft: -5, height_ft: 'x' });
  assert.equal(a.gross, 0);
  assert.equal(a.net, 0);
});

test('totalArea: sums multiple walls net', () => {
  const total = MK.totalArea([
    { width_ft: 10, height_ft: 8 },               // 80
    { width_ft: 12, height_ft: 8, deductions: [{ w_ft: 3, h_ft: 7 }] } // 96-21=75
  ]);
  assert.equal(total, 155);
});

test('defaultWaste: 15% plain, 20% with a repeat', () => {
  assert.equal(MK.defaultWaste(0), 0.15);
  assert.equal(MK.defaultWaste(18), 0.20);
});

test('rollsForArea: US standard sells double rolls', () => {
  // 155 ft² × 1.15 = 178.25 → /28 = 6.36 → 7 singles → 4 doubles
  const r = MK.rollsForArea(155, { formatId: 'us_standard', repeatIn: 0 });
  assert.equal(r.wastePct, 15);
  assert.equal(r.singleRolls, 7);
  assert.equal(r.doubleRolls, 4);
  assert.equal(r.soldInDoubles, true);
});

test('rollsForArea: repeat bumps default waste to 20%', () => {
  // 155 × 1.20 = 186 → /28 = 6.64 → 7 singles
  const r = MK.rollsForArea(155, { formatId: 'us_standard', repeatIn: 21 });
  assert.equal(r.wastePct, 20);
  assert.equal(r.singleRolls, 7);
});

test('rollsForArea: explicit waste override wins over repeat default', () => {
  const r = MK.rollsForArea(100, { formatId: 'us_standard', repeatIn: 21, waste: 0.10 });
  assert.equal(r.wastePct, 10);
});

test('rollsForArea: euro roll is sold single (no doubles)', () => {
  // 155 × 1.15 = 178.25 → /57 = 3.13 → 4 singles
  const r = MK.rollsForArea(155, { formatId: 'euro', repeatIn: 0 });
  assert.equal(r.singleRolls, 4);
  assert.equal(r.soldInDoubles, false);
  assert.equal(r.doubleRolls, undefined);
});

test('rollsForArea: zero area → zero rolls', () => {
  const r = MK.rollsForArea(0, { formatId: 'us_standard' });
  assert.equal(r.singleRolls, 0);
  assert.equal(r.doubleRolls, 0);
});

test('panelsForWalls: panels per wall by width, default 36"', () => {
  // wall 1: 10 ft / 3 ft = 3.33 → 4 panels; wall 2: 6 ft / 3 = 2 panels
  const p = MK.panelsForWalls([
    { width_ft: 10, height_ft: 9 },
    { width_ft: 6, height_ft: 9 }
  ]);
  assert.equal(p.panelWidthIn, 36);
  assert.equal(p.perWall[0].panels, 4);
  assert.equal(p.perWall[1].panels, 2);
  assert.equal(p.totalPanels, 6);
});

test('panelsForWalls: flags walls taller than panel max height', () => {
  const p = MK.panelsForWalls([{ width_ft: 8, height_ft: 12 }], { panelMaxHeightFt: 10 });
  assert.equal(p.perWall[0].tooTall, true);
});

test('buyLine: double-roll phrasing', () => {
  const r = MK.rollsForArea(155, { formatId: 'us_standard', repeatIn: 0 });
  assert.match(MK.buyLine(r), /Buy 4 double rolls \(7 single-roll equivalent\)/);
});

test('buyLine: empty result prompts to measure', () => {
  assert.match(MK.buyLine(MK.rollsForArea(0, {})), /Add a wall measurement/);
});