Web App Testing & Tools

Creating a Page Object

Miško Hevery

Miško Hevery

Qwik Creator (Previously Angular)
Web App Testing & Tools

Check out a free preview of the full Web App Testing & Tools course

The "Creating a Page Object" Lesson is part of the full, Web App Testing & Tools course featured in this preview video. Here's what you'd learn in this lesson:

Miško tests the behavior of the clustering form. Since elements on the page need to be selected and given specific values, a page object is created so the test API is more readable. This allows for some self-documentation to happen inside the test and alleviates confusion.

Preview
Close

Transcript from the "Creating a Page Object" Lesson

[00:00:00]
>> Now, let's make a, kind of a bigger test. So, this is kind of a trivial test, let's see if we can make something more interesting. So let's test if it prints Current parameters. So, again, we're gonna navigate, but when you navigate a page, you can specify additional parameters in here.

[00:00:35]
For example, I can say size equals 1,000. Number of clusters equals 5. Let's see. Is that the correct parameter? Size, distance, mincluster. So, size is that, and I can say distance is 450. So let's say we wanted to navigate with this particular URL, just to kind of prove a point.

[00:01:00]
I can go here. And, where is our Chicago? We can navigate and now you can see that the default size and distance has been updated, right? Let's say we wanted to assert this particular thing. So the most obvious way to do that is you navigate and then you start selecting things like, for example, you say a wait, expect page.locator.

[00:01:29]
And I think I have a size. Locator is the way you find things on a page. And I've already gave size a class, so that I can easily find it, and then I can assert that size two have text thousand, right? Why is this? So, if you look at this.

[00:01:59]
Thousand right here, You'll see that it's a span and it already has a class. So I've already given it a class so that it's easy for me to go and select it on the page. Otherwise, you would have a really hard time finding things on a page, right?

[00:02:13]
So typically, you kind of, again, this is another example of where you design the application with testability in mind. You put extra stuff in there so that later on it makes it easier for you to locate and find them and assert different things around it. And we can assert other thing.

[00:02:30]
First of all, let's see if it runs. So, let's see if our test is passing. And it looks like it's timing out. No, it's passed. So, it did pass. And you can see that it actually highlighted the selector on a page. If you click on this thing, you can see it highlighting that this is the part that it's asserting.

[00:02:57]
Now, the thing I wanna show you is that, you will, let's make more assertions here. So, we have size, we have distance, that should be 450. And we have min-cluster size And let's say that's, I think that's 10, what is the default? Not this 5, sorry, this is 5 here, and so now, I should be able to rerun this test and I should have more assertions and they all should pass, right?

[00:03:35]
So they're still passing. The thing wanna show you is, you're gonna get bored after a while writing these tests. And especially not only are you gonna get bored, it's gonna get annoying because all these selectors will make it difficult for you to reason about the application. So what you want to do is you want to put a level of indirection.

[00:03:57]
Between your unit tests or rather your end-to-end tests, and the actual application. And so, in the world of e2e, these are called page objects. And a page object is the logical representation of what the page does. So let's build one. So, what you want is you create a cluster page, And the constructor of the cluster page will take page, And let's say we want to get the title.

[00:04:33]
So we can create a title on it, and the title really is, oops, return this page locator h1, no, this page, page.title. And we also wanna be able to get size. Wow, Autopilot is amazing. Okay, get distance, yep, wow. Get min-cluster size, yes. You're reading my mind. It's just amazing when AI works, right?

[00:05:09]
So, now you have these things, and you probably also want to be able to do navigation. So you wanna create a, sorry, a saying go to and you wanna navigate and you probably instead of creating this URLs this way, you probably want to create them as parameters. You wanna basically say something like, I wanna have a size, which is a number.

[00:05:39]
And I wanna have a distance and min-cluster as well, AI, you are really rocking it. Create this. And, sorry, why is it not? Right, because it is right, we do Okay, so you're saying, look, when you do go to, you can give me these defaults and I'm gonna build up the URL for you, right?

[00:06:13]
So you will start with something like, const url = equals new URL. And then you can say, if you have size, then set the size, if you have distance, set the distance, if you have min-cluster size, set them in cluster size and then you do URL to string.

[00:06:39]
So now we can go back Into our original code and we can do some re-factorings. What we do, we say const cluster page equals new, oops. And now that we have a cluster page, we can rewrite it in a more natural way. You can say await cluster page go-to, we don't have to specify anything there.

[00:07:10]
And then we can write it in this particular format, which is kind of nicer. Similarly, in this case, instead of writing, I'm gonna actually just comment this out so it's easier to compare. Instead of writing this, we can write, go to, and now we have type safety, and we can specify that we want a distance of 450, size of 1000, minClusterSize of 5, and then we can Write assertions.

[00:07:39]
And again, assertions we don't have to worry about the selectors, we can just say, hey, on this page, to have this value, this value and that value so let's see if we have still have a working test. That test works, and that test works as well. So the idea behind, let me delete this.

[00:08:12]
Well, let me just keep it here. The idea behind a page object is that it provides a level of indirection between you and just the DOM. Cuz the DOM is difficult to work with. Selectors are difficult to understand, right? But what it allows you to do is, let's say in the future you decide to refactor the way you display stuff on it for the user.

[00:08:31]
You can do that. You then have to go and update the cluster page object, but you don't have to update hundreds of different tests to match this. Because the test speak a language that is strongly typed, right? The TypeScript is strongly typed. So here, instead of saying, give me a locator that has span distance, which you might forget, or somebody might refactor or change, etc, you can just say, give me the distance.

[00:08:58]
And you can work with that particular thing. Does that make sense? Yes.
>> What do you think about, I've used the testing library frameworks before and they prioritize accessibility attributes, what do you think about using stuff like that?.
>> Well, in general, you want to set up your page so that it's easier to test, right?

[00:09:26]
And you want to add extra attributes. Whether those attributes come in the form of classes or accessibility attributes or some other format, it doesn't really matter. What matters is that you create your up page, right, in whatever framework you're using. You create this page object, which abstracts away the selectors, right?

[00:09:48]
It hides the selectors from you, and does not just hiding of the selectors, it also hides how to do URL encoding, right? And then you just have the test. And so the test, instead of going to individual selectors, which are hard to read and understand and see why, it becomes easier to read.

[00:10:07]
And also, this now provides a place where you can leave documentation, right? You can say like represents the current size of the dataset. Or something like that, right? So it's a way of providing all this useful information. So the page object basically gives you a programmatic view to all the knobs and values that the user might be able to do.

[00:10:38]
So if you had a button over there, then that button would be exposed in your page object.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now