81 lines
6.7 KiB
JavaScript
81 lines
6.7 KiB
JavaScript
// Exercises actual PeerFiles, dashboard wrapper, shared styles and fade directive.
|
|
// Synthetic catalog only; no live app, wallet, payment or node requests.
|
|
const { chromium, expect } = require('../../neode-ui/node_modules/@playwright/test');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const base = process.env.PEER_SCROLL_TEST_URL || 'http://127.0.0.1:5198';
|
|
const output = process.env.PEER_SCROLL_EVIDENCE || '/tmp/archy-peer-scroll';
|
|
fs.mkdirSync(output, {recursive:true,mode:0o700});
|
|
const peer = 'a'.repeat(56) + '.onion';
|
|
(async()=>{
|
|
// Vite resolves dependency URLs for this exact checkout.
|
|
const source = await fetch(base+'/src/stores/resources.ts').then(r=>r.text());
|
|
const vue = source.match(/from "([^"]*\/vue\.js[^" ]*)"/)[1];
|
|
const peerSource = await fetch(base+'/src/views/PeerFiles.vue').then(r=>r.text());
|
|
const routerUrl = peerSource.match(/from "([^"]*vue-router\.js[^" ]*)"/)[1];
|
|
const pinia = source.match(/from "([^"]*pinia[^" ]*\.js[^" ]*)"/)[1];
|
|
const browser = await chromium.launch({headless:true});
|
|
const results=[];
|
|
try {
|
|
for (const width of [390,844,1440]) {
|
|
const page = await browser.newPage({viewport:{width,height:900},hasTouch:width<1000});
|
|
const errors=[];page.on('pageerror',e=>{errors.push(e.message);console.error('PAGE',e.message)});
|
|
page.on('console',m=>{if(m.type()==='error')console.error('CONSOLE',m.text())});
|
|
await page.route('**/peer-scroll-fixture',route=>route.fulfill({contentType:'text/html',body:`<!doctype html><meta name="viewport" content="width=device-width,initial-scale=1"><div id="fixture"></div><script type="module">
|
|
import {createApp,h} from '${vue}';
|
|
import {createPinia} from '${pinia}';
|
|
import {createRouter,createMemoryHistory} from '${routerUrl}';
|
|
import PeerFiles from '/src/views/PeerFiles.vue';
|
|
import {wrapperFor} from '/src/views/dashboard/dashboardViewWrappers.ts';
|
|
import {rpcClient} from '/src/api/rpc-client.ts';
|
|
import '/src/style.css';import '/src/views/dashboard/dashboard-styles.css';
|
|
const peer=${JSON.stringify(peer)};
|
|
const items=Array.from({length:48},(_,i)=>({id:'fixture-'+i,filename:'Shared document '+String(i+1).padStart(2,'0')+'.txt',mime_type:'text/plain',size_bytes:1024,description:'Shared file fixture',access:'free'}));
|
|
rpcClient.federationListNodes=async()=>({nodes:[{did:'did:key:fixture-peer',pubkey:'fixture',onion:peer,name:'Peer file library',trust_level:'trusted'}]});
|
|
rpcClient.call=async({method})=>{if(method==='content.browse-peer')return {items,transport:'fips'};if(method==='content.list-owned')return {items:[]};throw Error('Unexpected fixture RPC: '+method)};
|
|
const router=createRouter({history:createMemoryHistory(),routes:[{path:'/dashboard/cloud',name:'cloud',component:{render:()=>null}},{path:'/dashboard/federation',name:'federation',component:{render:()=>null}}]});
|
|
await router.push('/dashboard/cloud');
|
|
const Wrapper=wrapperFor('/dashboard/cloud/peers/'+peer);
|
|
createApp({render:()=>h('div',{class:'dashboard-view',style:'height:100dvh;position:relative'},[h('div',{class:'perspective-container-wrapper'},[h('div',{class:'perspective-container'},[h(Wrapper,{mobileTabPaddingTop:width<768?64:null,needsMobileBackButtonSpace:true},{default:()=>h(PeerFiles,{peerId:peer,class:'view-container flex-none'})})])])])}).use(createPinia()).use(router).mount('#fixture');
|
|
window.fixtureReady=true;
|
|
</script>`.replace('width<768',`${width}<768`)}));
|
|
// Every HTTP request stays on the fixture Vite origin.
|
|
await page.route('**/*',route=>{
|
|
if(new URL(route.request().url()).origin!==base)return route.abort();
|
|
return route.fallback();
|
|
});
|
|
await page.goto(base+'/peer-scroll-fixture');
|
|
await page.waitForSelector('.peer-files-scroll .glass-card',{timeout:45000});
|
|
const scroll=page.locator('.peer-files-scroll');
|
|
const header=page.locator('.peer-files-identity');
|
|
const back=page.getByRole('button',{name:'Back to Cloud',exact:true}).filter({visible:true});
|
|
await expect(back).toBeVisible();
|
|
const before=await header.boundingBox();const beforeBack=await back.boundingBox();
|
|
const initial=await scroll.evaluate(el=>({height:el.clientHeight,content:el.scrollHeight,mask:el.style.maskImage,outer:el.closest('.dashboard-scroll-panel').scrollTop}));
|
|
if(initial.height<160||initial.content<=initial.height)throw Error('Missing constrained scrolling viewport '+JSON.stringify(initial));
|
|
if(!initial.mask.includes('black 0px')||!initial.mask.includes('18px'))throw Error('Initial bottom fade absent');
|
|
await scroll.evaluate(el=>{el.scrollTop=350;el.dispatchEvent(new Event('scroll'))});
|
|
await page.waitForTimeout(100);
|
|
const after=await header.boundingBox();const afterBack=await back.boundingBox();
|
|
for(const key of ['x','y','width','height']){
|
|
if(Math.abs(before[key]-after[key])>1)throw Error('Header moved: '+key);
|
|
if(Math.abs(beforeBack[key]-afterBack[key])>1)throw Error('Back button moved: '+key);
|
|
}
|
|
const mid=await scroll.evaluate(el=>({top:el.scrollTop,mask:el.style.maskImage,outer:el.closest('.dashboard-scroll-panel').scrollTop,rect:el.getBoundingClientRect().toJSON()}));
|
|
if(mid.top<300||mid.outer!==initial.outer||!mid.mask.includes('black 18px'))throw Error('Wrong scroll ownership or top fade');
|
|
await page.screenshot({path:path.join(output,`peer-scroll-${width}.png`)});
|
|
await scroll.evaluate(el=>{el.scrollTop=el.scrollHeight;el.dispatchEvent(new Event('scroll'))});
|
|
const last=await scroll.evaluate(el=>({mask:el.style.maskImage,remaining:el.scrollHeight-el.clientHeight-el.scrollTop}));
|
|
if(last.remaining>1||!/100% [+-] 0px/.test(last.mask))throw Error('Bottom fade not cleared at end '+JSON.stringify(last));
|
|
const isolation=await page.evaluate(()=>{const panel=document.createElement('div');panel.className='dashboard-scroll-panel';panel.style.overflowY='auto';panel.innerHTML='<div class=unrelated-page></div>';document.body.append(panel);const value=getComputedStyle(panel).overflowY;panel.remove();return value});
|
|
if(isolation!=='auto')throw Error('Unrelated page scroll changed');
|
|
const horizontal=await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth);
|
|
if(horizontal)throw Error('Horizontal overflow');
|
|
if(errors.length)throw Error(errors.join('\n'));
|
|
results.push({width,height:900,passed:true,initial,mid,last,header:after,back:afterBack});
|
|
await page.close();
|
|
}
|
|
} finally {await browser.close();fs.writeFileSync(path.join(output,'result.json'),JSON.stringify(results,null,2));}
|
|
console.log(JSON.stringify({passed:true,viewports:results.map(r=>r.width),evidence:output}));
|
|
})().catch(e=>{console.error(e);process.exitCode=1});
|