DEV Community

Rahul
Rahul

Posted on

Testcraft Studio frontend 47: tests/frontend.test.mjs

import test, { after } from 'node:test';
import assert from 'node:assert/strict';
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { createServer } from 'vite';
import { readFile } from 'node:fs/promises';

const server = await createServer({ server: { middlewareMode: true, hmr: false }, appType: 'custom' });
after(() => server.close());
const { makeSeed: makeMcmSeed, upgradeDemoState } = await server.ssrLoadModule('/src/seed.js');
function makeSeed() { const state = makeMcmSeed(); state.session = { team: 'RMS', role: 'user', name: 'RMS User', authenticated: true }; state.activeWorkspaceId = 'w1042'; return state; }
const { resolveSelection, readiness, eligibleDocuments, bumpVersion, contextKey, csv, parseCsv, StoreProvider } = await server.ssrLoadModule('/src/store.jsx');
const { makeDemoSuite } = await server.ssrLoadModule('/src/generation.js');
const { default: App } = await server.ssrLoadModule('/src/AppShell.jsx');
const { authenticateTeam, hashPassword, addTeam, documentInputIssues, baselineInputIssues, saveClarification } = await server.ssrLoadModule('/src/access.js');
const { canApprove, visibleWorkspaces, roleLabels } = await server.ssrLoadModule('/src/store.jsx');
const { approvalBlockers } = await server.ssrLoadModule('/src/pages/Approvals.jsx');
const { stageFile } = await server.ssrLoadModule('/src/files.js');
const { requestBaseline, requestBaselineMerge, decideBaseline } = await server.ssrLoadModule('/src/baseline.js');
const { makeFreshState } = await server.ssrLoadModule('/src/store.jsx');
const { readTemplate, readZip } = await server.ssrLoadModule('/src/excel.js');
const { buildChatRequest, interpretChatRequest, requestWorkspaceAssistant, saveChatDraft, assertChatContext } = await server.ssrLoadModule('/src/chatAssistant.js');
const { suiteExport } = await server.ssrLoadModule('/src/suiteExport.js');

function chatFixture() {
  const state = makeMcmSeed(); state.session = { team: 'MCM', role: 'user', name: 'MCM User', authenticated: true };
  const workspace = state.workspaces.find(item => item.id === state.activeWorkspaceId);
  state.threads[contextKey(workspace)] = { workspaceId: workspace.id, team: workspace.team, version: workspace.version, messages: [] };
  return { state, workspace, messages: state.threads[contextKey(workspace)].messages };
}
async function chatReply(fixture, prompt, options = {}) {
  const { state, workspace, messages } = fixture;
  const request = buildChatRequest(state, workspace, { prompt, templateId: 'mcm-t1', messages, ...options });
  const response = await requestWorkspaceAssistant(request, { state });
  messages.push({ id: `user-${messages.length}`, role: 'user', actor: 'MCM User', content: prompt, at: new Date().toISOString() });
  const message = { ...response, id: `assistant-${messages.length}`, role: 'assistant', actor: 'Workspace assistant', at: new Date().toISOString() };
  messages.push(message); return message;
}

test('chat separates questions, source requests, typed generation and follow-up refinements', () => {
  assert.equal(interpretChatRequest('What does the member identifier requirement say?').intent, 'question');
  assert.equal(interpretChatRequest('Generate technical test cases', { kind: 'Business' }).kind, 'Technical');
  assert.equal(interpretChatRequest('Generate test cases', { kind: 'Business' }).kind, 'Business');
  const previousDraft = { kind: 'Technical' };
  assert.deepEqual([interpretChatRequest('Only negative scenarios', { previousDraft }).intent, interpretChatRequest('Only negative scenarios', { previousDraft }).kind], ['refine', 'Technical']);
  assert.equal(interpretChatRequest('Show sources for these test cases', { previousDraft }).intent, 'sources');
  assert.equal(interpretChatRequest('Generate 1000 technical tests').count, 1000);
});

