Files
Mastermind/test/utils.test.js

48 lines
2.0 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
let utilsPromise;
async function loadUtils() {
utilsPromise ||= import('../web/src/lib/utils.js');
return utilsPromise;
}
test('extractDomain returns lower-cased sender domain', async () => {
const { extractDomain } = await loadUtils();
assert.equal(extractDomain('Jane Doe <Jane.Doe@Example.COM>'), 'example.com');
assert.equal(extractDomain('no-at-symbol'), '');
});
test('extractFirstJobNumber finds the first long numeric token', async () => {
const { extractFirstJobNumber } = await loadUtils();
assert.equal(extractFirstJobNumber('RE: Job 0222600001 addendum'), '0222600001');
assert.equal(extractFirstJobNumber('no job here'), '');
});
test('validatePassword enforces the expected complexity rules', async () => {
const { validatePassword } = await loadUtils();
assert.equal(validatePassword('short'), 'Password must be at least 12 characters.');
assert.equal(validatePassword('alllowercase123'), 'Password must include an uppercase letter.');
assert.equal(validatePassword('ALLUPPERCASE123'), 'Password must include a lowercase letter.');
assert.equal(validatePassword('MissingNumber!'), 'Password must include a number.');
assert.equal(validatePassword('ValidPassword123'), null);
});
test('draft builders include source email context', async () => {
const { buildPCOBody, buildRFIBody } = await loadUtils();
const email = {
id: 'email-1',
subject: 'Coordination needed',
from_addr: 'pm@example.com',
date: '2026-03-01T00:00:00.000Z',
body_text: 'Need a price and schedule impact.'
};
const project = { name: 'Example Project', job_number: '0222600001' };
assert.match(buildPCOBody(email, project), /Potential Change Order/);
assert.match(buildPCOBody(email, project), /Coordination needed/);
assert.match(buildRFIBody(email, project), /RFI - Draft/);
assert.match(buildRFIBody(email, project), /Need a price and schedule impact\./);
});