informed-decision/tests/browser_review.mjs

118 lines
7.6 KiB
JavaScript
Raw Permalink Normal View History

// Automated browser contract exercise. All identities and grants are synthetic.
import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import path from 'node:path';
import {createRequire} from 'node:module';
const require=createRequire(import.meta.url);
const {chromium}=require(process.env.INFD_PLAYWRIGHT_PACKAGE || 'playwright');
const directory=process.argv[2];
const fixture=JSON.parse(await fs.readFile(path.join(directory,'server.json'),'utf8'));
const checks=[];
const browser=await chromium.launch({headless:true,executablePath:process.env.INFD_CHROMIUM_EXECUTABLE,args:[
'--no-proxy-server',
'--host-resolver-rules=MAP decisions.coulomb.social 127.0.0.1, MAP keycape.test 127.0.0.1',
'--ignore-certificate-errors-spki-list='+fixture.certificate_spki
]});
const context=await browser.newContext({viewport:{width:1360,height:1000},acceptDownloads:true});
const errors=[];
const navigation=[];
const formOrigins=[];
try {
// Both test names resolve to the disposable HTTPS server. All redirects,
// browser cookies and form Origins travel through real HTTP/TLS. Only this
// fixture certificate's public key is trusted by the browser override.
const page=await context.newPage();page.setDefaultTimeout(10000);
page.on('pageerror',error=>errors.push(String(error)));
page.on('request',request=>{if(request.method()==='POST')formOrigins.push({
path:new URL(request.url()).pathname,origin:request.headers().origin || null});});
page.on('response',response=>navigation.push({path:new URL(response.url()).pathname,status:response.status()}));
page.on('dialog',async dialog=>{errors.push('Unexpected script dialog');await dialog.dismiss();});
await page.goto(fixture.public_origin+'/');
await page.getByRole('link',{name:'Sign in with KeyCape'}).click();
await page.getByRole('heading',{name:'Open a decision review'}).waitFor({timeout:10000});
const cookies=await context.cookies();
const session=cookies.find(c=>c.name==='__Host-infd-session');
assert(session?.secure && session?.httpOnly && session?.sameSite==='Lax');
checks.push('PKCE callback and secure browser session');
await page.getByLabel('Memo identifier').fill(fixture.memo_id);
await page.getByRole('button',{name:'Open review',exact:true}).click();
await page.getByRole('heading',{name:'The request',exact:true}).waitFor();
const accept=()=>page.getByRole('button',{name:'Accept the complete request',exact:true});
assert(await accept().isDisabled());
assert.equal(await page.locator('img,script').count(),0);
await page.screenshot({path:path.join(directory,'review-desktop.png'),fullPage:true});
checks.push('Entitled page escapes memo and packet markup');
await accept().evaluate(button=>button.disabled=false);
await accept().click();
await page.getByText('Record all required highlight acknowledgments before accepting or declining.').waitFor();
let state=await (await fetch(fixture.origin+'/_fixture/status')).json();
assert.equal(state.entries,0);assert.equal(state.entry_posts,0);
checks.push('Server refuses bypass of missing acknowledgments');
await page.goBack();
await page.getByLabel('I have reviewed this highlight').check();
await page.getByRole('button',{name:'Record acknowledgments',exact:true}).click();
assert(await accept().isEnabled());
checks.push('Explicit acknowledgment unlocks the form');
await page.locator('summary').filter({hasText:'Whole fixture document'}).click();
const [download]=await Promise.all([
page.waitForEvent('download'),page.getByRole('link',{name:'Download complete document',exact:true}).click()
]);
const bytes=await fs.readFile(await download.path());
assert(bytes.includes(Buffer.from('Full fixture terms.')));
checks.push('Complete attachment download stays behind entitlement');
await page.locator('summary').filter({hasText:'Return for improvement'}).click();
const returned=page.locator('form').filter({has:page.locator('select[name="reason"]')});
await returned.locator('select').selectOption('clarification_needed');
await returned.locator('textarea').fill('Synthetic browser return: clarify the fixture scope.');
await returned.getByRole('button',{name:'Return for improvement',exact:true}).click();
await page.getByText('Synthetic browser return: clarify the fixture scope.').waitFor();
state=await (await fetch(fixture.origin+'/_fixture/status')).json();assert.equal(state.entries,0);
checks.push('Return records a memo response without an engine entry');
await page.setViewportSize({width:390,height:844});
assert(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth+1));
await page.screenshot({path:path.join(directory,'review-mobile.png'),fullPage:true});
checks.push('Mobile review fits the viewport');
await page.setViewportSize({width:1360,height:1000});
await accept().click();
await page.getByText('Approval entry recorded.',{exact:true}).waitFor();
assert.equal(await page.getByRole('button',{name:'Accept the complete request',exact:true}).count(),0);
await page.screenshot({path:path.join(directory,'recorded-desktop.png'),fullPage:true});
await page.reload();await page.getByText('Approval entry recorded.',{exact:true}).waitFor();
state=await (await fetch(fixture.origin+'/_fixture/status')).json();
assert.equal(state.entries,1);assert.equal(state.entry_posts,1);assert.equal(state.consume_calls,0);
assert(state.outbox_states.every(s=>s==='delivered'));
assert(state.decision_attributable.every(value=>value===0));
checks.push('One actual approval entry, stable on browser reload');
checks.push('Audit receiver holds all commitments; unsigned decision gap retained');
await fetch(fixture.origin+'/_fixture/refuse-caller');
await page.reload();await page.getByRole('heading',{name:'Review unavailable'}).waitFor();
assert(!(await page.content()).includes('private-brief-sentinel'));
state=await (await fetch(fixture.origin+'/_fixture/status')).json();
assert.equal(state.policy_outcomes.at(-1),'caller_refused');assert.equal(state.entries,1);
checks.push('Real workload caller refusal hides review content');
await page.goto(fixture.public_origin+'/');
await page.getByRole('button',{name:'Sign out',exact:true}).click();
await page.getByRole('link',{name:'Sign in with KeyCape'}).waitFor();
assert(!(await context.cookies()).some(c=>c.name==='__Host-infd-session'));
assert(formOrigins.every(form=>form.origin===fixture.public_origin));
checks.push('Sign-out clears the session; all forms carry the exact origin');
assert.deepEqual(errors,[]);
checks.push('No page errors or injected script execution');
const receipt={fixture_only:true,browser:'Chromium',checks_passed:checks.length,checks,
fixture_transport:'real HTTPS on ephemeral ports; synthetic issuer and TokenReview',
native_human_login_proven:false,native_policy_admitted:false,factory_attempts:0,paid_model_calls:0,
final_component_state:state};
await fs.writeFile(path.join(directory,'browser-result.json'),JSON.stringify(receipt,null,2)+'\n');
process.stdout.write(JSON.stringify({checks_passed:checks.length,entries:state.entries,entry_posts:state.entry_posts,fixture_only:true})+'\n');
} finally {
if(checks.length<12 && context.pages()[0]) {
const page=context.pages()[0], url=new URL(page.url());
await fs.writeFile(path.join(directory,'browser-debug.json'),JSON.stringify({
path:url.pathname,body:await page.locator('body').innerText(),navigation,formOrigins,
cookie_names:(await context.cookies()).map(c=>c.name),errors},null,2));
await page.screenshot({path:path.join(directory,'browser-debug.png'),fullPage:true});
}
await browser.close();
await fetch(fixture.origin+'/_fixture/stop').catch(()=>{});
}