gaoluyang
15 小时以前 cd8b52bdf89a4d1101f72e0ece9f4df22a3d3f7a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Real user dropdown, confirmation and router; all APIs simulated.
const assert=require('node:assert/strict'),fs=require('fs'),path=require('path');
const {chromium}=require('C:/Users/云/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright');
(async()=>{
 const server=await(await import('vite')).createServer({root:path.resolve(__dirname,'..'),server:{host:'127.0.0.1',port:5183}});await server.listen();
 const browser=await chromium.launch({headless:true,executablePath:'C:/Program Files/Google/Chrome/Application/chrome.exe'});
 const page=await browser.newPage({viewport:{width:1440,height:950},reducedMotion:'reduce'});const errors=[];let logoutCalls=0;let releaseLogout;let logoutHeader;
 page.on('pageerror',e=>errors.push(e.message));
 await page.route('**/admin-api/**',async route=>{
   const url=route.request().url();
   if(url.includes('/system/auth/logout')){logoutCalls++;logoutHeader=route.request().headers().authorization;await new Promise(r=>releaseLogout=r);}
   const data=url.includes('company-config')?{companyName:'退出验证平台'}:url.includes('count')?0:url.includes('list')?[]:null;
   await route.fulfill({contentType:'application/json',body:JSON.stringify({code:0,data,msg:''})}).catch(()=>{});
 });
 try{
  await page.goto('http://127.0.0.1:5183/auth/login',{waitUntil:'domcontentloaded'});await page.getByRole('heading',{name:'欢迎回来'}).waitFor();
  await page.waitForFunction(()=>!document.querySelector('#__app-loading__')||getComputedStyle(document.querySelector('#__app-loading__')).opacity==='0');
  await page.evaluate(async()=>{
   const stores=await import('/src/packages/stores/src/index.ts'),{router}=await import('/src/router/index.ts'),{h}=await import('/node_modules/.vite/deps/vue.js');
   stores.useAccessStore().setAccessToken('qa-session-token');stores.useAccessStore().setRefreshToken('qa-refresh-token');stores.useAccessStore().setIsAccessChecked(true);
   stores.useUserStore().setUserInfo({userId:'1',username:'logout-qa',nickname:'退出验证用户',avatar:''});
   router.addRoute('Root',{name:'LogoutQa',path:'/qa-logout-session',meta:{title:'退出验证工作区'},component:{render(){return h('div','退出验证工作区')}}});
   await router.push('/qa-logout-session');
  });
  await page.locator('[id="__vben_main_content"]').getByText('退出验证工作区',{exact:true}).waitFor({timeout:60000});
  const avatars=page.locator('button[aria-haspopup="menu"]').filter({has:page.locator('.size-8')}).first();
  await avatars.click();
  await page.getByRole('menuitem',{name:/退出登录/}).click();
  const dialog=page.getByRole('dialog');await dialog.waitFor();
  const started=Date.now();await dialog.getByRole('button',{name:/^确\s*[认定]$/}).click();
  await page.waitForURL('**/auth/login',{timeout:5000});await page.getByRole('heading',{name:'欢迎回来'}).waitFor();
  const elapsed=Date.now()-started;
  const state=await page.evaluate(async()=>{const s=await import('/src/packages/stores/src/index.ts');return{access:s.useAccessStore().accessToken,refresh:s.useAccessStore().refreshToken,user:s.useUserStore().userInfo}});
  assert.equal(state.access,null);assert.equal(state.refresh,null);assert.equal(state.user,null);
  assert.equal(logoutCalls,1);assert.equal(logoutHeader,'Bearer qa-session-token');assert.equal(typeof releaseLogout,'function','Server logout must still be pending when login page appears');
  releaseLogout();await page.waitForTimeout(100);
  const result={passed:true,scope:'Real application user dropdown, confirmation, stores and routing; simulated authenticated session and pending backend, no real account login',checks:['click logout and confirm','navigate without refresh while server pending','access and refresh token cleared','user info cleared','server revoke uses original token'],elapsedMs:elapsed,errors};
  assert.deepEqual(errors,[]);
  const out=path.resolve(__dirname,'../../scripts/logout-fix-20261015');fs.mkdirSync(out,{recursive:true});fs.writeFileSync(path.join(out,'browser-result.json'),JSON.stringify(result,null,2));console.log(JSON.stringify(result));
 }catch(error){console.error(JSON.stringify({message:error.message,errors,body:(await page.locator('body').innerText()).slice(0,1800)}));throw error;}
 finally{releaseLogout?.();await browser.close();await server.close();}
})();