test('technical chat cases use technical sources and retain exact approved expected behavior', async () => {
  const f = chatFixture(), response = await chatReply(f, 'Generate technical test cases');
  assert.equal(response.engine, 'local-evidence'); assert.equal(response.draft.kind, 'Technical');
  assert.deepEqual(response.draft.tests.map(test => test.requirement), ['VAL-001', 'VAL-003']);
  assert.ok(response.draft.tests.every(test => test.sourceIds.every(id => f.state.documents.find(doc => doc.id === id)?.category === 0)));
  for (const test of response.draft.tests) assert.equal(test.expected, f.state.baselines.find(b => b.id === f.workspace.baselineId).rules.find(rule => rule.id === test.requirement).text);
  assert.equal(response.citations[0].revision, 2); assert.match(response.citations[0].locator, /Lines/);
  assert.ok(!response.citations.some(citation => ['d1', 'd2', 'mcm-d2'].includes(citation.id)));
  const large = await chatReply(f, 'Generate 1000 technical test cases');
  assert.equal(large.draft.tests.length, 2); assert.match(large.content, /not filled the requested count/);
  const missing = await chatReply(f, 'Generate negative technical test cases');
  assert.equal(missing.draft, undefined); assert.match(missing.content, /does not support negative technical/);
});

test('source follow-ups cite the preceding answer and support opening its pinned revision', async () => {
  const f = chatFixture(), answer = await chatReply(f, 'What is the required member identifier behavior?');
  assert.match(answer.content, /missing required member identifier/);
  const sources = await chatReply(f, 'Show sources for this answer');
  assert.equal(sources.intent, 'sources');
  assert.deepEqual(sources.citations.map(item => item.id).sort(), answer.citations.map(item => item.id).sort());
  assert.ok(sources.citations.every(citation => citation.excerpt && citation.name && citation.revision));
  const sourceList = await chatReply(chatFixture(), 'Show sources for the selected knowledge');
  assert.ok(sourceList.citations.length > 0);
  const unknown = await chatReply(f, 'What is the approved quantum banana timeout?');
  assert.ok(!unknown.draft); assert.ok(!unknown.content.includes('30 seconds'));
});

test('chat refinements preserve previous drafts, filter to documented scenarios, and respect selected CR scope', async () => {
  const f = chatFixture(), original = await chatReply(f, 'Generate functional test cases');
  const originalCopy = structuredClone(original.draft);
  const refined = await chatReply(f, 'Only negative scenarios');
  assert.equal(refined.draft.tests.length, 1); assert.equal(refined.draft.tests[0].requirement, 'VAL-002');
  assert.equal(refined.draft.tests[0].expected, 'Reject a request with a missing required member identifier.');
  assert.deepEqual(original.draft, originalCopy);
  const scoped = await chatReply(f, 'Generate functional test cases for CR-1042');
  assert.deepEqual(scoped.draft.tests.map(test => test.requirement), ['VAL-002']);
  const unavailable = await chatReply(f, 'Generate technical test cases for CR-9999');
  assert.equal(unavailable.draft, undefined); assert.match(unavailable.content, /not in the selected workspace/);
});

test('chat drafts save once as independent reviewable suites and export the selected template columns', async () => {
  const f = chatFixture();
  f.state.templates.find(t => t.id === 'mcm-t1').fields = ['Test ID', 'Type', 'Title', 'Expected result', 'Evidence', 'Review batch'];
  const reply = await chatReply(f, 'Generate technical test cases'), before = f.state.suites.length;
  const id = saveChatDraft(f.state, f.workspace, reply.id);
  assert.equal(saveChatDraft(f.state, f.workspace, reply.id), id); assert.equal(f.state.suites.length, before + 1);
  const saved = f.state.suites.find(suite => suite.id === id);
  saved.tests[0].notes = 'Reviewed'; assert.equal(reply.draft.tests[0].notes, '');
  saved.tests[0].customFields['Review batch'] = 'Office review';
  f.state.templates.find(t => t.id === 'mcm-t1').fields.push('Later header');
  f.state.documents.find(d => d.id === 'mcm-d1').revision = 9;
  const rows = parseCsv(suiteExport(f.state, f.workspace, saved).content);
  assert.deepEqual(rows[0], ['Test ID', 'Type', 'Title', 'Expected result', 'Evidence', 'Review batch']);
  assert.equal(rows[1][1], 'Technical'); assert.match(rows[1][4], /revision 2/); assert.ok(!rows[1][4].includes('revision 9'));
  assert.equal(rows[1][5], 'Office review');
  assert.throws(() => saveChatDraft(f.state, f.workspace, reply.id), /knowledge changed/);
});

