]> acesimba.cloud Git - StationBuilder.git/commitdiff
test: verify 脚本支持 BASE 环境变量,可对公网生产路径跑 E2E
authorroot <root@localhost.localdomain>
Wed, 9 Sep 2026 05:22:52 +0000 (13:22 +0800)
committerroot <root@localhost.localdomain>
Wed, 9 Sep 2026 05:22:52 +0000 (13:22 +0800)
scripts/verify-design-merge.mjs [new file with mode: 0644]
scripts/verify-manual-asset.mjs

diff --git a/scripts/verify-design-merge.mjs b/scripts/verify-design-merge.mjs
new file mode 100644 (file)
index 0000000..cb53fef
--- /dev/null
@@ -0,0 +1,93 @@
+import pkg from '/home/StationBuilder/node_modules/playwright/index.js';
+const { chromium } = pkg;
+
+const BASE = process.env.BASE || 'http://127.0.0.1:37821/t/stationbuilder/';
+const results = [];
+const consoleErrors = [];
+function check(name, cond, extra='') { results.push({name, ok: !!cond, extra}); }
+
+const browser = await chromium.launch();
+const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
+const page = await ctx.newPage();
+page.on('console', m => { if (m.type() === 'error') consoleErrors.push(m.text()); });
+page.on('pageerror', e => consoleErrors.push('PAGEERROR: ' + e.message));
+
+try {
+  await page.goto(BASE, { waitUntil: 'networkidle' });
+  await page.waitForSelector('.company-side-nav', { timeout: 15000 });
+  check('load -> projects', true);
+
+  // Extension menu (open by default)
+  await page.screenshot({ path: '/tmp/sb-verify-0-sidenav.png' });
+  await page.waitForSelector('.extension-menu-items', { timeout: 5000 });
+  const extText = await page.locator('.extension-menu-items').innerText();
+  check('扩展页面: 仪表盘', extText.includes('仪表盘'));
+  check('扩展页面: 报表', extText.includes('报表'));
+  check('扩展页面: 数据源', extText.includes('数据源'));
+  // 报表 submenu open by default
+  await page.waitForSelector('.extension-third-menu', { timeout: 5000 });
+  const third = await page.locator('.extension-third-menu').innerText();
+  check('报表子菜单: 仪表盘报表', third.includes('仪表盘报表'));
+  check('报表子菜单: 文档报表', third.includes('文档报表'));
+  await page.screenshot({ path: '/tmp/sb-verify-1-extmenu.png' });
+
+  // AI welcome panel
+  await page.waitForSelector('.ai-fab', { timeout: 5000 });
+  await page.click('.ai-fab');
+  await page.waitForSelector('.ai-welcome', { timeout: 5000 });
+  const aiText = await page.locator('.ai-welcome').innerText();
+  check('AI欢迎面板: 我可以帮你建设场站', aiText.includes('我可以帮你建设场站'));
+  check('AI欢迎面板: 能力列表', await page.locator('.ai-capability-list').count() > 0);
+  check('AI欢迎面板: 你可以问', aiText.includes('你可以问'));
+  await page.screenshot({ path: '/tmp/sb-verify-2-aiwelcome.png' });
+  await page.click('.ai-close');
+
+  // Site edit 5 steps (SiteEditTabs)
+  await page.locator('.company-side-nav button:has-text("站点编辑")').first().click();
+  await page.waitForSelector('.site-edit-tabs', { timeout: 5000 });
+  const tabLabels = await page.locator('.site-edit-tabs button span').allInnerTexts();
+  check('向导5步数量', tabLabels.length === 5, 'got ' + JSON.stringify(tabLabels));
+  check('向导含页面配置', tabLabels.join(' ').includes('页面配置'));
+  await page.screenshot({ path: '/tmp/sb-verify-3-steps.png' });
+
+  // pageConfig blank
+  await page.locator('.site-edit-tabs button:has-text("页面配置")').click();
+  await page.waitForSelector('.site-step-blank', { timeout: 5000 });
+  check('页面配置: site-step-blank 占位', await page.locator('.site-step-blank').count() > 0);
+  await page.screenshot({ path: '/tmp/sb-verify-4-pageconfig.png' });
+
+  // Manual asset UI
+  await page.locator('.site-edit-tabs button:has-text("站点资产设置")').click();
+  await page.waitForSelector('button[role="tab"]', { timeout: 5000 });
+  await page.locator('button[role="tab"]:has-text("手动配置")').click();
+  await page.waitForSelector('.manual-asset-editor, .asset-editor-loading', { timeout: 8000 });
+  check('手动配置资产: 编辑器或加载态渲染', await page.locator('.manual-asset-editor, .asset-editor-loading').count() > 0);
+  await page.screenshot({ path: '/tmp/sb-verify-5-manualasset.png' });
+
+  // Regression: 领域方案库
+  await page.locator(".company-side-nav button:has-text(\"领域方案\")").first().click();
+  await page.waitForTimeout(1500);
+  check('回归: 领域方案库渲染', await page.locator('.company-list-panel, .domain-grid, .domain-library').count() > 0);
+  await page.screenshot({ path: '/tmp/sb-verify-6-domains.png' });
+
+  // Regression: 设备模板
+  await page.locator(".company-side-nav button:has-text(\"设备模板\")").first().click();
+  await page.waitForTimeout(1000);
+  check('回归: 设备模板渲染', true);
+  await page.screenshot({ path: '/tmp/sb-verify-7-devicetemplates.png' });
+
+  // Regression: 页面样式库
+  await page.locator(".company-side-nav button:has-text(\"页面样式\")").first().click();
+  await page.waitForTimeout(1000);
+  check('回归: 页面样式库渲染', true);
+  await page.screenshot({ path: '/tmp/sb-verify-8-stylelibrary.png' });
+
+} catch (e) {
+  results.push({ name: 'SCRIPT ERROR', ok: false, extra: e.message });
+} finally {
+  console.log('=== CHECKS ===');
+  for (const r of results) console.log(`${r.ok ? 'PASS' : 'FAIL'}  ${r.name}${r.extra ? '  ('+r.extra+')' : ''}`);
+  console.log('=== CONSOLE ERRORS (' + consoleErrors.length + ') ===');
+  for (const e of consoleErrors.slice(0, 30)) console.log(e);
+  await browser.close();
+}
index 93fea5f8707f18775b26545ac2a36b23efd8bdf5..1709aa823895c2e4320fa8926843f0f7f3cdf0f6 100644 (file)
@@ -1,7 +1,7 @@
 import pkg from '/home/StationBuilder/node_modules/playwright/index.js';
 const { chromium } = pkg;
 
-const BASE = 'http://127.0.0.1:37821/t/stationbuilder/';
+const BASE = process.env.BASE || 'http://127.0.0.1:37821/t/stationbuilder/';
 const results = [];
 const errs = [];
 const check = (n, c, e='') => results.push({ n, ok: !!c, e });