Saturday, April 13, 2024
 Popular · Latest · Hot · Upcoming
44
rated 0 times [  47] [ 3]  / answers: 1 / hits: 5476  / 3 Years ago, wed, march 3, 2021, 12:00:00

I'm converting a bunch of tests from Selenium + Jest to Playwright + Jest, and one of the differences is that for element lookups, await page.$(".whatever") doesn't reject if it doesn't find the element.


I'm doing a lot of element lookups as we've built out Page Object Models for a lot of components.


My question is, do I need to manually add some error handling, or am I missing something here? Jest will tell me which test fails but there's no stack trace so it can be hard to track down what went wrong. Also, is this a good way to do it?


// some-test.js
it("should display the event title", async () => {
let eventTitle = await this.bookingPage.getEventTitle();
expect(await eventTitle.textContent()).toBe("Some special event");
});


// Page Object Model

class BookingPage extends PageObjectModel {
async getEventTitle() {
const selector = "h2.title .content";
const result = await page.$(selector);
if (!result) throw new Error(`Could not find selector: "${selector}"`);
return result;
}
}

If it is a good approach it seems like a pain to have to do for all lookups. Would it be a good idea to wrap page.$ in another function that just does it for me? It would be a bad idea to mutate page.$ itself right? So maybe create a wrapper method that does the error handling and it and then calls page.$?


So I could do something like this:


class PageObjectModel {
async $(selector) {
const result = await page.$(selector);
if (!result) throw new Error(`Could not find selector: "${selector}"`);
return result;
}
}


class BookingPage extends PageObjectModel {
async getEventTitle() {
return this.$("h2.title .content");
}
}


Which is kinda nice but then for some reason the stack trace only links to some-test.js and PageObjectModel.js, and not to BookingPage.js.


I feel like I'm not missing something about JS error handling in general? ¯_(ツ)_/¯


More From » playwright

 Answers
0

Okay so in the end I found that you can use page.waitForSelector which will also return the element if it's found and will reject with a TimeoutError if it's not found, which is what I wanted.


For some reason the stack-trace still only links to some-test.js and PageObjectModel.js however if I catch and re-throw it in BookingPage.js then it does add that to the stack trace.


I don't actually need to throw it, I just need to log it out. So this is the solution I'm going with:


// some-test.js - ** unchanged **
it("should display the event title", async () => {
let eventTitle = await this.bookingPage.getEventTitle();
expect(await eventTitle.textContent()).toBe("Some special event");
});

class PageObjectModel {
async $(selector) {
return page.waitForSelector(selector);
}
}

class BookingPage extends PageObjectModel {
async getEventTitle() {
return await this.$("h2.title .content").catch(console.error);
}
}

It's a bit weird as according to this article await return is redundant outside of try/catch, but I guess because I'm using .catch it's functionally the same as try catch?


Anyway, this gives me the stack trace that I want.


[#1702] Friday, February 26, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
gonzaloulyssess

Total Points: 225
Total Questions: 114
Total Answers: 112

Location: Iraq
Member since Fri, Jun 5, 2020
4 Years ago
;