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!