Search code examples
javascriptplaywright-test

Playwright test, If Delay/timeout e.g. click({delay:2000}), is not declared, then element or text in the next step is not found and throws error


  • I have declared actionTimeout: 20 * 1000, in playwright.config.ts file. However, without declaring additional inline delay/timeout, the test fails due to the below error. Even with increased time, it throws the same error.
  • If I declare a delay like await this.page.getByText('All applications').first().dblclick({delay:2000});, then the element is found and the test is passed.
  • I have tried with pageload/waitfor/isvisible() methods, but it does not work and fails in the same place.

Is declaring delay inline a right approach as playwright has inbuild wait methods, then why is it failing to locate element without additional timeout/delay?

Is there any other way we can avoid these additional timeouts?

Code:

import { Page, expect } from "@playwright/test";

export default class appRegNavigateHelper{
    constructor(public page: Page) {
    }
   async AllApplications(AppName: string) {
   //Navigate to AppRegistration, select All applications and search Application 
   await this.page.getByRole('link', { name: 'App registrations' }).click();
   await this.page.getByText('All applications').first().dblclick();
   await this.page.getByRole('searchbox', { name: 'Search box' }).click();
   await this.page.getByRole('searchbox', { name: 'Search box' }).fill(AppName);
   }
}

Error: TimeoutError: locator.click: Timeout 20000ms exceeded. at appRegNavigateHelper.AllApplications (c:\Users:10:67) at tests\P3TestCaseSet01\AppRole.spec.ts:10:2 Execution log

waiting for getByRole('searchbox', { name: 'Search box' }) locator resolved to <input disabled type="text" tabindex="-1" role="searchb…/> attempting click action waiting for element to be visible, enabled and stable element is not enabled - waiting... element is not visible - waiting...

playwright.config.ts

const config: PlaywrightTestConfig = {
**timeout: 150 * 1000,**
  expect: {
    /**
     * Maximum time expect() should wait for the condition to be met.
     * For example in `await expect(locator).toHaveText();`
     */
    **timeout: 8 * 1000,**
  },
  use: {
    /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
    **actionTimeout: 20 * 1000,**
    /* Base URL to use in actions like `await page.goto('/')`. */
    // baseURL: 'http://localhost:3000',

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
    headless: false,
    screenshot: 'only-on-failure',
  },
} 

Sharing Runnable sample code : Line 15 - If delay time is not declared test fails.

import { test, expect } from '@playwright/test';

test('test', async ({ page }) => {
  await page.goto('https://portal.azure.com/');
  await page.getByPlaceholder('Email, phone, or Skype').fill('TestUser@####');
  await page.getByRole('button', { name: 'Next' }).click();
  await page.getByPlaceholder('Password').click();
  await page.getByPlaceholder('Password').fill('#####');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await page.getByRole('button', { name: 'Yes' }).click();
  await page.getByPlaceholder('Search resources, services, and docs (G+/)').click();
  await page.getByPlaceholder('Search resources, services, and docs (G+/)').fill('Microsoft Entra ID');
  await page.locator('#Microsoft_AAD_IAM_AzureActiveDirectory a').click();
  await page.getByRole('link', { name: 'App registrations' }).click();
  await page.getByText('All applications', { exact: true }).first().click({delay:2000});
  await page.getByRole('searchbox', { name: 'Search box' }).click();
  await page.getByRole('searchbox', { name: 'Search box' }).fill('test');
  await page.getByRole('link', { name: 'TE Test', exact: true }).click();
});

Solution

  • Without seeing the page that the button lives on, or at least the html for said area, this is all just conjecture, but I can give some things to try.

    First, no you shouldnt need inline delays in your locator actions. Playwright has perfect auto wait properties build in for you to use. This just needs the perfect combo of these, along with better understanding your page under test to debug EXACTLY what is happening. Playwright just follows exactly the steps you give it.

    Option 1:

    Before you click, you should wait for it to be visible, something like:

    await expect (page.getByText('All applications', { exact: true })).toBeVisible()

    This will wait up to your set timeout for it to return true. Then, click it.

    After this point, you should wait for the searchbox button with:

    .ToBeEnabled()

    Before you try to click it.

    Option 2:

    Take a step back and dive into your page first. I recommend taking some time to debug WHY it is not ready for clicking.

    Try this link:

    https://www.debugbear.com/blog/chrome-devtools-network-throttling

    And see how the page loads after each manual click. This will show you how the loading is done on a more human readable way. Then you can adjust your auto waits as needed.