Sunday, 25 September 2022

puppeteer iframe waitForNavigation return timeout

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

Search Input enter image description here

Table enter image description here

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 issue I get enter image description here

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