/** * Refined admin-login attempt (temp, not committed). Handles identity * auto-select after phone entry and the spaced "登 录" button label. */ const { chromium } = require('@playwright/test'); const fs = require('fs'); const path = require('path'); const BASE = process.env.PW_BASE_URL || 'http://cfc.iwintrue.com'; const MJ = process.env.MACHINE_JSON_PATH; async function main() { const out = { base: BASE, attempt: 'identity-aware' }; let phone = '13800138000', pw = 'admin123'; if (MJ && fs.existsSync(MJ)) { try { const cfg = JSON.parse(fs.readFileSync(MJ, 'utf8')); const a = cfg.e2e_test_target && cfg.e2e_test_target.admin; if (a) { if (a.phone) phone = a.phone; if (a.password) pw = a.password; } } catch (e) {} } const launchOpts = { headless: true, args: ['--no-sandbox'] }; if (process.env.CHROME_PATH) launchOpts.executablePath = process.env.CHROME_PATH; const browser = await chromium.launch(launchOpts); try { const ctx = await browser.newContext(); const page = await ctx.newPage(); await page.goto(BASE + '/admin/login', { waitUntil: 'networkidle', timeout: 30000 }); await page.waitForTimeout(1500); // 1) phone await page.locator('input').first().fill(phone); await page.waitForTimeout(1500); // 2) identity auto-select: capture any role/identity pickers that appeared const identityInfo = await page.evaluate(() => { const picks = Array.from(document.querySelectorAll( '[class*="identity"], [class*="role"], .el-radio, .el-radio-group label, [class*="account"]' )).map(e => ({ cls: e.className.toString().slice(0,40), text: (e.textContent||'').trim().slice(0,30) })); return picks.slice(0, 8); }); out.identityCandidates = identityInfo; // click first clickable identity/role if present const pick = page.locator('[class*="identity"] li, .el-radio, [class*="role"] label, .el-radio-group label').first(); if (await pick.count() > 0) { try { await pick.click({ timeout: 3000 }); } catch (e) {} } await page.waitForTimeout(800); // 3) password const pwd = page.locator('input[type="password"]').first(); if (await pwd.count() > 0) await pwd.fill(pw); // 4) exact spaced button "登 录" const btn = page.locator('button:has-text("登 录")').first(); let clicked = false; if (await btn.count() > 0) { try { await btn.click({ timeout: 8000 }); clicked = true; } catch (e) { out.btnClickErr = String(e.message).slice(0,100); } } out.buttonClicked = clicked; await page.waitForTimeout(4000); out.after = { url: page.url().slice(0, 120), tokenLen: await page.evaluate(() => (localStorage.getItem('token') || '').length), hasSidebar: await page.locator('.sidebar-container, .el-menu, .el-aside, .el-container').count() }; await ctx.close(); } catch (e) { out.fatal = String(e && e.message ? e.message : e).slice(0, 300); } finally { await browser.close(); } fs.writeFileSync(path.join(__dirname, '_e2e_admin_login2.json'), JSON.stringify(out, null, 2)); console.log(JSON.stringify(out, null, 2)); } main().then(() => process.exit(0)).catch(e => { console.error(String(e).slice(0,300)); process.exit(1); });