Fix local startup defaults and add MVP tests
This commit is contained in:
14
test/compose.integration.test.mjs
Normal file
14
test/compose.integration.test.mjs
Normal file
@@ -0,0 +1,14 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
|
||||
test('docker compose config exposes the expected local services and safe defaults', () => {
|
||||
const config = fs.readFileSync('/tmp/mastermind-mvp/docker-compose.yml', 'utf8');
|
||||
|
||||
assert.match(config, /db:/);
|
||||
assert.match(config, /web:/);
|
||||
assert.match(config, /worker:/);
|
||||
assert.match(config, /BOOTSTRAP_OWNER_EMAIL: \$\{BOOTSTRAP_OWNER_EMAIL:-owner@local\}/);
|
||||
assert.match(config, /BOOTSTRAP_OWNER_PASSWORD: \$\{BOOTSTRAP_OWNER_PASSWORD:-owner\}/);
|
||||
assert.match(config, /\.\/README\.md:\/app\/README\.md:ro/);
|
||||
});
|
||||
62
test/helpers.test.mjs
Normal file
62
test/helpers.test.mjs
Normal file
@@ -0,0 +1,62 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
import {
|
||||
applyRulesToEmail,
|
||||
buildPCOBody,
|
||||
buildRFIBody,
|
||||
extractDomain,
|
||||
extractFirstJobNumber,
|
||||
validatePassword
|
||||
} from '../web/src/lib/helpers.js';
|
||||
|
||||
test('extractDomain returns normalized domain', () => {
|
||||
assert.equal(extractDomain('Jane Doe <Jane.Doe@Example.COM>'), 'example.com');
|
||||
assert.equal(extractDomain('no-domain'), '');
|
||||
});
|
||||
|
||||
test('extractFirstJobNumber finds the first long job number', () => {
|
||||
assert.equal(extractFirstJobNumber('RE: Job 0222600001 - panel issue'), '0222600001');
|
||||
assert.equal(extractFirstJobNumber('ticket 12345 only'), '');
|
||||
});
|
||||
|
||||
test('validatePassword enforces the documented rules', () => {
|
||||
assert.equal(validatePassword('short'), 'Password must be at least 12 characters.');
|
||||
assert.equal(validatePassword('lowercaseonly1'), 'Password must include an uppercase letter.');
|
||||
assert.equal(validatePassword('UPPERCASEONLY1'), 'Password must include a lowercase letter.');
|
||||
assert.equal(validatePassword('NoDigitsHere!'), 'Password must include a number.');
|
||||
assert.equal(validatePassword('ValidPassword1'), null);
|
||||
});
|
||||
|
||||
test('applyRulesToEmail returns the first matching rule', async () => {
|
||||
const match = await applyRulesToEmail(
|
||||
{
|
||||
from_addr: 'pm@gc.example.com',
|
||||
subject: '0222600001 change request',
|
||||
body_text: 'Please review the change request.',
|
||||
thread_key: 'thread-1'
|
||||
},
|
||||
[
|
||||
{ id: '1', enabled: true, match_type: 'subject_contains', match_value: '0222600001', project_id: 'project-a' },
|
||||
{ id: '2', enabled: true, match_type: 'from_domain', match_value: 'example.com', project_id: 'project-b' }
|
||||
]
|
||||
);
|
||||
|
||||
assert.deepEqual(match, { projectId: 'project-a', confidence: 0.9, ruleId: '1' });
|
||||
});
|
||||
|
||||
test('draft builders include key context from the source email', () => {
|
||||
const email = {
|
||||
id: 'email-1',
|
||||
subject: 'Need clarification',
|
||||
from_addr: 'pm@example.com',
|
||||
date: '2026-03-01',
|
||||
body_text: 'Line one\nLine two'
|
||||
};
|
||||
const project = { name: 'Tower A', job_number: '0222600001' };
|
||||
|
||||
assert.match(buildPCOBody(email, project), /Potential Change Order/);
|
||||
assert.match(buildPCOBody(email, project), /Tower A/);
|
||||
assert.match(buildRFIBody(email, project), /RFI/);
|
||||
assert.match(buildRFIBody(email, project), /> Line one/);
|
||||
});
|
||||
Reference in New Issue
Block a user