Commit 01540e6e authored by liguangyu06's avatar liguangyu06
Browse files

修复统计报表 iframe 误绑空壳导致查询超时,统一按查询按钮所在 frame 绑定

parent 89d08aa0
......@@ -23,7 +23,6 @@ export function iframeCssSelector(iframeSrc: string): string {
if (src.includes('?')) continue;
variants.add(`${src}?iframe=true`);
}
variants.add('iframe=true');
if (iframeSrc.includes('settel/')) {
variants.add(iframeSrc.replace(/settel\//g, 'settle/'));
}
......@@ -357,6 +356,33 @@ export class CenterReportSharedLocators {
return (await this.searchBtn.count()) > 0;
}
/**
* 按「查询/搜索」所在 frame 绑定报表根。
* FineReport src 常是通用 viewer,`iframe[src*="iframe=true"]` 会先命中空 iframe,
* 导致 searchBtn 在错误 frame 里等到超时。
*/
async bindReportFrame(): Promise<boolean> {
const options = this.locatorOptions;
const searchRe = options.searchBtnLabel === '搜 索' ? /搜\s*索/ : /查\s*询/;
const hints = [
options.iframeSrc,
...options.iframeSrc.split('/').filter((part) => part.length >= 4),
].filter((hint, index, all) => hint && hint !== 'iframe=true' && all.indexOf(hint) === index);
for (const frame of this.hostPage.frames()) {
if (frame === this.hostPage.mainFrame()) continue;
const btn = frame.getByRole('button', { name: searchRe }).first();
if ((await btn.count()) === 0) continue;
const marker = frame.url();
if (marker && (await this.attachToFrameUrl(marker))) return true;
}
for (const hint of hints) {
if (await this.attachToFrameUrl(hint)) return true;
}
return false;
}
/** 双表页按 tableWrapperIndex 定位对应工具栏「导 出」按钮(0=左表,1=右表)。 */
exportBtnForTable(tableWrapperIndex: number): Locator {
return this.report.getByRole('button', { name: '导 出' }).nth(tableWrapperIndex);
......
......@@ -15,7 +15,6 @@ import {
import {
CenterReportSharedLocators,
COLUMN_SETTINGS_TRIGGER_CSS,
iframeCssSelector,
tableHasColumnSorter,
} from '../../locators/spd/center-report-shared.locator';
import { retryReportLoad } from './helpers/report-load-retry.helper';
......@@ -355,9 +354,8 @@ export class CenterReportSharedPage extends BasePage {
async isReportShellReady(): Promise<boolean> {
try {
if (this.page.isClosed()) return false;
const iframe = this.page.locator(iframeCssSelector(this.data.iframeSrc)).first();
if ((await iframe.count()) === 0) return false;
return await this.locators.searchBtn.isVisible().catch(() => false);
if (await this.locators.searchBtn.isVisible().catch(() => false)) return true;
return this.locators.bindReportFrame();
} catch {
return false;
}
......@@ -395,36 +393,10 @@ export class CenterReportSharedPage extends BasePage {
async expectLoaded(): Promise<void> {
const loadOnce = async () => {
// 先等 iframe 挂上,避免在壳页上空等 searchBtn
const iframeSelector = iframeCssSelector(this.data.iframeSrc);
const iframeAttachMs = /trace\/|report\/trace/.test(this.data.iframeSrc) ? 35_000 : timeouts.pageReady;
let iframeBound = false;
await expect
.poll(async () => {
if ((await this.page.locator(iframeSelector).count()) > 0) {
iframeBound = false;
return true;
}
const hints = [
this.data.iframeSrc,
...this.data.iframeSrc.split('/').filter(Boolean).slice(-2),
];
for (const hint of hints) {
if (!hint) continue;
if (await this.locators.attachToFrameUrl(hint)) {
iframeBound = true;
return true;
}
}
return false;
}, { timeout: iframeAttachMs })
.poll(async () => this.locators.bindReportFrame(), { timeout: iframeAttachMs })
.toBeTruthy();
if (!iframeBound) {
const iframe = this.page.locator(iframeSelector).first();
await iframe.waitFor({ state: 'attached', timeout: 8_000 });
const frame = await iframe.elementHandle().then((handle) => handle?.contentFrame() ?? null);
await frame?.waitForLoadState('domcontentloaded').catch(() => undefined);
}
await this.waitVisible(this.locators.searchBtn, timeouts.pageReady);
await this.waitVisible(this.locators.resetBtn, timeouts.expect * 2);
// 壳就绪后先写默认条件,再等表挂载/显式 search(),避免 iframe 初始查询抢跑
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment