68 lines
4.7 KiB
JavaScript
68 lines
4.7 KiB
JavaScript
// Browser checks run only against the isolated SLICE13 test host.
|
|
import {chromium,expect} from '@playwright/test';
|
|
import fs from 'node:fs/promises';
|
|
const [host,port,phase]=process.argv.slice(2);
|
|
if(!/^conductor-slice13-[a-f0-9]{10}$/.test(host)||!/^\d+$/.test(port)||!['seed','legacy','upgraded'].includes(phase))throw Error('Disposable upgrade fixture required.');
|
|
const dir='test-results/slice13',base='https://conductor.customer.test:'+port;
|
|
const browser=await chromium.launch({headless:true,args:['--host-resolver-rules=MAP conductor.customer.test 127.0.0.1','--no-proxy-server']});
|
|
let page;
|
|
try{
|
|
const context=await browser.newContext({baseURL:base,ignoreHTTPSErrors:true,viewport:{width:1400,height:1000}});
|
|
page=await context.newPage();
|
|
await page.goto('/');
|
|
await expect(page.getByLabel('Username',{exact:true})).toBeVisible();
|
|
const request=async(method,url,options={})=>{
|
|
const value=await page.evaluate(async({method,url,data,headers})=>{
|
|
const response=await fetch(url,{method,headers:{...(data?{'Content-Type':'application/json'}:{}),...headers},body:data?JSON.stringify(data):undefined});
|
|
return {status:response.status,body:await response.json()};
|
|
},{method,url,...options});
|
|
return {status:()=>value.status,json:async()=>value.body};
|
|
};
|
|
let auth;
|
|
if(phase==='seed'){
|
|
const setup=await request('GET','/api/auth/setup');
|
|
auth=await request('POST','/api/auth/setup',{headers:{'X-Setup-Token':(await setup.json()).setupToken},data:{username:'customer-admin',password:'disposable-upgrade-password',displayName:'Customer Administrator'}});
|
|
expect(auth.status()).toBe(201);
|
|
}else{
|
|
auth=await request('POST','/api/auth/login',{data:{username:'customer-admin',password:'disposable-upgrade-password'}});
|
|
expect(auth.status()).toBe(200);
|
|
}
|
|
const csrf=(await auth.json()).csrfToken;
|
|
if(phase==='seed'){
|
|
const project=await request('POST','/api/projects',{headers:{'X-CSRF-Token':csrf},data:{name:'Customer project',description:'Preserve my saved work.'}});
|
|
expect(project.status()).toBe(201);
|
|
const publication=await request('POST','/api/admin/published-apps',{headers:{'X-CSRF-Token':csrf},data:{sourceProjectId:(await project.json()).id,slug:'customer-app',displayName:'Customer publication',visibility:'authenticated'}});
|
|
expect(publication.status()).toBe(201);
|
|
}
|
|
const projects=await (await request('GET','/api/projects')).json();
|
|
expect(projects).toHaveLength(1);expect(projects[0].name).toBe('Customer project');
|
|
const published=await (await request('GET','/api/admin/published-apps')).json();
|
|
expect(published).toHaveLength(1);expect(published[0].slug).toBe('customer-app');
|
|
expect(published[0].version).toBe(1);
|
|
const session=await request('GET','/api/social-scheduler/session');
|
|
expect(session.status()).toBe(200);expect((await session.json()).role).toBe('admin');
|
|
const snapshot=await (await request('GET','/api/social-scheduler/workspaces/customer')).json();
|
|
expect(snapshot.accounts[0].handle).toBe('customer.bsky.social');
|
|
expect(snapshot.posts[0].text).toBe('Scheduled before the Conductor upgrade.');
|
|
const errors=[];page.on('pageerror',e=>errors.push(e.message));
|
|
await page.goto('/');await page.getByRole('navigation').getByRole('button',{name:'Publishing',exact:true}).click();
|
|
await expect(page.getByRole('heading',{name:'Social Scheduler',exact:true})).toHaveCount(1);
|
|
await page.screenshot({path:dir+'/'+phase+'-publishing.png',fullPage:true});
|
|
await page.getByRole('link',{name:'Open Social Scheduler',exact:true}).click();
|
|
await expect(page.getByRole('heading',{name:'Compose a post',exact:true})).toBeVisible();
|
|
await expect(page.getByText('Scheduled before the Conductor upgrade.',{exact:true}).first()).toBeVisible();
|
|
if(phase==='upgraded'){
|
|
await expect(page).toHaveTitle('Social Scheduler · Conductor');
|
|
await expect(page.locator('#conductor-favicon')).toHaveAttribute('href','/favicon.svg');
|
|
}
|
|
await page.screenshot({path:dir+'/'+phase+'-social.png',fullPage:true});
|
|
await page.goto('/apps/customer-app');
|
|
await expect(page.getByText('Customer publication',{exact:true}).first()).toBeVisible();
|
|
expect(errors).toEqual([]);
|
|
await fs.writeFile(dir+'/'+phase+'-browser.json',JSON.stringify({passed:true,phase,checks:['same administrator password','saved project','unchanged published snapshot/version','existing social connection','existing queued post','authenticated API bridge','single included-app card','real Social Scheduler screen',...(phase==='upgraded'?['app browser title','default favicon']:[])]},null,2));
|
|
console.log('PASS: '+phase+' browser login, project/publication, app screen and existing connection/queue.');
|
|
}catch(error){
|
|
if(page)await page.screenshot({path:dir+'/'+phase+'-failure.png',fullPage:true}).catch(()=>{});
|
|
throw error;
|
|
}finally{await browser.close();}
|