Playwright error (Target closed) after navigation

Viewed 19697

I'm trying something really simple:

  • Navigate to google.com
  • Fill the search box with "cheese"
  • Press enter on the search box
  • Print the text for the title of the first result

So simple, but I can't get it to work. This is the code:

const playwright = require('playwright');

(async () => {
  for (const browserType of ['chromium', 'firefox', 'webkit']) {
    const browser = await playwright[browserType].launch();
    try {
      const context = await browser.newContext();
      const page = await context.newPage();
      await page.goto('https://google.com');
      await page.fill('input[name=q]', 'cheese');
      await page.press('input[name=q]', 'Enter');
      await page.waitForNavigation();

      page.waitForSelector('div#rso h3')
          .then(firstResult => console.log(`${browserType}: ${firstResult.textContent()}`))
          .catch(error => console.error(`Waiting for result: ${error}`));
    } catch(error) {
      console.error(`Trying to run test on ${browserType}: ${error}`);
    } finally {
      await browser.close();
    }
  }
})();

At first I tried to get the first result with a page.$() but it didn't work. After investigating the issue a little bit I discovered that page.waitForNavigation() that I thought would be the solution, but it isn't.

I'm using the latest playwright version: 1.0.2.

3 Answers

It seems to me that the only problem was with your initial promise composition, I've just refactored the promise to async/await and using page.$eval to retrieve the textContent it works perfectly, there are no target closed errors anymore.

try {
      const context = await browser.newContext();
      const page = await context.newPage();
      await page.goto('https://google.com');
      await page.fill('input[name=q]', 'cheese');
      await page.press('input[name=q]', 'Enter');
      await page.waitForNavigation();

      // page.waitForSelector('div#rso h3').then(firstResult => console.log(`${browserType}: ${firstResult.textContent()}`)).catch(error => console.error(`Waiting for result: ${error}`));

      await page.waitForSelector('div#rso h3');
      const firstResult = await page.$eval('div#rso h3', firstRes => firstRes.textContent);
      console.log(`${browserType}: ${firstResult}`)
    } catch(error) {
      console.error(`Trying to run test on ${browserType}: ${error}`);
    } finally {
      await browser.close();
    }
  }

Output:

chrome: Cheese – Wikipedia
firefox: Cheese – Wikipedia
webkit: Cheese – Wikipedia

Note: chrome and webkit works, firefox fails on waitForNavigation for me. If I replaced it with await page.waitForTimeout(5000); firefox worked as well. It might be an issue with playwright's Firefox support for the navigation promise.

If you await the page.press('input[name=q]', 'Enter'); it might be too late for waitForNavigation to work.

You could remove the await on the press call. You can need to wait for the navigation, not the press action.

const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://google.com');
await page.fill('input[name=q]', 'cheese');
page.press('input[name=q]', 'Enter');
await page.waitForNavigation();

var firstResult = await page.waitForSelector('div#rso h3');
console.log(`${browserType}: ${await firstResult.textContent()}`);

Also notice that you need to await for textContent().

  1. In my case the Playwright error Target closed appeared at the first attempt to retrieve a text from the page. The error is inaccurate, the actual reason was that the Basic Auth was enabled in the target site. Playwright could not open a page and just stuck with "Target closed".

    const options = { 
       httpCredentials = { username: 'user', password: 'password'}
    };
    const context = await browser.newContext(options);
    
  2. One more issue was that local tests were running without a problem, including docker containers, while Github CI was failing with Playwright without any details except the above error.
    The reason was with a special symbol in a Github Secret. For example, the dollar sign $ will be just removed from the secret in Github Actions. To correct it, either use env: section

    env:
      XXX: ${ secrets.SUPER_SECRET }
    

    or wrap the secret in single quotes:

    run: |
      export XXX='${{ secrets.YYY}}'
    

    A similar escaping specificity exists in Kubernetes, Docker and Gitlub; $$ becomes $ and z$abc becomes z.

  3. Use mcr.microsoft.com/playwright docker hub image from Microsoft with pre-installed node, npm and playwright. Alternatively during the playwright installation do not forget to install system package dependencies by running npx playwright install-deps.

  4. A VM should have enough resources to handle browser tests. A common problem in CI/CD worfklows.

Related