test('knowledge changes, revoked access and history prevent stale chat drafts being saved or refined', async () => {
  const f = chatFixture(), response = await chatReply(f, 'Generate technical test cases');
  const request = buildChatRequest(f.state, f.workspace, { prompt: 'What is the identifier format?', templateId: 'mcm-t1', messages: f.messages });
  f.state.documents.find(d => d.id === 'mcm-d1').excerpt += ' Changed extraction.';
  assert.throws(() => assertChatContext(f.state, request), /knowledge changed/);
  assert.throws(() => saveChatDraft(f.state, f.workspace, response.id), /knowledge changed/);
  assert.throws(() => buildChatRequest(f.state, f.workspace, { prompt: 'Add negative scenarios', messages: f.messages }), /Generate a new draft/);
  assert.throws(() => saveChatDraft(f.state, f.workspace, response.id, 'historic:1'), /read-only/);
  const fresh = chatFixture(), pending = buildChatRequest(fresh.state, fresh.workspace, { prompt: 'Show sources', templateId: 'mcm-t1', messages: [] });
  fresh.state.shares.find(share => share.consumer === 'MCM').status = 'Revoked';
  await assert.rejects(requestWorkspaceAssistant(pending, { state: fresh.state }), /knowledge changed/);
});

test('chat transport honors cancellation and rejects fabricated citations and malformed cases', async () => {
  const f = chatFixture(), request = buildChatRequest(f.state, f.workspace, { prompt: 'Generate technical test cases', templateId: 'mcm-t1' });
  const abort = new AbortController(); abort.abort();
  await assert.rejects(requestWorkspaceAssistant(request, { state: f.state, signal: abort.signal }), { name: 'AbortError' });
  const during = new AbortController();
  await assert.rejects(requestWorkspaceAssistant(request, { state: f.state, signal: during.signal, transport: async () => { during.abort(); return {}; } }), { name: 'AbortError' });
  await assert.rejects(requestWorkspaceAssistant(request, { state: f.state, transport: async () => ({ content: 'Answer', citations: [{ id: 'd1', revision: 2 }] }) }), /invalid evidence/);
  await assert.rejects(requestWorkspaceAssistant(request, { state: f.state, transport: async () => ({ content: 'Answer', citations: [{ id: 'mcm-d1', revision: 99 }] }) }), /invalid evidence/);
  const valid = await requestWorkspaceAssistant(request, { state: f.state });
  valid.draft.tests[0].steps = [42];
  await assert.rejects(requestWorkspaceAssistant(request, { state: f.state, transport: async () => valid }), /invalid test-case draft/);
});

test('chat draft controls and suite deep links render with the existing application shell', async () => {
  const f = chatFixture(); await chatReply(f, 'Generate technical test cases');
  globalThis.location = { hash: '#chat' };
  globalThis.localStorage = { getItem: key => key === 'testcraft-studio-v2' ? JSON.stringify(f.state) : null };
  const html = renderToStaticMarkup(React.createElement(StoreProvider, null, React.createElement(App)));
  assert.ok(html.includes('Technical test cases')); assert.ok(html.includes('Save to test suite')); assert.ok(html.includes('Chat test-case template')); assert.ok(html.includes('Upload Excel template'));
  const message = f.messages.at(-1), id = saveChatDraft(f.state, f.workspace, message.id);
  globalThis.location = { hash: `#suites?suite=${id}` };
  const suite = renderToStaticMarkup(React.createElement(StoreProvider, null, React.createElement(App)));
  assert.ok(suite.includes('Verify identifier format')); assert.ok(suite.includes('Technical tests'));
});

