TestVagrant

Handle Multiple Webviews — Mobile Application Automation

Handle Multiple Webviews — Mobile Application Automation

handle multiple webviews - mobile app automation

Blog

Handle Multiple Webviews — Mobile Application Automation

Problem statement:

MFE(Micro frontend) architecture is a design approach in which the front-end app is broken down into smaller independent micro apps. Usually in a project, there could be many teams working independently, each team could load their respective app in a separate webview.

Context:

The application undertest is a mobile app built on react native with MFE architecture. Application content is loaded as part of multiple Webviews to improve performance.

Challenges:

  • Switch to appropriate webview if multiple webviews are loaded
  • Switch to appropriate webview if multiple webview with same title loaded
  • Switch back to parent webview and continue with the test

Solutions:

First Solution: Using Title of the Webview

Most of the webview would have title associated with it. In order to resolve above challenges, one of the solution is switch to webview based on title and continue further steps.

Steps To Inspect Device:

  • Setup Emulator/Real device(For Real device make sure connected to computer via cable and Enable developer option)
  • Installed app on the device
  • Launch the app
  • Open chrome and go to url chrome://inspect/#devices

Note: Each webview will have Title and Url as shown in the above image

Below sample code is written using WebdriverIO framework along with Typescript

				
					 /**
   * switch to webview based on title
   */
  export async function switchToWebviewWithTitle(driver: Browser, title: string) {
    try {
      // Add wait if webview loading takes time
      const windowHandles: string[] = await driver.getWindowHandles();
      console.info('below are window handles');
      windowHandles.forEach((windowHandle) => {
        console.info(windowHandle);
      });
      let foundWebview:boolean = false;
      for (let index = 0; index < windowHandles.length; index += 1) {
        await driver.switchToWindow(windowHandles[index]);
        const currentTitle:string = await driver.getTitle();
        if (currentTitle === title) {
            foundWebview = true;
            console.info(`Switched to webview with title - ${title}`);
            break;
        }
      }
      if (!foundWebview) {
        console.warn(`Could not find the webview with specified title-${title}, switching to ${windowHandles[0]}`);
        await driver.switchToWindow(windowHandles[0]);
      }
    } catch (error) {
      console.error('switch to child window was not successful\n');
      console.info(error.stack);
      throw new Error(error);
    }
  }
				
			

Drawback

There might be chances of loading multiple webview with same Title and could be a blocker issue. In this situation automation script might switch to inappropriate webview and test script might fail.

Second Solution: Using Webview Url

Since each of the webview will have URL associated with it. One more solution is switch to webview based on URL. We need to switch webview which contains portion of URL which we expect and continue further steps.

				
					  /**
   * switch to webview which contains expected url path
   */
  export async function switchToWebviewWithUrl(driver: Browser, urlContains:string) {
    try {
      // Add wait if webview loading takes time
      const windowHandles: string[] = await driver.getWindowHandles();
      console.info('below are window handles');
      windowHandles.forEach((windowHandle) => {
        console.info(windowHandle);
      });
      let foundWebview:boolean = false;
      for (let index = 0; index < windowHandles.length; index += 1) {
        await driver.switchToWindow(windowHandles[index]);
        const currentUrl:string = await driver.getUrl();
        if (currentUrl.includes(urlContains)) {
          foundWebview = true;
          console.info(`Switched to webview with url containing-${urlContains}`);
          break;
        }
      }
      if (!foundWebview) {
        console.warn(`Could not find the webview with with url containing-${urlContains}, switching to ${windowHandles[0]}`);
        await driver.switchToWindow(windowHandles[0]);
      }
    } catch (error) {
      console.error('switch to child window was not successful\n');
      console.info(error.stack);
      throw new Error(error);
    }
  }

				
			

Conclusion:

Approach to follow completely depends on the how application developed, below are the few points to consider.

  • First solution will be suitable if webviews loaded at any point in time has unique titles.
  • Second solution will be suitable if multiple webview loaded with same title but different URL.

I would recommend to use the Second solution, since it is more reliable works in most of the cases.

Share This Article

Other Related Articles

Scroll to Top