48 lines
2.0 KiB
JavaScript
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\./);
|
|
});
|