test('document uploads retain readable content, checksum, category, and original file', async () => {
  const saved = [];
  globalThis.indexedDB = { open() { const request = {}; queueMicrotask(() => {
    request.result = { objectStoreNames: { contains: () => true }, close() {}, transaction() {
      const transaction = { objectStore: () => ({ put(file, id) { saved.push({ file, id }); queueMicrotask(() => transaction.oncomplete()); } }) };
      return transaction;
    } }; request.onsuccess();
  }); return request; } };
  const original = new File(['abc'], 'MCM_context.txt', { type: 'text/plain' });
  const document = await stageFile(original, { team: 'MCM', category: 2 });
  assert.equal(document.excerpt, 'abc');
  assert.equal(document.checksum, 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
  assert.equal(document.category, 2);
  assert.equal(saved[0].file, original); assert.equal(saved[0].id, document.id);
  await assert.rejects(stageFile(new File([], 'empty.txt'), {}), /empty/);
  await assert.rejects(stageFile(new File(['abc'], 'program.exe'), {}), /use PDF/);
  delete globalThis.indexedDB;
});

test('blocked browser file storage produces a retryable error instead of an endless upload', async () => {
  globalThis.indexedDB = { open() { const request = {}; queueMicrotask(() => request.onblocked()); return request; } };
  await assert.rejects(stageFile(new File(['abc'], 'context.txt'), {}), /storage is busy/);
  delete globalThis.indexedDB;
});

test('baseline approval checks knowledge selection without blocking on optional questions', () => {
  const state = makeSeed(), candidate = state.candidates[0];
  assert.deepEqual(approvalBlockers(state, candidate), []);
  candidate.crIds.push('cr1068');
  assert.deepEqual(approvalBlockers(state, candidate), []);
});

test('shared team passwords select only User or Administrator access', async () => {
  const state = makeMcmSeed();
  assert.deepEqual(Object.keys(roleLabels), ['user', 'administrator']);
  const normal = await authenticateTeam(state, 'MCM', 'team-demo');
  const admin = await authenticateTeam(state, 'MCM', 'admin-demo');
  assert.equal(normal.role, 'user'); assert.equal(admin.role, 'administrator');
  assert.equal(canApprove({ ...state, session: normal }), false);
  assert.equal(canApprove({ ...state, session: admin }), true);
  await assert.rejects(authenticateTeam(state, 'MCM', 'incorrect'), /password does not match/);
  await assert.rejects(authenticateTeam(state, 'Unknown', 'team-demo'), /Choose a team/);
});

test('only Administrators add teams, with separate shared and admin passwords', async () => {
  const state = makeMcmSeed();
  const userHash = await hashPassword('new-team-password'), adminHash = await hashPassword('new-admin-password');
  state.session = await authenticateTeam(state, 'MCM', 'team-demo');
  assert.throws(() => addTeam(state, 'New Team', userHash, adminHash), /Only an Administrator/);
  state.session = await authenticateTeam(state, 'MCM', 'admin-demo');
  addTeam(state, 'New Team', userHash, adminHash);
  assert.equal((await authenticateTeam(state, 'New Team', 'new-team-password')).role, 'user');
  assert.equal((await authenticateTeam(state, 'New Team', 'new-admin-password')).role, 'administrator');
  await assert.rejects(authenticateTeam(state, 'New Team', 'team-demo'), /password does not match/);
});

test('baseline and CR uploads need one document in any category, never all three', () => {
  const state = makeSeed();
  assert.equal(baselineInputIssues(state, 'New baseline', []).length, 1);
  assert.equal(documentInputIssues([]).length, 1);
  for (const category of [0, 1, 2]) {
    const docs = [{ id: `single-${category}`, category }];
    assert.deepEqual(baselineInputIssues(state, 'New baseline', docs), []);
    assert.deepEqual(documentInputIssues(docs), []);
  }
});

test('Users resolve source-backed questions without a reviewer approval step', () => {
  const state = makeSeed(), workspace = state.workspaces[0];
  const docs = eligibleDocuments(state, workspace);
  for (const question of state.questions.filter(q => q.workspaceId === workspace.id)) saveClarification(state, workspace, question.id, 'Synthetic supported behavior', 'dshared', 'Sample contract v2.1, interface section', docs);
  assert.equal(readiness(state, workspace).ready, true);
  assert.ok(state.questions.filter(q => q.workspaceId === workspace.id).every(q => q.status === 'resolved'));
  assert.equal(visibleWorkspaces(state).length, 4);
});

test('MCM is the default team with complete isolated demo data', () => {
  const state = makeMcmSeed();
  assert.equal(state.session.team, 'MCM');
  assert.equal(state.teams[0], 'MCM');
  const workspace = state.workspaces.find(w => w.id === state.activeWorkspaceId);
  assert.equal(workspace.team, 'MCM');
  assert.ok(eligibleDocuments(state, workspace).some(d => d.name === 'MCM_Message_Processor.sql'));
  assert.ok(eligibleDocuments(state, workspace).every(d => d.team === 'MCM' || d.id === 'dshared'));
  assert.deepEqual(resolveSelection(state, workspace.baselineId, workspace.crIds).issues, []);
  const reviewWorkspace = state.workspaces.find(w => w.id === 'mcm-w1051');
  assert.equal(readiness(state, reviewWorkspace).ready, true);
  assert.ok(makeDemoSuite(state, reviewWorkspace, 'mcm-t1', false).tests.length > 0);
});

test('MCM migration preserves existing data and later team choices', () => {
  const state = makeSeed();
  state.demoTeamVersion = undefined;
  state.documents.find(d => d.id === 'd1').excerpt = 'Existing local review';
  state.threads['w1042:1'] = [{ content: 'Existing conversation' }];
  const counts = Object.fromEntries(['workspaces', 'documents', 'suites'].map(key => [key, state[key].length]));
  upgradeDemoState(state);
  assert.equal(state.session.team, 'MCM');
  assert.equal(state.documents.find(d => d.id === 'd1').excerpt, 'Existing local review');
  assert.equal(state.threads['w1042:1'][0].content, 'Existing conversation');
  for (const key of Object.keys(counts)) assert.equal(state[key].length, counts[key]);
  state.session.team = 'RMS';
  state.session.name = 'RMS Normal User';
  state.session.authenticated = true;
  state.audit.push({ id: 'legacy-user-label', actor: 'RMS Normal User', action: 'Signed in to RMS as Normal User' });
  upgradeDemoState(state);
  assert.equal(state.session.team, 'RMS');
  assert.equal(state.session.name, 'RMS User');
  assert.equal(state.session.authenticated, true);
  assert.equal(state.audit.at(-1).actor, 'RMS User');
  assert.equal(state.audit.at(-1).action, 'Signed in to RMS as User');
});

test('Membership is an alias of MCM and existing records retain their references', () => {
  const state = makeMcmSeed();
  state.teams.push('Membership');
  state.workspaces.push({ ...state.workspaces[0], id: 'membership-workspace', team: 'Membership', members: ['Membership Reviewer'] });
  state.documents.push({ ...state.documents[0], id: 'membership-source', team: 'Membership', sharedWith: ['Membership', 'MCM'] });
  state.shares.push({ id: 'membership-share', sourceId: 'membership-source', owner: 'Membership', consumer: 'RMS', status: 'Active' });
  state.session = { team: 'Membership', role: 'reviewer', name: 'Membership Reviewer' };
  delete state.accessModelVersion;
  state.activeWorkspaceId = 'membership-workspace';
  upgradeDemoState(state);
  assert.equal(state.teams.filter(t => t === 'MCM').length, 1);
  assert.ok(!state.teams.includes('Membership'));
  assert.equal(state.session.name, 'MCM User');
  assert.equal(state.activeWorkspaceId, 'membership-workspace');
  assert.equal(state.workspaces.find(w => w.id === 'membership-workspace').team, 'MCM');
  assert.deepEqual(state.documents.find(d => d.id === 'membership-source').sharedWith, ['MCM']);
  assert.equal(state.shares.find(g => g.id === 'membership-share').owner, 'MCM');
});

test('all application pages render their intended content', () => {
  const cases = [
    ['overview', 'Workspace overview'], ['workspaces', 'Your workspaces'], ['baselines', 'System Baselines'],
    ['workspace', 'Functional / Bug Information'], ['versions', 'Knowledge diff'], ['chat', 'Workspace chat'],
    ['readiness', 'Generate test cases'], ['suites', 'Accept scenario'], ['templates', 'Template library'],
    ['approvals', 'Exact manifest SHA-256'], ['graph', 'Interactive source-backed dependency graph'],
    ['admin', 'Configured teams'], ['login', 'Welcome back'],
  ];
  for (const [page, expected] of cases) {
    const state = makeSeed();
    if (page === 'admin') state.session.role = 'administrator';
    if (page === 'suites') state.activeWorkspaceId = 'w1051';
    globalThis.location = { hash: `#${page}` };
    globalThis.localStorage = { getItem: key => key === 'ccil-studio-demo-v1' ? JSON.stringify(state) : null };
    const html = renderToStaticMarkup(React.createElement(StoreProvider, null, React.createElement(App)));
    assert.ok(html.includes(expected), `${page} must render ${expected}`);
    assert.ok(!/Team Baseline|Demo role|Baseline Approver|Reviewer|Contributor|Frontend demo|Local frontend demo|One shared login for your team/.test(html), `${page} must use the clean shared team access model`);
    assert.ok(!html.includes('Planned for the complete frontend'), `${page} must not contain prototype placeholders`);
  }
});

test('application pages require the shared team sign-in form', () => {
  const state = makeMcmSeed();
  globalThis.location = { hash: '#overview' };
  globalThis.localStorage = { getItem: key => key === 'ccil-studio-demo-v1' ? JSON.stringify(state) : null };
  const html = renderToStaticMarkup(React.createElement(StoreProvider, null, React.createElement(App)));
  assert.ok(html.includes('System password'));
  assert.ok(!html.includes('Workspace overview'));
  assert.ok(!html.includes('Demo role'));
  assert.ok(!html.includes('Sample team passwords'));
  assert.ok(!html.includes('team-demo'));
  assert.ok(!html.includes('admin-demo'));
});

test('a newly configured team sees useful empty states on every page', () => {
  const state = makeSeed(); state.teams.push('New Team'); state.session = { team: 'New Team', role: 'user', name: 'New Team User', authenticated: true }; state.activeWorkspaceId = '';
  globalThis.localStorage = { getItem: key => key === 'ccil-studio-demo-v1' ? JSON.stringify(state) : null };
  for (const page of ['overview', 'workspaces', 'baselines', 'workspace', 'versions', 'chat', 'readiness', 'suites', 'templates', 'approvals', 'graph', 'admin']) {
    globalThis.location = { hash: `#${page}` };
    assert.doesNotThrow(() => renderToStaticMarkup(React.createElement(StoreProvider, null, React.createElement(App))), page);
  }
});

test('knowledge resolution rejects prerequisites, conflicts, and incorporated CRs', () => {
  const s = makeSeed();
  assert.ok(resolveSelection(s, 'b1', ['cr1068']).issues.some(i => i.includes('requires CR-1051')));
  assert.ok(resolveSelection(s, 'b1', ['cr1042', 'cr1073']).issues.some(i => i.includes('conflicts')));
  assert.ok(resolveSelection(s, 'b2', ['cr1042']).issues.some(i => i.includes('already incorporated')));
  assert.equal(resolveSelection(s, 'b1', ['cr1051', 'cr1068']).issues.length, 0);
});

test('partial replacement preserves unchanged knowledge and suppresses obsolete source text', () => {
  const s = makeSeed(), w = s.workspaces[0];
  s.questions.filter(q => q.workspaceId === w.id).forEach(q => { q.status = 'resolved'; q.answer = 'Approved sample behavior'; q.sourceReference = 'Sample contract revision 2.1'; });
  const suite = makeDemoSuite(s, w, 't1', false);
  assert.equal(suite.tests.find(t => t.requirement === 'VAL-002').expected, 'Reject a request with a missing required member identifier.');
  assert.ok(suite.tests.some(t => t.requirement === 'VAL-001'));
  assert.ok(suite.tests.some(t => t.requirement === 'VAL-003'));
  assert.ok(!eligibleDocuments(s, w).some(d => d.id === 'd2'));
});

test('REMOVE excludes deleted rules and their obsolete evidence from current generation', () => {
  const s = makeSeed(), w = s.workspaces[0]; w.crIds = ['cr1073'];
  s.questions = s.questions.filter(q => q.workspaceId !== w.id);
  const suite = makeDemoSuite(s, w, 't1', false);
  assert.ok(!suite.tests.some(t => t.requirement === 'VAL-002'));
  assert.ok(!eligibleDocuments(s, w).some(d => d.id === 'd2' || d.id === 'd3'));
});

test('open clarifications are optional and do not produce invented expected outcomes', () => {
  const s = makeSeed(), w = s.workspaces[0];
  const question = s.questions.find(q => q.workspaceId === w.id);
  for (let index = 0; index < 1000; index++) s.questions.push({ ...question, id: `optional-${index}` });
  assert.equal(readiness(s, w).ready, true);
  const suite = makeDemoSuite(s, w, 't1');
  assert.equal(suite.provisional, false); assert.equal(suite.status, 'Ready for review');
  assert.ok(suite.gaps.length >= 1000);
  assert.ok(suite.tests.every(test => test.expected !== 'Expected result unresolved' && test.sourceIds.length));
  w.baselineId = '';
  assert.throws(() => makeDemoSuite(s, w, 't1'), /active System Baseline/);
});

test('new installations start with no workspaces or baselines and retain default templates', () => {
  const state = makeFreshState();
  assert.equal(state.session.authenticated, false);
  assert.equal(state.workspaces.length, 0); assert.equal(state.baselines.length, 0);
  assert.ok(state.templates.some(template => template.team === 'MCM'));
});

test('baseline creation needs approval and only an Administrator can make it usable', async () => {
  const state = makeFreshState(); state.session = await authenticateTeam(state, 'MCM', 'team-demo');
  const workspace = { id: 'fresh-workspace', team: 'MCM', version: 1, baselineId: '', crIds: [], customRules: [], requirementCount: 0 };
  state.workspaces.push(workspace);
  const doc = { id: 'fresh-document', team: 'MCM', category: 0, name: 'source.md', revision: 1, checksum: 'abc' };
  const request = requestBaseline(state, { ref: 'Membership foundation' }, [doc], workspace.id);
  assert.equal(workspace.baselineId, ''); assert.equal(workspace.pendingBaselineId, request.baselineId);
  assert.ok(resolveSelection(state, request.baselineId, []).issues.length);
  assert.throws(() => decideBaseline(state, request.id, 'Approved'), /Only an Administrator/);
  state.session = await authenticateTeam(state, 'MCM', 'admin-demo');
  decideBaseline(state, request.id, 'Approved', 'Reviewed');
  assert.equal(workspace.baselineId, request.baselineId);
  assert.equal(state.baselines[0].status, 'Approved');
  assert.deepEqual(resolveSelection(state, request.baselineId, []).issues, []);
});

test('baseline edits add and remove documents only after approval, preserving the old version', async () => {
  const state = makeSeed(); state.session = await authenticateTeam(state, 'RMS', 'team-demo');
  const parent = state.baselines.find(item => item.id === 'b1'), workspace = state.workspaces[0], originalSources = [...parent.sourceIds];
  const addition = { id: 'new-source', team: 'RMS', name: 'revised.md', category: 1, revision: 1, checksum: 'new' };
  assert.throws(() => requestBaseline(state, { ref: parent.ref }, [], workspace.id, parent.id), /at least one/);
  const request = requestBaseline(state, { ref: parent.ref, description: 'Updated knowledge' }, [addition], workspace.id, parent.id);
  assert.equal(workspace.baselineId, parent.id); assert.deepEqual(parent.sourceIds, originalSources);
  state.session = await authenticateTeam(state, 'RMS', 'admin-demo');
  decideBaseline(state, request.id, 'Approved');
  assert.equal(workspace.baselineId, request.baselineId); assert.ok(workspace.version > 1);
  assert.deepEqual(parent.sourceIds, originalSources);
  assert.deepEqual(state.baselines.find(item => item.id === request.baselineId).sourceIds, ['new-source']);
  assert.throws(() => decideBaseline(state, request.id, 'Approved'), /already been decided/);
});

test('changed source revisions invalidate a pending baseline approval', async () => {
  const state = makeFreshState(); state.session = await authenticateTeam(state, 'MCM', 'team-demo');
  const request = requestBaseline(state, { ref: 'New baseline' }, [{ id: 'source', team: 'MCM', revision: 1, checksum: 'initial' }]);
  state.documents[0].checksum = 'changed'; state.session = await authenticateTeam(state, 'MCM', 'admin-demo');
  assert.throws(() => decideBaseline(state, request.id, 'Approved'), /changed or is unavailable/);
});

test('CR merges create a new baseline only after Administrator approval and retain the complete source set', async () => {
  const state = makeMcmSeed(); state.session = await authenticateTeam(state, 'MCM', 'team-demo');
  const workspace = state.workspaces.find(item => item.id === state.activeWorkspaceId);
  const parent = state.baselines.find(item => item.id === workspace.baselineId), original = structuredClone(parent), count = state.baselines.length;
  const contextDoc = { id: 'context-only', team: 'MCM', name: 'Business_context.md', revision: 1, status: 'Ready', checksum: 'context' };
  state.documents.push(contextDoc); parent.sourceIds.push(contextDoc.id); original.sourceIds.push(contextDoc.id);
  const request = requestBaselineMerge(state, workspace.id, 'MCM merged knowledge');
  assert.equal(state.baselines.length, count); assert.equal(workspace.baselineId, parent.id);
  assert.equal(request.status, 'Pending review'); assert.equal(request.type, 'changes');
  assert.throws(() => requestBaselineMerge(state, workspace.id, 'Duplicate request'), /pending baseline request/);
  assert.throws(() => decideBaseline(state, request.id, 'Approved'), /Only an Administrator/);
  state.session = await authenticateTeam(state, 'MCM', 'admin-demo');
  const created = decideBaseline(state, request.id, 'Approved', 'Reviewed CR sources', 'manifest-hash');
  assert.equal(state.baselines.length, count + 1); assert.equal(created.version, '2.0');
  assert.equal(created.parentId, parent.id); assert.equal(workspace.baselineId, created.id);
  assert.ok(created.sourceIds.includes(contextDoc.id));
  assert.ok(created.incorporatedCRs.includes('mcm-cr1042')); assert.deepEqual(workspace.crIds, []);
  assert.equal(created.rules.find(rule => rule.id === 'VAL-002').text, 'Reject a request with a missing required member identifier.');
  assert.equal(created.rules.find(rule => rule.id === 'VAL-001').text, original.rules.find(rule => rule.id === 'VAL-001').text);
  assert.deepEqual(parent, original);
});

test('pending CR merges reject source or CR revision changes and require reviewed selected evidence', async () => {
  const state = makeMcmSeed(); state.session = await authenticateTeam(state, 'MCM', 'team-demo');
  const workspace = state.workspaces.find(item => item.id === state.activeWorkspaceId);
  const source = state.documents.find(item => item.id === 'mcm-d3');
  source.status = 'Pending review';
  assert.throws(() => requestBaselineMerge(state, workspace.id, 'MCM merged knowledge'), /Review every selected/);
  source.status = 'Ready'; const request = requestBaselineMerge(state, workspace.id, 'MCM merged knowledge');
  source.revision += 1; state.session = await authenticateTeam(state, 'MCM', 'admin-demo');
  assert.throws(() => decideBaseline(state, request.id, 'Approved'), /document changed/);
  source.revision -= 1; state.crs.find(item => item.id === workspace.crIds[0]).revision += 1;
  assert.throws(() => decideBaseline(state, request.id, 'Approved'), /CR changed/);
});

test('template input validates headers, duplicates, invalid workbooks and file size', async () => {
  const imported = await readTemplate(new File(['Test ID,Title,Expected result\nTC-1,Accept member,Accepted'], 'format.csv'));
  assert.deepEqual(imported.fields, ['Test ID', 'Title', 'Expected result']);
  await assert.rejects(readTemplate(new File(['Title,title\nA,B'], 'duplicate.csv')), /unique name/);
  await assert.rejects(readTemplate(new File(['invalid'], 'invalid.xlsx')), /valid Excel/);
  await assert.rejects(readTemplate({ name: 'large.xlsx', size: 3 * 1024 * 1024 }), /smaller than 2 MB/);
});

test('Excel ZIP reader reads a real compressed workbook fixture', async () => {
  const workbook = await readFile(new URL('./fixtures/Membership_Test_Template.xlsx', import.meta.url));
  const zip = await readZip(workbook.buffer.slice(workbook.byteOffset, workbook.byteOffset + workbook.byteLength));
  assert.ok((await zip.get('xl/workbook.xml')()).includes('name="Test cases"'));
  const sheet = await zip.get('xl/worksheets/sheet1.xml')();
  assert.ok(sheet.includes('Expected result')); assert.ok(sheet.includes('Validate active member'));
});

test('version changes reset clarification readiness and preserve historic chat context', () => {
  const s = makeSeed(), w = s.workspaces[0], oldKey = contextKey(w);
  s.threads[oldKey] = { workspaceId: w.id, version: 1, messages: [{ content: 'Historic evidence' }] };
  s.questions.filter(q => q.workspaceId === w.id).forEach(q => { q.status = 'resolved'; q.answer = 'Old answer'; });
  bumpVersion(s, w);
  assert.notEqual(contextKey(w), oldKey);
  assert.equal(s.threads[oldKey].messages[0].content, 'Historic evidence');
  assert.equal(s.threads[contextKey(w)], undefined);
  const current = s.questions.filter(q => q.workspaceId === w.id && q.version === w.version);
  assert.equal(current.length, 2); assert.ok(current.every(q => q.status === 'open' && q.answer === ''));
});

test('revoked shared contracts leave scope and block generation', () => {
  const s = makeSeed(), w = s.workspaces[0];
  s.questions.filter(q => q.workspaceId === w.id).forEach(q => { q.status = 'resolved'; q.answer = 'Reviewed'; });
  assert.ok(eligibleDocuments(s, w).some(d => d.id === 'dshared'));
  s.shares[0].status = 'Revoked';
  assert.ok(!eligibleDocuments(s, w).some(d => d.id === 'dshared'));
  assert.equal(readiness(s, w).ready, false);
});

test('CSV round-trips quotes and multiline cells and neutralizes spreadsheet formulas', () => {
  const text = csv([['Title', 'Expected result'], ['A "quoted" title', 'Two\nlines'], ['=SUM(A1:A2)', 'literal']]);
  const rows = parseCsv(text);
  assert.equal(rows[1][0], 'A "quoted" title'); assert.equal(rows[1][1], 'Two\nlines');
  assert.equal(rows[2][0], "'=SUM(A1:A2)");
  assert.throws(() => parseCsv('"Unclosed'), /unclosed/);
});

test('selected templates retain immutable field snapshots and custom fields', () => {
  const s = makeSeed(), w = s.workspaces.find(w => w.id === 'w1051');
  s.templates[0].fields.push('Review batch');
  const suite = makeDemoSuite(s, w, 't1', false);
  assert.equal(suite.tests[0].customFields['Review batch'], '');
  s.templates[0].fields.push('Later field');
  assert.ok(!suite.templateSnapshot.fields.includes('Later field'));
  s.templates[0].visibility = 'workspace'; s.templates[0].workspaceId = 'w1042';
  assert.throws(() => makeDemoSuite(s, w, 't1', false), /accessible team template/);
});

Enter fullscreen mode Exit fullscreen mode

Top comments (0)