Search code examples
javascriptnode.jschromiumplaywright

Playwright - Chromium keeps crashing while filling input within for loop


I'm relatively new to Playwright and stuck on something. I'm using it to automate an otherwise manual data entry process. The process is as follows:

  • Loop through several objects in an array
  • Find a category on the page that contains the object's name (str) and click it, then click another button that opens a dialog
  • In that open dialog, find an input contained within a form field that also contains the string's name (the dialog is basically a ul of forms with price inputs) and fill that input with a new price value
  • Close the dialog, return the item and move on to the next one

My simplified code for this process is below:

const playwright = require("playwright");
const state = {
  str: "",
  step: "",
};
var page;
var frameLocator;

var items = [
  {
    str: "A50",
    price: 0,
  },
  {
    str: "AP2",
    price: 23,
  },
  {
    str: "B25",
    price: 406,
  },
  {
    str: "C72",
    price: 309,
  },
  {
    str: "CB1",
    price: 0,
  },
];
var results = [];

async () => {
  const browser = await playwright.chromium.launch({
    headless: false,
    slowMo: 1000,
  });
  const url = "https://example.com";
  const context = await browser.newContext();
  page = await context.newPage();
  page.on("domcontentloaded", async (e) => {
    await page.waitForSelector("#ContentFrame");
    frameLocator = await page.locator("#ContentFrame").frameLocator(":scope");
    for (let i = 0; i < items.length; i++) {
      var result = await updatePrice(items[i].str, items[i].price);
      results.push(result);
    }
  });
};

async function updatePrice(str, price) {
  state.str = str;
  var item = {
    str: str,
    newPrice: price,
  };
  state.step = "Finding Category";
  const category = await frameLocator
    .locator(".section")
    .filter({ hasText: str });
  await category
    .elementHandle({ timeout: 5000 })
    .then(async () => {
      item.cat = await category.locator(".info-title").innerText();
      await category.click();
      await page.locator("#toolbar button").first().click();
      state.step = "Finding input";
      var input = await page
        .locator(".dialog .multifield")
        .filter({ hasText: str })
        .locator("input");
      state.step = "Updating input";
      await page.waitForTimeout(2000);
      await input.evaluateHandle((node, price) => {
        node.value = price;
      }, price);
      state.step = "Done updating input";
      await page.locator(".dialog .submit").click();
    })
    .catch(async (err) => {
      //Some other irrelevant error handling logic goes here
    });
  return item;
}

The code is working fine, but at random points throughout the for loop the browser page crashes (just get the "page crashed" error, browser does not close) - not every time I run the loop, but most times. You can see I've already added in some sloMo and a waiting period before filling the input to try and slow the script speed a bit, but I'm not sure if that's helping or hurting. Is there anything I can refactor in this code to reduce or eliminate those page crashes? Thanks!


Solution

  • I can't see any issues with your code. Sometimes tabs do crash. Your best bet at fixing a tab crash is to try a different browser, or a different version of the same browser.

    Different version of Chromium

    Update Playwright to get a newer Chromium version

    Playwright says:

    Each version of Playwright needs specific versions of browser binaries to operate. Depending on the language you use, Playwright will either download these browsers at package install time for you, or you will need to use Playwright CLI to install these browsers.

    NPM does install the browser binaries when you install the package. Installing a new version of playwright package will also update the installed binary. This is a good first step.

    npm i playwright@latest
    

    and then try running your code again.

    Changing the Chromium channel

    You can change the Chromium channel by specifying channel in your launch config:

      const browser = await playwright.chromium.launch({
        headless: false,
        slowMo: 1000,
        channel: "chrome", //chrome,chrome-beta,chrome-dev,chrome-canary,msedge,msedge-beta,msedge-dev,msedge-canary
      });
    

    Changing browsers

    Playwright works with several engines. You might try Firefox instead.

      const browser = await playwright.firefox.launch({