const assert=require('assert'),{createHarness,settle}=require('./harness.cjs') async function render(h,name='shareCard'){const page=h.page(name);page.hook('onReady');await page.startSharing();return page} ;(async()=>{ const h=createHarness(),first=await render(h);assert(first.poster&&first.cached) const original=first.poster h.state.profile.nickname='修改后的合成昵称' const changed=await render(h);assert(changed.cached&&changed.poster!==original);assert(!h.files.has(original),'obsolete cached image must be removed') h.files.delete(changed.cover);const missing=await render(h);assert(missing.poster!==changed.poster,'missing file must regenerate') h.storage.set('token','synthetic-other-token');h.storage.set('user_id',43);h.state.profile.id=43 const other=await render(h);assert(other.poster.includes('-43-personal-'));assert(!other.poster.includes('-42-personal-')) const index=h.storage.get('fulian-sharing-cache-v5');index['43-personal'].savedAt=Date.now()-2*24*3600*1000;h.storage.set('fulian-sharing-cache-v5',index) const expired=await render(h);assert(expired.poster!==other.poster) h.flags.copyFail=true;const disk=await render(h,'myShare');assert(disk.poster&&!disk.cached);assert(!disk.generating) for(const flag of ['imageInfoHang','imageHang','canvasHang','exportHang','requestHang']){ const broken=createHarness();broken.flags[flag]=true const page=await render(broken) await settle(()=>!page.generating&&!page.profileLoading,flag) assert(page.posterError||page.profileError,'missing callbacks must end in an error: '+flag) } const independent=createHarness();independent.flags.route=options=>options.url.endsWith('/invitees')?'hang':null const invitation=independent.page('myShare');invitation.hook('onLoad');invitation.hook('onReady') await settle(()=>invitation.poster&&!invitation.generating,'independent invitation poster');assert(invitation.poster) const cancel=createHarness(),leave=cancel.page('shareCard');leave.hook('onReady');const work=leave.startSharing();leave.hook('onUnload');await work;assert(!leave.poster) console.log('PASS: profile invalidation, missing cache, account isolation, TTL, full-disk fallback, image/canvas/export/request timeouts, independent pagination and unload cancellation.') })().catch(error=>{console.error(error.stack);process.exitCode=1})