_e2e_admin_debug.cjs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /**
  2. * Temporary admin-login diagnostic (NOT committed). Classifies why /admin
  3. * login returned no token: credential rejection vs selector mismatch.
  4. * Credentials read from local machine.json; never printed.
  5. */
  6. const { chromium } = require('@playwright/test');
  7. const fs = require('fs');
  8. const path = require('path');
  9. const BASE = process.env.PW_BASE_URL || 'http://cfc.iwintrue.com';
  10. const MJ = process.env.MACHINE_JSON_PATH;
  11. async function main() {
  12. const out = { base: BASE, steps: {} };
  13. let admin = { phone: '13800138000' };
  14. let pw = 'admin123';
  15. if (MJ && fs.existsSync(MJ)) {
  16. try {
  17. const cfg = JSON.parse(fs.readFileSync(MJ, 'utf8'));
  18. if (cfg.e2e_test_target && cfg.e2e_test_target.admin) {
  19. if (cfg.e2e_test_target.admin.phone) admin.phone = cfg.e2e_test_target.admin.phone;
  20. if (cfg.e2e_test_target.admin.password) pw = cfg.e2e_test_target.admin.password;
  21. }
  22. } catch (e) {}
  23. }
  24. const launchOpts = { headless: true, args: ['--no-sandbox'] };
  25. if (process.env.CHROME_PATH) launchOpts.executablePath = process.env.CHROME_PATH;
  26. const browser = await chromium.launch(launchOpts);
  27. try {
  28. const ctx = await browser.newContext();
  29. const page = await ctx.newPage();
  30. const resp = await page.goto(BASE + '/admin/login', { waitUntil: 'networkidle', timeout: 30000 });
  31. await page.waitForTimeout(2000);
  32. out.steps.loginPage = {
  33. status: resp ? resp.status() : null,
  34. url: page.url().slice(0, 120),
  35. title: String(await page.title()).slice(0, 80)
  36. };
  37. // Inventory inputs & buttons (safe DOM metadata only)
  38. out.steps.dom = await page.evaluate(() => {
  39. const inputs = Array.from(document.querySelectorAll('input')).map(i => ({
  40. type: i.type || i.getAttribute('type'),
  41. placeholder: i.placeholder || '',
  42. name: i.name || ''
  43. }));
  44. const buttons = Array.from(document.querySelectorAll('button')).map(b => (b.textContent || '').trim().slice(0, 20));
  45. return { inputCount: inputs.length, inputs, buttonTexts: buttons.slice(0, 10) };
  46. });
  47. // Attempt fill + submit
  48. const phoneIn = page.locator('input').first();
  49. if (await phoneIn.count() > 0) await phoneIn.fill(admin.phone);
  50. const pwdIn = page.locator('input[type="password"]').first();
  51. if (await pwdIn.count() > 0) await pwdIn.fill(pw);
  52. const btn = page.locator('button[type="submit"], .el-button--primary, button:has-text("登录")').first();
  53. if (await btn.count() > 0) await btn.click();
  54. await page.waitForTimeout(4000);
  55. out.steps.afterLogin = {
  56. url: page.url().slice(0, 120),
  57. tokenLen: await page.evaluate(() => (localStorage.getItem('token') || '').length),
  58. errorText: await page.evaluate(() => {
  59. const el = document.querySelector('.el-message, .el-notification, [class*="error"], .tip, .err');
  60. return el ? el.textContent.trim().slice(0, 120) : null;
  61. })
  62. };
  63. await ctx.close();
  64. } catch (e) {
  65. out.fatal = String(e && e.message ? e.message : e).slice(0, 300);
  66. } finally {
  67. await browser.close();
  68. }
  69. fs.writeFileSync(path.join(__dirname, '_e2e_admin_debug.json'), JSON.stringify(out, null, 2));
  70. console.log(JSON.stringify(out, null, 2));
  71. }
  72. main().then(() => process.exit(0)).catch(e => { console.error(String(e).slice(0,300)); process.exit(1); });