I working with puppeteer to build e2e automation testing. I navigate to page, click on button, it opens new tab that include iframe. Into the iframe I have search input and table. I'm trying to write some text in search input and hover on first row of the table, when it hovers it shows me connect button, I want to click on it and it redirect to new url. I want to wait for the next url.
my tree structure
part of my tests:
it("connect to apps", async () => {
await Promise.all([
page.goto(process.env.URL_MY_APPS),
page.waitForNavigation(),
]);
await policyPage.connectToApps();
});
policyPage
import { Browser, Page } from "puppeteer";
import { getDocument, queries } from "pptr-testing-library";
import selectors from "../selectors";
import fixtures from "../fixtures";
import AppPage from "./appPage";
class PolicyPage extends AppPage {
constructor(page: Page, browser: Browser) {
super(page, browser);
}
async connectToApps() {
const pageTarget = this.page.target();
await this.clickElement('div[class="app-image "]', {
visible: true,
});
const newTarget = await this.browser.waitForTarget(
(target) => target.opener() === pageTarget
);
const newPage = await newTarget.page();
const url = newPage?.url();
console.log({ newPage, url });
if (newPage) this.setPage(newPage);
await this.setIframe('iframe[id="myiframe"]');
await this.iframeTypeValue("input", "app one");
const tableRow = await this.frame.waitForSelector(
"table tbody tr:nth-child(1)"
);
await this.frame.hover("table tbody tr:nth-child(1)");
await this.clickIframeElement("button");
const btn = await tableRow?.$("button");
console.log("after all");
expect('iframe[id="myiframe"]').toBeDefined();
}
}
export default PolicyPage;
I have class called AppPage that the page above extends from it and use all the functions. import { getDocument } from "pptr-testing-library"; import { Browser, ElementHandle, Frame, Page, WaitForSelectorOptions, } from "puppeteer"; import selectors from "../selectors";
class AppPage {
page: Page;
browser: Browser;
document: ElementHandle;
frame: Frame;
constructor(page: Page, browser: Browser) {
this.page = page;
this.browser = browser;
}
init = async (): Promise<void> => {
try {
this.document = await getDocument(this.page);
} catch (e) {}
};
setPage(page: Page): void {
if (page) this.page = page;
}
setIframe = async (selectorId: string): Promise<void> => {
const elementHandle = await this.page.waitForSelector(selectorId, {
visible: true,
});
const frameCtx = await elementHandle?.contentFrame();
if (frameCtx) {
this.frame = frameCtx;
await this.frame.waitForNavigation({ waitUntil: "domcontentloaded" });
} else {
throw new Error("Iframe is not found");
}
console.log("afterLogin:", this.frame);
};
clickElement = async (
selector: string,
selectorsOptions?: WaitForSelectorOptions
): Promise<void> => {
await this.page.bringToFront();
await this.page.waitForSelector(selector, selectorsOptions);
const element = await this.page.$(selector);
if (!element)
throw new Error("Could not find element with selector " + selector);
await element.click();
};
clickIframeElement = async (
selector: string,
selectorsOptions?: WaitForSelectorOptions
): Promise<void> => {
console.log("this frame is", this.frame);
const element = await this.frame.waitForSelector(
selector,
selectorsOptions
);
if (!element)
throw new Error("Could not find element with selector " + selector);
await element.click();
};
hoverElement = async (selector: string): Promise<void> => {
await this.frame.hover(selector);
};
typeValue = async (
selector: string,
value: string,
selectorsOptions?: WaitForSelectorOptions
): Promise<void> => {
await this.page.bringToFront();
await this.page.waitForSelector(selector, selectorsOptions);
await this.page.type(selector, value);
};
iframeTypeValue = async (
selector: string,
value: string,
selectorsOptions?: WaitForSelectorOptions
): Promise<void> => {
await this.frame.waitForSelector(selector, selectorsOptions);
await this.frame.type(selector, value);
};
selectorExists = async (page: Page, selector: string): Promise<boolean> => {
return !!(await page.$(selector));
};
waitSelectorExists = async (selector: string): Promise<boolean> => {
await this.page.bringToFront();
try {
await this.page.waitForSelector(selector);
return true;
} catch (e) {
console.info(
"Encountered error when waiting for selector (" + selector + "): " + e
);
return false;
}
};
getSelectorTextContent = async (
selector: string
): Promise<string | undefined> => {
await this.page.bringToFront();
return this.page.evaluate(
(el) => el?.textContent?.trim(),
await this.page.$(selector)
);
};
}
export default AppPage;
the test sometimes works and success and sometimes no. without any change.. I guess maybe it related to
await this.frame.waitForNavigation({ waitUntil: "domcontentloaded" });
I tried to use waitForSelector and use any class selector from iframe but it still failed and not find this selector.
from puppeteer iframe waitForNavigation return timeout
No comments:
Post a Comment