Files
svsmspcalc/pre-alpha/tests/test-quote-engine.js
2026-03-16 01:42:17 -04:00

1149 lines
48 KiB
JavaScript

/**
* SVS MSP Calculator — Quote Engine Tests
*
* Run: node svsmspcalc/tests/test-quote-engine.js
*
* Zero dependencies. Uses a minimal test harness built-in.
* Tests the pure calculateQuote(state, pricing) function against
* known-good expected values using default pricing.
*/
// ── Minimal test harness ───────────────────────────────────────
let _passed = 0;
let _failed = 0;
let _group = '';
function describe(name, fn) {
_group = name;
console.log(`\n ${name}`);
fn();
}
function it(name, fn) {
try {
fn();
_passed++;
console.log(` \x1b[32m✓\x1b[0m ${name}`);
} catch (e) {
_failed++;
console.log(` \x1b[31m✗\x1b[0m ${name}`);
console.log(` \x1b[31m${e.message}\x1b[0m`);
}
}
function assert(condition, msg) {
if (!condition) throw new Error(msg || 'Assertion failed');
}
function eq(actual, expected, label) {
if (actual !== expected) {
throw new Error(`${label || 'Value'}: expected ${expected}, got ${actual}`);
}
}
function near(actual, expected, tolerance, label) {
if (Math.abs(actual - expected) > tolerance) {
throw new Error(`${label || 'Value'}: expected ~${expected}${tolerance}), got ${actual}`);
}
}
// ── Load engine (mock window as global) ────────────────────────
const _global = {};
(function loadModules() {
const fs = require('fs');
const path = require('path');
const dir = path.resolve(__dirname, '..');
// Load quote-pricing.js — sets DEFAULTS on _global
const pricingSrc = fs.readFileSync(path.join(dir, 'quote-pricing.js'), 'utf8')
.replace(/\(window\)\s*;?\s*$/, '(_global);');
new Function('_global', pricingSrc)(_global);
// Load quote-engine.js — sets calculateQuote on _global
const engineSrc = fs.readFileSync(path.join(dir, 'quote-engine.js'), 'utf8')
.replace(/\(window\)\s*;?\s*$/, '(_global);');
new Function('_global', engineSrc)(_global);
})();
const calculateQuote = _global.calculateQuote;
const DEFAULTS = _global.SVSQuotePricing.DEFAULTS;
// Helper: build a state object with sensible defaults
function makeState(overrides) {
return Object.assign({
byol: false,
users: 0,
endpoints: 0,
servers: 0,
addExtHours: false,
addPWM: false,
addINKY: false,
addZT: false,
addUSB: false,
addBMB: false,
ztSeats: 0,
ztRouters: 0,
voipTier: 'basic',
voipSeats: 0,
addVoipPhone: false,
addVoipFax: false,
clientName: '',
contractTerm: 'm2m',
hstEnabled: false,
oneTimeFee: 0,
adminWaived: false
}, overrides);
}
// ── Tests ──────────────────────────────────────────────────────
console.log('\n\x1b[1mSVS Quote Engine — Test Suite\x1b[0m');
// ── 1. Basic pricing ──────────────────────────────────────────
describe('Basic M365 quote (1 user, 1 endpoint, m2m)', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1 }), DEFAULTS);
it('userBase = 140 (m2m rate)', () => eq(q.userBase, 140, 'userBase'));
it('userTotal = 140', () => eq(q.userTotal, 140, 'userTotal'));
it('endpointBase = 35', () => eq(q.endpointBase, 35, 'endpointBase'));
it('endpointTotal = 35', () => eq(q.endpointTotal, 35, 'endpointTotal'));
it('baseSubtotal = 175', () => eq(q.baseSubtotal, 175, 'baseSubtotal'));
it('admin fee scales: max(150, 650-175) = 475', () => eq(q.siteAdminBase, 475, 'siteAdminBase'));
it('adminFeeNet = 475', () => eq(q.adminFeeNet, 475, 'adminFeeNet'));
it('MRR = 650', () => eq(q.MRR, 650, 'MRR'));
it('annual = 7800', () => eq(q.annual, 7800, 'annual'));
it('no discount at m2m', () => eq(q.discountAmt, 0, 'discountAmt'));
it('effectiveMrr = MRR', () => eq(q.effectiveMrr, 650, 'effectiveMrr'));
});
// ── 2. BYOL rate ──────────────────────────────────────────────
describe('BYOL rate (1 user, 1 endpoint)', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true }), DEFAULTS);
it('baseUserRate = 110 (BYOL)', () => eq(q.baseUserRate, 110, 'baseUserRate'));
it('userBase = 110', () => eq(q.userBase, 110, 'userBase'));
it('baseSubtotal = 145', () => eq(q.baseSubtotal, 145, 'baseSubtotal'));
it('admin fee scales: max(150, 650-145) = 505', () => eq(q.siteAdminBase, 505, 'siteAdminBase'));
it('MRR still = 650 (admin absorbs difference)', () => eq(q.MRR, 650, 'MRR'));
});
// ── 3. Admin fee floor ────────────────────────────────────────
describe('Admin fee floor (high service volume)', () => {
// 5 users + 1 endpoint: baseSubtotal = 675+35 = 710 > 650
const q = calculateQuote(makeState({ users: 5, endpoints: 1 }), DEFAULTS);
it('baseSubtotal = 735', () => eq(q.baseSubtotal, 735, 'baseSubtotal'));
it('admin hits floor: max(150, 650-710) = 150', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
it('adminFeeNet = 150', () => eq(q.adminFeeNet, 150, 'adminFeeNet'));
});
// ── 4. Admin fee ZT premium ───────────────────────────────────
describe('Admin fee with Zero Trust premium', () => {
const q = calculateQuote(makeState({ users: 5, endpoints: 1, addZT: true }), DEFAULTS);
it('ztActive = true', () => assert(q.ztActive, 'ztActive'));
it('admin includes ZT premium: 150 + 250 = 400', () => eq(q.adminFeeNet, 400, 'adminFeeNet'));
});
describe('Admin fee ZT premium via ztSeats (no addZT checkbox)', () => {
const q = calculateQuote(makeState({ users: 5, endpoints: 1, ztSeats: 2 }), DEFAULTS);
it('ztActive = true (from ztSeats > 0)', () => assert(q.ztActive, 'ztActive'));
it('admin includes ZT premium', () => eq(q.adminFeeNet, 400, 'adminFeeNet'));
});
// ── 5. Admin fee 1Password markup ─────────────────────────────
describe('Admin fee with 1Password markup', () => {
// 5 users, 1 endpoint, addPWM
// userPWM = 5 * 9 = 45, admin1PWM = round(45 * 0.10) = 5
const q = calculateQuote(makeState({ users: 5, endpoints: 1, addPWM: true }), DEFAULTS);
it('userPWM = 45', () => eq(q.userPWM, 45, 'userPWM'));
it('admin1PWM = 5 (10% of 45, rounded)', () => eq(q.admin1PWM, 5, 'admin1PWM'));
it('adminFeeNet = 150 + 5 = 155', () => eq(q.adminFeeNet, 155, 'adminFeeNet'));
});
// ── 6. Admin waived ───────────────────────────────────────────
describe('Admin fee waived', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, adminWaived: true }), DEFAULTS);
it('adminFeeNet still calculated = 475', () => eq(q.adminFeeNet, 475, 'adminFeeNet'));
it('admin does not contribute to MRR', () => {
eq(q.MRR, 140 + 35, 'MRR without admin'); // 175
});
});
// ── 7. User add-ons ──────────────────────────────────────────
describe('All user add-ons (10 users)', () => {
const q = calculateQuote(makeState({
users: 10, endpoints: 1,
addExtHours: true, addPWM: true, addINKY: true, addZT: true
}), DEFAULTS);
it('userExt = 250', () => eq(q.userExt, 250, 'userExt'));
it('userPWM = 90', () => eq(q.userPWM, 90, 'userPWM'));
it('userINKY = 80', () => eq(q.userINKY, 80, 'userINKY'));
it('userZT = 550', () => eq(q.userZT, 550, 'userZT'));
it('addonRate = 25+9+8+55 = 97', () => {
eq(q.totalUserRate - q.baseUserRate, 97, 'addonRate');
});
it('userTotal = 10 * (140+97) = 2370', () => eq(q.userTotal, 2370, 'userTotal'));
});
// ── 8. Endpoint add-ons ──────────────────────────────────────
describe('Endpoint add-ons (10 endpoints)', () => {
const q = calculateQuote(makeState({
users: 1, endpoints: 10, addUSB: true, addBMB: true
}), DEFAULTS);
it('endpointBase = 350', () => eq(q.endpointBase, 350, 'endpointBase'));
it('endpointUSB = 40', () => eq(q.endpointUSB, 40, 'endpointUSB'));
it('endpointBMB = 250', () => eq(q.endpointBMB, 250, 'endpointBMB'));
it('endpointTotal = 640 (includes no servers)', () => eq(q.endpointTotal, 640, 'endpointTotal'));
});
// ── 9. Server pricing ────────────────────────────────────────
describe('Server pricing', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, servers: 3 }), DEFAULTS);
it('serverBase = 360', () => eq(q.serverBase, 360, 'serverBase'));
it('servers included in endpointTotal', () => eq(q.endpointTotal, 35 + 360, 'endpointTotal'));
it('servers in baseSubtotal', () => eq(q.baseSubtotal, 140 + 35 + 360, 'baseSubtotal'));
});
// ── 10. Contract discounts ───────────────────────────────────
describe('Contract term discounts', () => {
const base = { users: 10, endpoints: 10 };
it('m2m = 0% discount', () => {
const q = calculateQuote(makeState({ ...base, contractTerm: 'm2m' }), DEFAULTS);
eq(q.discountPct, 0, 'discountPct');
eq(q.discountAmt, 0, 'discountAmt');
});
it('12mo = 3% discount', () => {
const q = calculateQuote(makeState({ ...base, contractTerm: '12mo' }), DEFAULTS);
eq(q.discountPct, 0.03, 'discountPct');
eq(q.discountAmt, Math.round(q.MRR * 0.03), 'discountAmt');
eq(q.effectiveMrr, q.MRR - q.discountAmt, 'effectiveMrr');
});
it('24mo = 5% discount', () => {
const q = calculateQuote(makeState({ ...base, contractTerm: '24mo' }), DEFAULTS);
eq(q.discountPct, 0.05, 'discountPct');
eq(q.discountAmt, Math.round(q.MRR * 0.05), 'discountAmt');
});
});
// ── 10b. M365 term-aware rate ────────────────────────────────
describe('M365 rate varies by contract term', () => {
it('m2m uses RATE_M365_M2M ($140)', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: 'm2m' }), DEFAULTS);
eq(q.m365Rate, 140, 'm365Rate');
eq(q.baseUserRate, 140, 'baseUserRate');
});
it('12mo uses RATE_M365 ($130)', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: '12mo' }), DEFAULTS);
eq(q.m365Rate, 130, 'm365Rate');
eq(q.baseUserRate, 130, 'baseUserRate');
});
it('24mo uses RATE_M365 ($130)', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: '24mo' }), DEFAULTS);
eq(q.m365Rate, 130, 'm365Rate');
eq(q.baseUserRate, 130, 'baseUserRate');
});
it('BYOL rate unaffected by term', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true, contractTerm: '12mo' }), DEFAULTS);
eq(q.baseUserRate, 110, 'baseUserRate');
});
});
// ── 11. HST calculation ──────────────────────────────────────
describe('HST calculation', () => {
const q = calculateQuote(makeState({
users: 1, endpoints: 1, hstEnabled: true
}), DEFAULTS);
it('hstAmt = round(650 * 0.13) = 85', () => eq(q.hstAmt, 85, 'hstAmt'));
it('mrrWithHst = 650 + 85 = 735', () => eq(q.mrrWithHst, 735, 'mrrWithHst'));
});
describe('HST disabled = 0', () => {
const q = calculateQuote(makeState({
users: 1, endpoints: 1, hstEnabled: false
}), DEFAULTS);
it('hstAmt = 0', () => eq(q.hstAmt, 0, 'hstAmt'));
it('mrrWithHst = effectiveMrr', () => eq(q.mrrWithHst, q.effectiveMrr, 'mrrWithHst'));
});
// ── 12. VoIP tiers ───────────────────────────────────────────
describe('VoIP tiers', () => {
it('basic = $28/seat', () => {
const q = calculateQuote(makeState({ voipSeats: 5, voipTier: 'basic' }), DEFAULTS);
eq(q.voipSeatRate, 28, 'voipSeatRate');
eq(q.voipSeatsAmt, 140, 'voipSeatsAmt');
});
it('standard = $35/seat', () => {
const q = calculateQuote(makeState({ voipSeats: 5, voipTier: 'standard' }), DEFAULTS);
eq(q.voipSeatRate, 35, 'voipSeatRate');
eq(q.voipSeatsAmt, 175, 'voipSeatsAmt');
});
it('premium = $45/seat', () => {
const q = calculateQuote(makeState({ voipSeats: 5, voipTier: 'premium' }), DEFAULTS);
eq(q.voipSeatRate, 45, 'voipSeatRate');
eq(q.voipSeatsAmt, 225, 'voipSeatsAmt');
});
});
// ── 13. VoIP add-ons ─────────────────────────────────────────
describe('VoIP phone + fax add-ons', () => {
const q = calculateQuote(makeState({
voipSeats: 10, voipTier: 'standard',
addVoipPhone: true, addVoipFax: true
}), DEFAULTS);
it('voipPhoneAmt = 150', () => eq(q.voipPhoneAmt, 150, 'voipPhoneAmt'));
it('voipFaxAmt = 100', () => eq(q.voipFaxAmt, 100, 'voipFaxAmt'));
it('voipTotal = 350+150+100 = 600', () => eq(q.voipTotal, 600, 'voipTotal'));
});
// ── 14. Zero Trust networking ────────────────────────────────
describe('Zero Trust networking', () => {
const q = calculateQuote(makeState({ ztSeats: 10, ztRouters: 2 }), DEFAULTS);
it('ztNetSeats = 250', () => eq(q.ztNetSeats, 250, 'ztNetSeats'));
it('ztNetRouters = 200', () => eq(q.ztNetRouters, 200, 'ztNetRouters'));
it('ztNetTotal = 450', () => eq(q.ztNetTotal, 450, 'ztNetTotal'));
it('ztActive = true', () => assert(q.ztActive, 'ztActive'));
});
// ── 15. Zero users edge case ─────────────────────────────────
describe('Zero users edge case', () => {
const q = calculateQuote(makeState({ users: 0, endpoints: 0 }), DEFAULTS);
it('perUserAllin = 0', () => eq(q.perUserAllin, 0, 'perUserAllin'));
it('perUserServices = 0', () => eq(q.perUserServices, 0, 'perUserServices'));
it('userTotal = 0', () => eq(q.userTotal, 0, 'userTotal'));
it('admin still applies (floor)', () => {
// baseSubtotal = 0, max(150, 650-0) = 650
eq(q.siteAdminBase, 650, 'siteAdminBase');
});
});
// ── 16. Per-user breakdown ───────────────────────────────────
describe('Per-user cost breakdown', () => {
const q = calculateQuote(makeState({ users: 10, endpoints: 10 }), DEFAULTS);
it('perUserServices = round(userTotal / users)', () => {
eq(q.perUserServices, Math.round(q.userTotal / 10), 'perUserServices');
});
it('perUserSiteOvhd = round((effectiveMrr - userTotal) / users)', () => {
eq(q.perUserSiteOvhd, Math.round((q.effectiveMrr - q.userTotal) / 10), 'perUserSiteOvhd');
});
it('perUserAllin = MRR / users', () => {
eq(q.perUserAllin, q.MRR / 10, 'perUserAllin');
});
});
// ── 17. HST + discount combo ─────────────────────────────────
describe('HST applied AFTER contract discount', () => {
const q = calculateQuote(makeState({
users: 10, endpoints: 10,
contractTerm: '12mo', hstEnabled: true
}), DEFAULTS);
it('discount applied first', () => {
eq(q.effectiveMrr, q.MRR - q.discountAmt, 'effectiveMrr');
});
it('HST on discounted amount', () => {
eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
});
it('mrrWithHst = effectiveMrr + hstAmt', () => {
eq(q.mrrWithHst, q.effectiveMrr + q.hstAmt, 'mrrWithHst');
});
});
// ── 18. Realistic full quote ─────────────────────────────────
describe('Realistic 22-user full quote', () => {
const q = calculateQuote(makeState({
users: 22, endpoints: 22, servers: 2,
addPWM: true, addINKY: true,
ztSeats: 5, ztRouters: 1,
voipSeats: 15, voipTier: 'standard', addVoipPhone: true,
contractTerm: '12mo', hstEnabled: true
}), DEFAULTS);
it('userTotal = 22 * (130+9+8) = 3234', () => eq(q.userTotal, 3234, 'userTotal'));
it('endpointBase = 770', () => eq(q.endpointBase, 770, 'endpointBase'));
it('serverBase = 240', () => eq(q.serverBase, 240, 'serverBase'));
it('ztNetTotal = 5*25 + 1*100 = 225', () => eq(q.ztNetTotal, 225, 'ztNetTotal'));
it('voipTotal = 15*35 + 15*15 = 750', () => eq(q.voipTotal, 750, 'voipTotal'));
it('admin: baseSubtotal = 2860+770+240 = 3870, floor applies', () => {
// baseSubtotal = 22*130 + 22*35 + 2*120 = 2860+770+240 = 3870
// Wait: baseSubtotal = userBase + endpointBase + serverBase
// userBase = 22*130 = 2860, endpointBase = 770, serverBase = 240
eq(q.baseSubtotal, 3870, 'baseSubtotal');
eq(q.siteAdminBase, 150, 'siteAdminBase (floor)');
});
it('admin includes ZT premium + 1PWM', () => {
// ztActive because ztSeats > 0
// admin1PWM = round(22*9 * 0.10) = round(19.8) = 20
eq(q.admin1PWM, 20, 'admin1PWM');
eq(q.adminFeeNet, 150 + 250 + 20, 'adminFeeNet'); // 420
});
it('MRR components sum correctly', () => {
const expected = q.userTotal + q.endpointTotal + q.adminFeeNet + q.ztNetTotal + q.voipTotal;
eq(q.MRR, expected, 'MRR');
});
it('12mo discount = 3%', () => {
eq(q.discountAmt, Math.round(q.MRR * 0.03), 'discountAmt');
});
it('HST on discounted total', () => {
eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
});
it('effectiveAnnual = effectiveMrr * 12', () => {
eq(q.effectiveAnnual, q.effectiveMrr * 12, 'effectiveAnnual');
});
});
// ── 19. MRR components always sum ────────────────────────────
describe('MRR = sum of all components (various configs)', () => {
const configs = [
{ users: 1, endpoints: 1 },
{ users: 50, endpoints: 50, servers: 5, addPWM: true, addZT: true },
{ users: 0, endpoints: 0, voipSeats: 20, voipTier: 'premium' },
{ users: 10, endpoints: 10, adminWaived: true },
{ users: 3, endpoints: 3, ztSeats: 10, ztRouters: 3 }
];
configs.forEach((cfg, i) => {
it(`config #${i + 1}: MRR = user + endpoint + admin + zt + voip`, () => {
const q = calculateQuote(makeState(cfg), DEFAULTS);
const adminEff = q.adminWaived ? 0 : q.adminFeeNet;
const expected = q.userTotal + q.endpointTotal + adminEff + q.ztNetTotal + q.voipTotal;
eq(q.MRR, expected, 'MRR sum');
});
});
});
// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Pricing Defaults Integrity ────────────────────
// ══════════════════════════════════════════════════════════════
describe('Pricing DEFAULTS integrity', () => {
const requiredKeys = [
'RATE_M365', 'RATE_M365_M2M', 'RATE_BYOL',
'ADDON_EXT_HOURS', 'ADDON_1PASSWORD', 'ADDON_INKY', 'ADDON_ZERO_TRUST_USER',
'RATE_ENDPOINT', 'RATE_SERVER',
'ADDON_USB_BLOCKING', 'ADDON_BARE_METAL_BACKUP',
'ZT_SEAT_RATE', 'ZT_ROUTER_RATE',
'ADMIN_FEE_FLOOR', 'ADMIN_FEE_MINIMUM', 'ADMIN_FEE_ZT', 'ADMIN_1PWM_PCT',
'VOIP_RATE_BASIC', 'VOIP_RATE_STANDARD', 'VOIP_RATE_PREMIUM',
'VOIP_PHONE_RATE', 'VOIP_FAX_RATE',
'DISCOUNT_M2M', 'DISCOUNT_12MO', 'DISCOUNT_24MO',
'HST_RATE'
];
requiredKeys.forEach(key => {
it(`DEFAULTS.${key} exists and is a number`, () => {
assert(key in DEFAULTS, `${key} missing from DEFAULTS`);
assert(typeof DEFAULTS[key] === 'number', `${key} is not a number`);
});
});
it('DEFAULTS is frozen (immutable)', () => {
assert(Object.isFrozen(DEFAULTS), 'DEFAULTS should be frozen');
});
it('M365 m2m rate > annual rate', () => {
assert(DEFAULTS.RATE_M365_M2M > DEFAULTS.RATE_M365, 'm2m should exceed annual');
});
it('BYOL rate < M365 annual rate', () => {
assert(DEFAULTS.RATE_BYOL < DEFAULTS.RATE_M365, 'BYOL should be less than M365');
});
it('VoIP tiers in ascending order', () => {
assert(DEFAULTS.VOIP_RATE_BASIC < DEFAULTS.VOIP_RATE_STANDARD, 'basic < standard');
assert(DEFAULTS.VOIP_RATE_STANDARD < DEFAULTS.VOIP_RATE_PREMIUM, 'standard < premium');
});
it('Discount rates in ascending order (m2m < 12mo < 24mo)', () => {
assert(DEFAULTS.DISCOUNT_M2M < DEFAULTS.DISCOUNT_12MO, 'm2m < 12mo');
assert(DEFAULTS.DISCOUNT_12MO < DEFAULTS.DISCOUNT_24MO, '12mo < 24mo');
});
it('HST_RATE is 13%', () => {
eq(DEFAULTS.HST_RATE, 0.13, 'HST_RATE');
});
it('ADMIN_FEE_FLOOR < ADMIN_FEE_MINIMUM', () => {
assert(DEFAULTS.ADMIN_FEE_FLOOR < DEFAULTS.ADMIN_FEE_MINIMUM, 'floor < minimum');
});
it('Known pricing values match spec', () => {
eq(DEFAULTS.RATE_M365, 130, 'M365 annual');
eq(DEFAULTS.RATE_M365_M2M, 140, 'M365 m2m');
eq(DEFAULTS.RATE_BYOL, 110, 'BYOL');
eq(DEFAULTS.ADDON_EXT_HOURS, 25, 'ExtHours');
eq(DEFAULTS.ADDON_1PASSWORD, 9, '1PWM');
eq(DEFAULTS.ADDON_INKY, 8, 'INKY');
eq(DEFAULTS.ADDON_ZERO_TRUST_USER, 55, 'ZT user');
eq(DEFAULTS.RATE_ENDPOINT, 35, 'endpoint');
eq(DEFAULTS.RATE_SERVER, 120, 'server');
eq(DEFAULTS.ADMIN_FEE_FLOOR, 150, 'admin floor');
eq(DEFAULTS.ADMIN_FEE_MINIMUM, 650, 'admin minimum');
eq(DEFAULTS.ADMIN_FEE_ZT, 250, 'admin ZT');
});
});
// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Engine Edge Cases & Boundaries ────────────────
// ══════════════════════════════════════════════════════════════
describe('Admin fee exact threshold (baseSubtotal = 500)', () => {
// baseSubtotal = 500 → max(150, 650-500) = max(150, 150) = 150
const q = calculateQuote(makeState({ users: 3, endpoints: 1, byol: true }), DEFAULTS);
// 3 * 110 = 330 + 35 = 365 … not 500. Let me use custom pricing.
it('at threshold: admin = max(floor, minimum - subtotal)', () => {
// 3 users BYOL + 1 endpoint: 330 + 35 = 365
eq(q.baseSubtotal, 365, 'baseSubtotal');
eq(q.siteAdminBase, Math.max(150, 650 - 365), 'siteAdminBase');
});
});
describe('Admin fee exactly at minimum (baseSubtotal = 650)', () => {
// Need baseSubtotal = 650. 4 users M365 m2m = 560, + ~3 endpoints = 105 → 665 too much
// 4 users m2m = 560 + 2 endpoints = 70 → 630; + 0 servers → 630
// Use: 4 users BYOL = 440 + 6 endpoints = 210 → 650
const q = calculateQuote(makeState({ users: 4, endpoints: 6, byol: true }), DEFAULTS);
it('baseSubtotal = 650 exactly', () => eq(q.baseSubtotal, 650, 'baseSubtotal'));
it('admin = floor (650-650=0, floor wins)', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
});
describe('Admin fee when baseSubtotal just under minimum', () => {
// 4 users BYOL = 440, 5 endpoints = 175 → 615
const q = calculateQuote(makeState({ users: 4, endpoints: 5, byol: true }), DEFAULTS);
it('baseSubtotal = 615', () => eq(q.baseSubtotal, 615, 'baseSubtotal'));
it('admin = max(150, 650-615) = max(150, 35) = 150', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
});
describe('Large user count (100 users, 100 endpoints)', () => {
const q = calculateQuote(makeState({
users: 100, endpoints: 100, servers: 10,
addExtHours: true, addPWM: true, addINKY: true, addZT: true,
addUSB: true, addBMB: true,
contractTerm: '24mo', hstEnabled: true
}), DEFAULTS);
it('userTotal = 100 * (130+25+9+8+55) = 22700', () => eq(q.userTotal, 22700, 'userTotal'));
it('endpointBase = 3500', () => eq(q.endpointBase, 3500, 'endpointBase'));
it('endpointUSB = 400', () => eq(q.endpointUSB, 400, 'endpointUSB'));
it('endpointBMB = 2500', () => eq(q.endpointBMB, 2500, 'endpointBMB'));
it('serverBase = 1200', () => eq(q.serverBase, 1200, 'serverBase'));
it('admin hits floor', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
it('MRR is positive integer', () => assert(q.MRR > 0 && Number.isInteger(q.MRR), 'MRR'));
it('24mo discount = 5%', () => eq(q.discountPct, 0.05, 'discountPct'));
it('HST calculated on discounted MRR', () => {
eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
});
it('annual = effectiveMrr * 12', () => eq(q.effectiveAnnual, q.effectiveMrr * 12, 'effectiveAnnual'));
});
describe('String coercion for numeric inputs', () => {
const q = calculateQuote(makeState({ users: '5', endpoints: '3', servers: '2' }), DEFAULTS);
it('users parsed from string', () => eq(q.users, 5, 'users'));
it('endpoints parsed from string', () => eq(q.endpoints, 3, 'endpoints'));
it('servers parsed from string', () => eq(q.servers, 2, 'servers'));
it('calculations correct with string inputs', () => {
eq(q.userBase, 5 * 140, 'userBase');
eq(q.endpointBase, 3 * 35, 'endpointBase');
eq(q.serverBase, 2 * 120, 'serverBase');
});
});
describe('Invalid inputs handled gracefully', () => {
it('NaN endpoints → 0', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: NaN }), DEFAULTS);
eq(q.endpoints, 0, 'endpoints');
});
it('undefined servers → 0', () => {
const q = calculateQuote(makeState({ users: 1, servers: undefined }), DEFAULTS);
eq(q.servers, 0, 'servers');
});
it('null users → 0', () => {
const q = calculateQuote(makeState({ users: null, endpoints: 1 }), DEFAULTS);
eq(q.users, 0, 'users');
});
it('empty string users → 0', () => {
const q = calculateQuote(makeState({ users: '', endpoints: 1 }), DEFAULTS);
eq(q.users, 0, 'users');
});
});
describe('Single endpoint, no users', () => {
const q = calculateQuote(makeState({ users: 0, endpoints: 1 }), DEFAULTS);
it('endpointBase = 35', () => eq(q.endpointBase, 35, 'endpointBase'));
it('userTotal = 0', () => eq(q.userTotal, 0, 'userTotal'));
it('admin still scales', () => {
// baseSubtotal = 0 + 35 + 0 = 35, max(150, 650-35) = 615
eq(q.siteAdminBase, 615, 'siteAdminBase');
});
});
describe('Only servers, no users or endpoints', () => {
const q = calculateQuote(makeState({ users: 0, endpoints: 0, servers: 5 }), DEFAULTS);
it('serverBase = 600', () => eq(q.serverBase, 600, 'serverBase'));
it('endpointTotal includes servers', () => eq(q.endpointTotal, 600, 'endpointTotal'));
it('baseSubtotal = 600', () => eq(q.baseSubtotal, 600, 'baseSubtotal'));
it('admin = max(150, 650-600) = 150', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
});
describe('VoIP only quote (no users, no endpoints)', () => {
const q = calculateQuote(makeState({
users: 0, endpoints: 0,
voipSeats: 20, voipTier: 'premium', addVoipPhone: true, addVoipFax: true
}), DEFAULTS);
it('voipSeatsAmt = 900', () => eq(q.voipSeatsAmt, 900, 'voipSeatsAmt'));
it('voipPhoneAmt = 300', () => eq(q.voipPhoneAmt, 300, 'voipPhoneAmt'));
it('voipFaxAmt = 200', () => eq(q.voipFaxAmt, 200, 'voipFaxAmt'));
it('voipTotal = 1400', () => eq(q.voipTotal, 1400, 'voipTotal'));
it('admin is full (no user/endpoint base)', () => eq(q.siteAdminBase, 650, 'siteAdminBase'));
});
describe('VoIP fax without phone', () => {
const q = calculateQuote(makeState({
voipSeats: 5, voipTier: 'basic', addVoipFax: true, addVoipPhone: false
}), DEFAULTS);
it('voipFaxAmt = 50', () => eq(q.voipFaxAmt, 50, 'voipFaxAmt'));
it('voipPhoneAmt = 0', () => eq(q.voipPhoneAmt, 0, 'voipPhoneAmt'));
it('voipTotal = 140 + 50 = 190', () => eq(q.voipTotal, 190, 'voipTotal'));
});
describe('VoIP addons with zero seats', () => {
const q = calculateQuote(makeState({
voipSeats: 0, voipTier: 'standard', addVoipPhone: true, addVoipFax: true
}), DEFAULTS);
it('voipPhoneAmt = 0 (no seats)', () => eq(q.voipPhoneAmt, 0, 'voipPhoneAmt'));
it('voipFaxAmt = 0 (no seats)', () => eq(q.voipFaxAmt, 0, 'voipFaxAmt'));
it('voipTotal = 0', () => eq(q.voipTotal, 0, 'voipTotal'));
});
describe('ZT networking without ZT user addon', () => {
const q = calculateQuote(makeState({
users: 5, endpoints: 5, addZT: false, ztSeats: 10, ztRouters: 1
}), DEFAULTS);
it('ztActive = true (from ztSeats)', () => assert(q.ztActive, 'ztActive'));
it('userZT = 0 (addZT is false)', () => eq(q.userZT, 0, 'userZT'));
it('ztNetTotal = 250 + 100 = 350', () => eq(q.ztNetTotal, 350, 'ztNetTotal'));
it('admin includes ZT supplement', () => {
assert(q.adminFeeNet >= q.siteAdminBase + 250, 'admin includes ZT');
});
});
describe('Admin waived still calculates adminFeeNet', () => {
const q = calculateQuote(makeState({
users: 10, endpoints: 10, addPWM: true, addZT: true, adminWaived: true
}), DEFAULTS);
it('adminWaived flag is true', () => assert(q.adminWaived, 'adminWaived'));
it('adminFeeNet is still calculated (non-zero)', () => assert(q.adminFeeNet > 0, 'adminFeeNet > 0'));
it('MRR excludes admin', () => {
const expected = q.userTotal + q.endpointTotal + q.ztNetTotal + q.voipTotal;
eq(q.MRR, expected, 'MRR without admin');
});
});
describe('All addons combined with 12mo discount', () => {
const q = calculateQuote(makeState({
users: 15, endpoints: 15, servers: 3,
addExtHours: true, addPWM: true, addINKY: true, addZT: true,
addUSB: true, addBMB: true,
ztSeats: 8, ztRouters: 2,
voipSeats: 10, voipTier: 'standard', addVoipPhone: true, addVoipFax: true,
contractTerm: '12mo', hstEnabled: true
}), DEFAULTS);
it('all user addons active', () => {
assert(q.userExt > 0, 'userExt');
assert(q.userPWM > 0, 'userPWM');
assert(q.userINKY > 0, 'userINKY');
assert(q.userZT > 0, 'userZT');
});
it('all endpoint addons active', () => {
assert(q.endpointUSB > 0, 'endpointUSB');
assert(q.endpointBMB > 0, 'endpointBMB');
});
it('ztNetTotal > 0', () => assert(q.ztNetTotal > 0, 'ztNetTotal'));
it('voipTotal > 0', () => assert(q.voipTotal > 0, 'voipTotal'));
it('12mo discount applied', () => eq(q.discountPct, 0.03, 'discountPct'));
it('HST on discounted total', () => {
eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
});
it('MRR components sum', () => {
const expected = q.userTotal + q.endpointTotal + q.adminFeeNet + q.ztNetTotal + q.voipTotal;
eq(q.MRR, expected, 'MRR sum');
});
});
describe('Per-user breakdown with admin waived', () => {
const q = calculateQuote(makeState({
users: 10, endpoints: 10, adminWaived: true
}), DEFAULTS);
it('perUserAllin = MRR / users', () => {
eq(q.perUserAllin, q.MRR / 10, 'perUserAllin');
});
it('perUserSiteOvhd reflects waived admin', () => {
eq(q.perUserSiteOvhd, Math.round((q.effectiveMrr - q.userTotal) / 10), 'perUserSiteOvhd');
});
});
describe('1Password admin markup scales with users', () => {
it('1 user: admin1PWM = round(9 * 0.10) = 1', () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, addPWM: true }), DEFAULTS);
eq(q.admin1PWM, 1, 'admin1PWM');
});
it('50 users: admin1PWM = round(450 * 0.10) = 45', () => {
const q = calculateQuote(makeState({ users: 50, endpoints: 1, addPWM: true }), DEFAULTS);
eq(q.admin1PWM, 45, 'admin1PWM');
});
it('no 1PWM addon: admin1PWM = 0', () => {
const q = calculateQuote(makeState({ users: 50, endpoints: 1, addPWM: false }), DEFAULTS);
eq(q.admin1PWM, 0, 'admin1PWM');
});
});
describe('HST with admin waived', () => {
const q = calculateQuote(makeState({
users: 10, endpoints: 10, hstEnabled: true, adminWaived: true
}), DEFAULTS);
it('HST computed on MRR without admin', () => {
eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
});
it('mrrWithHst = effectiveMrr + hstAmt', () => {
eq(q.mrrWithHst, q.effectiveMrr + q.hstAmt, 'mrrWithHst');
});
});
describe('Contract term does not affect BYOL rate', () => {
['m2m', '12mo', '24mo'].forEach(term => {
it(`${term}: BYOL rate = 110`, () => {
const q = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true, contractTerm: term }), DEFAULTS);
eq(q.baseUserRate, 110, 'baseUserRate');
});
});
});
describe('Discount amounts are rounded integers', () => {
['12mo', '24mo'].forEach(term => {
it(`${term} discount is integer`, () => {
const q = calculateQuote(makeState({ users: 7, endpoints: 7, contractTerm: term }), DEFAULTS);
assert(Number.isInteger(q.discountAmt), `discountAmt should be integer, got ${q.discountAmt}`);
});
});
});
// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Export JSON Schema Validation ─────────────────
// ══════════════════════════════════════════════════════════════
describe('Export JSON payload schema (simulated)', () => {
// Simulate the payload that exportQuoteJSON() builds from a quote result
function buildExportPayload(q, overrides) {
const o = overrides || {};
const termMap = { m2m: 'Month-to-Month', '12mo': '12-Month', '24mo': '24-Month' };
return {
version: '1.1',
quoteRef: o.quoteRef || 'SVS-20260315-1234',
quoteDate: o.quoteDate || '2026-03-15',
clientName: q.clientName || '',
repName: o.repName || '',
quoteNotes: o.quoteNotes || '',
contractTerm: termMap[q.contractTerm] || 'Month-to-Month',
licensing: q.byol ? 'BYOL' : 'M365-Included',
users: q.users,
endpoints: q.endpoints,
servers: q.servers,
addons: {
extendedHours: q.addExtHours,
passwordManager: q.addPWM,
inkyPro: q.addINKY,
zeroTrustUsers: q.addZT,
baremetalBackup: q.addBMB,
usbBlocking: q.addUSB
},
zeroTrustNetwork: {
seats: q.ztSeats,
routers: q.ztRouters
},
voip: {
tier: q.voipSeats > 0 ? q.voipTier : null,
seats: q.voipSeats,
phoneHardware: q.addVoipPhone,
faxLine: q.addVoipFax,
currentPhoneBill: 0
},
adminWaived: q.adminWaived || false,
onboardingWaived: false,
onboardingManual: false,
pricing: {
baseMrr: q.MRR,
discountPct: Math.round(q.discountPct * 100),
discountAmt: q.discountAmt,
effectiveMrr: q.effectiveMrr,
annual: q.effectiveAnnual,
oneTimeFee: q.oneTimeFee,
hstIncluded: q.hstEnabled,
hstAmt: q.hstAmt,
mrrWithHst: q.mrrWithHst
}
};
}
const q = calculateQuote(makeState({
users: 10, endpoints: 10, servers: 1,
addPWM: true, addINKY: true, addZT: true,
ztSeats: 5, ztRouters: 1,
voipSeats: 8, voipTier: 'standard', addVoipPhone: true,
contractTerm: '12mo', hstEnabled: true,
clientName: 'Acme Corp'
}), DEFAULTS);
const payload = buildExportPayload(q);
it('has version field = "1.1"', () => eq(payload.version, '1.1', 'version'));
it('has quoteRef string', () => assert(typeof payload.quoteRef === 'string' && payload.quoteRef.length > 0, 'quoteRef'));
it('has quoteDate string', () => assert(typeof payload.quoteDate === 'string', 'quoteDate'));
it('clientName matches', () => eq(payload.clientName, 'Acme Corp', 'clientName'));
it('contractTerm is display label', () => eq(payload.contractTerm, '12-Month', 'contractTerm'));
it('licensing is M365-Included', () => eq(payload.licensing, 'M365-Included', 'licensing'));
it('users/endpoints/servers are numbers', () => {
assert(typeof payload.users === 'number', 'users');
assert(typeof payload.endpoints === 'number', 'endpoints');
assert(typeof payload.servers === 'number', 'servers');
});
it('addons object has all 6 boolean keys', () => {
const keys = ['extendedHours', 'passwordManager', 'inkyPro', 'zeroTrustUsers', 'baremetalBackup', 'usbBlocking'];
keys.forEach(k => {
assert(typeof payload.addons[k] === 'boolean', `addons.${k} should be boolean`);
});
});
it('zeroTrustNetwork has seats and routers', () => {
assert(typeof payload.zeroTrustNetwork.seats === 'number', 'zt seats');
assert(typeof payload.zeroTrustNetwork.routers === 'number', 'zt routers');
});
it('voip object has required fields', () => {
assert(typeof payload.voip.seats === 'number', 'voip seats');
assert(typeof payload.voip.phoneHardware === 'boolean', 'voip phone');
assert(typeof payload.voip.faxLine === 'boolean', 'voip fax');
assert(payload.voip.tier === 'standard', 'voip tier');
});
it('voip tier is null when no seats', () => {
const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, voipSeats: 0 }), DEFAULTS);
const p2 = buildExportPayload(q2);
eq(p2.voip.tier, null, 'voip tier null');
});
it('pricing object has all required fields', () => {
const pricingKeys = ['baseMrr', 'discountPct', 'discountAmt', 'effectiveMrr', 'annual', 'oneTimeFee', 'hstIncluded', 'hstAmt', 'mrrWithHst'];
pricingKeys.forEach(k => {
assert(k in payload.pricing, `pricing.${k} missing`);
});
});
it('pricing.discountPct is integer percentage', () => {
eq(payload.pricing.discountPct, 3, 'discountPct as integer %');
});
it('pricing.baseMrr matches engine MRR', () => {
eq(payload.pricing.baseMrr, q.MRR, 'baseMrr');
});
it('pricing.effectiveMrr matches engine', () => {
eq(payload.pricing.effectiveMrr, q.effectiveMrr, 'effectiveMrr');
});
it('pricing.mrrWithHst matches engine', () => {
eq(payload.pricing.mrrWithHst, q.mrrWithHst, 'mrrWithHst');
});
it('BYOL licensing label', () => {
const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true }), DEFAULTS);
const p2 = buildExportPayload(q2);
eq(p2.licensing, 'BYOL', 'licensing');
});
it('m2m contractTerm label', () => {
const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: 'm2m' }), DEFAULTS);
const p2 = buildExportPayload(q2);
eq(p2.contractTerm, 'Month-to-Month', 'contractTerm');
});
it('24mo contractTerm label', () => {
const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: '24mo' }), DEFAULTS);
const p2 = buildExportPayload(q2);
eq(p2.contractTerm, '24-Month', 'contractTerm');
});
it('repName is string', () => {
assert(typeof payload.repName === 'string', 'repName should be string');
});
it('quoteNotes is string', () => {
assert(typeof payload.quoteNotes === 'string', 'quoteNotes should be string');
});
it('repName populates from override', () => {
const p2 = buildExportPayload(q, { repName: 'Jane Doe' });
eq(p2.repName, 'Jane Doe', 'repName');
});
it('quoteNotes populates from override', () => {
const p2 = buildExportPayload(q, { quoteNotes: 'Special pricing approved.' });
eq(p2.quoteNotes, 'Special pricing approved.', 'quoteNotes');
});
});
// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Persistence State Shape ───────────────────────
// ══════════════════════════════════════════════════════════════
describe('Persistence state shape (save round-trip)', () => {
// Simulate the state shape that saveState() produces
function buildPersistenceState(overrides) {
return Object.assign({
clientName: '',
users: 0,
endpoints: 0,
servers: 0,
byol: false,
addExtHours: false,
addPWM: false,
addINKY: false,
addZT: false,
addUSB: false,
addBMB: false,
ztSeats: 0,
ztRouters: 0,
voipTier: 'basic',
voipSeats: 0,
addVoipPhone: false,
addVoipFax: false,
phoneBill: 0,
contractTerm: 'm2m',
hstEnabled: false,
oneTimeFee: 0,
adminWaived: false,
onboardingWaived: false,
onboardingManual: false,
repName: '',
quoteNotes: ''
}, overrides);
}
const fullState = buildPersistenceState({
clientName: 'Test Client',
users: 15, endpoints: 12, servers: 2,
byol: true, addExtHours: true, addPWM: true, addINKY: true,
addZT: true, addUSB: true, addBMB: true,
ztSeats: 5, ztRouters: 1,
voipTier: 'premium', voipSeats: 10,
addVoipPhone: true, addVoipFax: true, phoneBill: 250,
contractTerm: '24mo', hstEnabled: true,
oneTimeFee: 500, adminWaived: true,
onboardingWaived: true, onboardingManual: false
});
it('serializes to valid JSON', () => {
const json = JSON.stringify(fullState);
const parsed = JSON.parse(json);
assert(typeof parsed === 'object', 'valid JSON object');
});
it('round-trip preserves all string fields', () => {
const parsed = JSON.parse(JSON.stringify(fullState));
eq(parsed.clientName, 'Test Client', 'clientName');
eq(parsed.voipTier, 'premium', 'voipTier');
eq(parsed.contractTerm, '24mo', 'contractTerm');
});
it('round-trip preserves all numeric fields', () => {
const parsed = JSON.parse(JSON.stringify(fullState));
eq(parsed.users, 15, 'users');
eq(parsed.endpoints, 12, 'endpoints');
eq(parsed.servers, 2, 'servers');
eq(parsed.ztSeats, 5, 'ztSeats');
eq(parsed.ztRouters, 1, 'ztRouters');
eq(parsed.voipSeats, 10, 'voipSeats');
eq(parsed.phoneBill, 250, 'phoneBill');
eq(parsed.oneTimeFee, 500, 'oneTimeFee');
});
it('round-trip preserves all boolean fields', () => {
const parsed = JSON.parse(JSON.stringify(fullState));
const boolKeys = ['byol', 'addExtHours', 'addPWM', 'addINKY', 'addZT',
'addUSB', 'addBMB', 'addVoipPhone', 'addVoipFax',
'hstEnabled', 'adminWaived', 'onboardingWaived', 'onboardingManual'];
boolKeys.forEach(k => {
assert(typeof parsed[k] === 'boolean', `${k} should be boolean after round-trip`);
});
});
it('persistence state feeds engine correctly', () => {
const q = calculateQuote(fullState, DEFAULTS);
eq(q.users, 15, 'users');
eq(q.byol, true, 'byol');
eq(q.contractTerm, '24mo', 'contractTerm');
assert(q.MRR > 0, 'MRR > 0');
});
it('default state produces valid zero quote', () => {
const q = calculateQuote(buildPersistenceState(), DEFAULTS);
eq(q.users, 0, 'users');
eq(q.userTotal, 0, 'userTotal');
eq(q.endpointTotal, 0, 'endpointTotal');
eq(q.voipTotal, 0, 'voipTotal');
});
});
// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Import Payload Mapping ────────────────────────
// ══════════════════════════════════════════════════════════════
describe('Import payload reverse-maps contract term correctly', () => {
const termReverseMap = {
'Month-to-Month': 'm2m',
'12-Month': '12mo',
'24-Month': '24mo'
};
it('Month-to-Month → m2m', () => eq(termReverseMap['Month-to-Month'], 'm2m', 'term'));
it('12-Month → 12mo', () => eq(termReverseMap['12-Month'], '12mo', 'term'));
it('24-Month → 24mo', () => eq(termReverseMap['24-Month'], '24mo', 'term'));
it('unknown defaults to m2m', () => eq(termReverseMap['bogus'] || 'm2m', 'm2m', 'fallback'));
});
describe('Import → engine round-trip (full payload)', () => {
// Build an export payload, then feed it back through the engine
const original = calculateQuote(makeState({
users: 20, endpoints: 18, servers: 2,
byol: true, addPWM: true, addINKY: true,
ztSeats: 3, ztRouters: 1,
voipSeats: 12, voipTier: 'premium', addVoipPhone: true,
contractTerm: '12mo', hstEnabled: true,
clientName: 'Round Trip Inc'
}), DEFAULTS);
// Simulate import: map export payload fields back to engine state
const imported = makeState({
users: original.users,
endpoints: original.endpoints,
servers: original.servers,
byol: original.byol,
addPWM: original.addPWM,
addINKY: original.addINKY,
addExtHours: original.addExtHours,
addZT: original.addZT,
addUSB: original.addUSB,
addBMB: original.addBMB,
ztSeats: original.ztSeats,
ztRouters: original.ztRouters,
voipTier: original.voipTier,
voipSeats: original.voipSeats,
addVoipPhone: original.addVoipPhone,
addVoipFax: original.addVoipFax,
contractTerm: original.contractTerm,
hstEnabled: original.hstEnabled,
clientName: original.clientName,
adminWaived: original.adminWaived
});
const reimported = calculateQuote(imported, DEFAULTS);
it('MRR matches after round-trip', () => eq(reimported.MRR, original.MRR, 'MRR'));
it('effectiveMrr matches', () => eq(reimported.effectiveMrr, original.effectiveMrr, 'effectiveMrr'));
it('mrrWithHst matches', () => eq(reimported.mrrWithHst, original.mrrWithHst, 'mrrWithHst'));
it('userTotal matches', () => eq(reimported.userTotal, original.userTotal, 'userTotal'));
it('endpointTotal matches', () => eq(reimported.endpointTotal, original.endpointTotal, 'endpointTotal'));
it('voipTotal matches', () => eq(reimported.voipTotal, original.voipTotal, 'voipTotal'));
it('adminFeeNet matches', () => eq(reimported.adminFeeNet, original.adminFeeNet, 'adminFeeNet'));
it('effectiveAnnual matches', () => eq(reimported.effectiveAnnual, original.effectiveAnnual, 'effectiveAnnual'));
});
// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Quote Output Invariants ───────────────────────
// ══════════════════════════════════════════════════════════════
describe('Quote output invariants across random configs', () => {
const configs = [
{ users: 1, endpoints: 1 },
{ users: 25, endpoints: 25, servers: 5, addPWM: true },
{ users: 0, endpoints: 0, voipSeats: 30, voipTier: 'premium' },
{ users: 50, endpoints: 50, addZT: true, ztSeats: 20, ztRouters: 5, contractTerm: '24mo', hstEnabled: true },
{ users: 10, endpoints: 10, adminWaived: true, contractTerm: '12mo' },
{ users: 3, endpoints: 3, byol: true, addExtHours: true, addINKY: true }
];
configs.forEach((cfg, i) => {
const q = calculateQuote(makeState(cfg), DEFAULTS);
it(`config #${i + 1}: effectiveMrr = MRR - discountAmt`, () => {
eq(q.effectiveMrr, q.MRR - q.discountAmt, 'effectiveMrr');
});
it(`config #${i + 1}: effectiveAnnual = effectiveMrr * 12`, () => {
eq(q.effectiveAnnual, q.effectiveMrr * 12, 'effectiveAnnual');
});
it(`config #${i + 1}: mrrWithHst = effectiveMrr + hstAmt`, () => {
eq(q.mrrWithHst, q.effectiveMrr + q.hstAmt, 'mrrWithHst');
});
it(`config #${i + 1}: all monetary values ≥ 0`, () => {
assert(q.MRR >= 0, 'MRR >= 0');
assert(q.effectiveMrr >= 0, 'effectiveMrr >= 0');
assert(q.hstAmt >= 0, 'hstAmt >= 0');
assert(q.mrrWithHst >= 0, 'mrrWithHst >= 0');
});
});
});
// ── Results ──────────────────────────────────────────────────
console.log(`\n${'─'.repeat(50)}`);
if (_failed === 0) {
console.log(`\x1b[32m All ${_passed} tests passed.\x1b[0m\n`);
process.exit(0);
} else {
console.log(`\x1b[31m ${_failed} of ${_passed + _failed} tests failed.\x1b[0m\n`);
process.exit(1);
}