149 lines
6.2 KiB
JavaScript
149 lines
6.2 KiB
JavaScript
const { test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
function loadVitals() {
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'vitals.json'), 'utf8');
|
|
return JSON.parse(raw);
|
|
}
|
|
|
|
test('vitals.json exposes all calculator age groups', () => {
|
|
const data = loadVitals();
|
|
assert.equal(data.version, '1.0');
|
|
assert.deepEqual(Object.keys(data.ageGroups), [
|
|
'premie',
|
|
'0-3mo',
|
|
'3-6mo',
|
|
'6-12mo',
|
|
'1-3yr',
|
|
'3-6yr',
|
|
'6-12yr',
|
|
'>12yr'
|
|
]);
|
|
});
|
|
|
|
test('vitals.json preserves key Harriet Lane ranges', () => {
|
|
const groups = loadVitals().ageGroups;
|
|
assert.equal(groups.premie.hr.awake, '120-170');
|
|
assert.equal(groups.premie.spo2, '88-95% (target)');
|
|
assert.equal(groups['0-3mo'].sbp, '65-85');
|
|
assert.equal(groups['3-6mo'].rr, '30-45');
|
|
assert.equal(groups['1-3yr'].weight, '10-15 kg');
|
|
assert.equal(groups['6-12yr'].hr.sleeping, '50-85');
|
|
assert.equal(groups['>12yr'].dbp, '65-85');
|
|
});
|
|
|
|
test('vitals.json entries have complete renderable fields', () => {
|
|
const groups = loadVitals().ageGroups;
|
|
Object.entries(groups).forEach(([key, group]) => {
|
|
assert.ok(group.label, `${key}.label`);
|
|
assert.ok(group.hr && group.hr.awake && group.hr.sleeping, `${key}.hr`);
|
|
['rr', 'sbp', 'dbp', 'temp', 'weight', 'spo2'].forEach((field) => {
|
|
assert.ok(group[field], `${key}.${field}`);
|
|
});
|
|
assert.ok(Array.isArray(group.notes) && group.notes.length > 0, `${key}.notes`);
|
|
});
|
|
});
|
|
|
|
test('resus-meds.json exposes all PALS medication formulas', () => {
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'resus-meds.json'), 'utf8');
|
|
const data = JSON.parse(raw);
|
|
assert.equal(data.version, '1.0');
|
|
assert.deepEqual(data.medications.map((m) => m.formula), [
|
|
'adenosine',
|
|
'amiodarone',
|
|
'atropine',
|
|
'calciumChloride',
|
|
'calciumGluconate',
|
|
'dextrose',
|
|
'epinephrine',
|
|
'hydrocortisone',
|
|
'insulin',
|
|
'lidocaine',
|
|
'magnesiumSulfate',
|
|
'naloxone',
|
|
'sodiumBicarbonate'
|
|
]);
|
|
});
|
|
|
|
test('resus dose formulas preserve representative outputs', async () => {
|
|
const { calculateResusDose } = await import('../public/js/calculators/resus.js');
|
|
assert.equal(calculateResusDose('adenosine', 20).dose, '2 mg (0.1 mg/kg)');
|
|
assert.equal(calculateResusDose('epinephrine', 10).dose, '0.1 mg IV/IO (0.01 mg/kg of 0.1 mg/mL = 1 mL) q3-5 min');
|
|
assert.equal(calculateResusDose('magnesiumSulfate', 50).dose, '2000 mg (50 mg/kg)');
|
|
assert.equal(calculateResusDose('sodiumBicarbonate', 8).extra, 'Dilute to 0.5 mEq/mL (use 4.2% solution) for neonates/small infants.');
|
|
});
|
|
|
|
test('fenton-lms.json preserves key LMS anchors', () => {
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'fenton-lms.json'), 'utf8');
|
|
const data = JSON.parse(raw);
|
|
assert.equal(data.version, '1.0');
|
|
assert.deepEqual(data.weightLms.male['22'], { L: 0.21, M: 496, S: 0.17 });
|
|
assert.deepEqual(data.weightLms.male['40'], { L: 0.01, M: 3530, S: 0.12 });
|
|
assert.deepEqual(data.weightLms.female['22'], { L: 0.23, M: 474, S: 0.17 });
|
|
assert.deepEqual(data.weightLms.female['40'], { L: 0.01, M: 3340, S: 0.12 });
|
|
});
|
|
|
|
test('neonatal Fenton helpers preserve interpolation and classification', async () => {
|
|
const neonatal = await import('../public/js/calculators/neonatal.js');
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'fenton-lms.json'), 'utf8');
|
|
const data = JSON.parse(raw).weightLms;
|
|
assert.deepEqual(neonatal.interpolateLMS(data.male, 30), { L: 0.18, M: 1430, S: 0.14 });
|
|
assert.equal(Math.round(neonatal.interpolateLMS(data.female, 30.5).M), 1415);
|
|
assert.equal(neonatal.classifyGA(36, 6).label, 'Late Preterm');
|
|
assert.equal(neonatal.classifyBirthWeight(900).label, 'Extremely Low Birth Weight (ELBW)');
|
|
assert.equal(neonatal.classifyWeight(50).label, 'AGA');
|
|
});
|
|
|
|
test('equipment.json preserves equipment age groups and anchors', () => {
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'equipment.json'), 'utf8');
|
|
const data = JSON.parse(raw);
|
|
assert.equal(data.version, '1.0');
|
|
assert.deepEqual(Object.keys(data.ageGroups), [
|
|
'premie',
|
|
'newborn',
|
|
'6mo',
|
|
'1yr',
|
|
'2-3yr',
|
|
'4-6yr',
|
|
'7-10yr',
|
|
'11-15yr',
|
|
'16yr'
|
|
]);
|
|
assert.equal(data.ageGroups.newborn.ett, '3.0-3.5');
|
|
assert.equal(data.ageGroups['1yr'].lma, '2');
|
|
assert.equal(data.ageGroups['4-6yr'].blade, 'Miller 2 / MAC 2');
|
|
assert.equal(data.ageGroups['16yr'].foley, '12 Fr');
|
|
});
|
|
|
|
test('equipment.json entries have complete renderable fields', () => {
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'equipment.json'), 'utf8');
|
|
const groups = JSON.parse(raw).ageGroups;
|
|
Object.entries(groups).forEach(([key, group]) => {
|
|
['label', 'bvm', 'nasal', 'oral', 'blade', 'ett', 'lma', 'glidescope', 'iv', 'cvl', 'ngt', 'chest', 'foley'].forEach((field) => {
|
|
assert.ok(group[field], `${key}.${field}`);
|
|
});
|
|
});
|
|
});
|
|
|
|
test('bhutani-zones.json preserves risk-zone curves', () => {
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'bhutani-zones.json'), 'utf8');
|
|
const data = JSON.parse(raw);
|
|
assert.equal(data.version, '1.0');
|
|
assert.deepEqual(Object.keys(data.zones), ['p95', 'p75', 'p40']);
|
|
assert.equal(data.zones.p95['24'], 9.6);
|
|
assert.equal(data.zones.p75['48'], 12.6);
|
|
assert.equal(data.zones.p40['120'], 13.2);
|
|
});
|
|
|
|
test('bilirubin helpers preserve Bhutani interpolation and classification', async () => {
|
|
const bilirubin = await import('../public/js/calculators/bilirubin.js');
|
|
const raw = fs.readFileSync(path.join(__dirname, '..', 'public', 'data', 'calculators', 'bhutani-zones.json'), 'utf8');
|
|
const zones = JSON.parse(raw).zones;
|
|
assert.equal(bilirubin.interpolateThreshold(zones.p95, 21), 9.05);
|
|
assert.equal(bilirubin.classifyBhutaniRisk(zones, 24, 10).zone, 'High-Risk Zone');
|
|
assert.equal(bilirubin.classifyBhutaniRisk(zones, 24, 8).zone, 'High-Intermediate Zone');
|
|
assert.equal(bilirubin.classifyBhutaniRisk(zones, 24, 7).zone, 'Low-Intermediate Zone');
|
|
assert.equal(bilirubin.classifyBhutaniRisk(zones, 24, 5).zone, 'Low-Risk Zone');
|
|
});
|