Page Objects Helper | Bondar Academy
Course: Playwright UI Testing with TypeScript
Module: Page Objects
Instructor: Artem Bondar
Lesson Summary
In this lesson, we enhance our framework by introducing PageObjectHelper . This helper allows us to consolidate reusable functions across different PageObjects , minimizing code duplication. Implementation of PageObjectHelper We will implement the PageObjectHelper using inheritance from object-oriented programming. Here’s how: Create a new class named HelperBase in HelperBase.ts . Define the standard structure for HelperBase : Page fixture Class definition Constructor Add a method called waitForNumberOfSeconds to demonstrate a hard-coded wait function. Method Implementation The method waitForNumberOfSeconds takes a parameter timeInSeconds and uses it to create a wait time in milliseconds: await this.page.waitForTimeout(timeInSeconds * 1000); Using the Helper in PageObjects To utilize this method in a PageObject , such as NavigationPage , follow these steps: Extend HelperBase using extends HelperBase . Resolve any constructor conflicts using super(page) . Call the method as needed: await this.waitForNumberOfSeconds(...); Framework Architecture Overview Our framework is organized into two main areas: Test Area: Contains spec files for tests. Code Area: Houses all implementation code, including PageObjects and HelperBase . The PageManager manages instances of all PageObjects , facilitating their use within tests. Summary In this lesson, we created a HelperBase class for reusable methods, utilized inheritance to extend this base class in PageObjects , and adjusted our approach to accessing the page fixture. This architecture is scalable and suitable for real projects.
Video Transcript
In this lesson, we will make one more improvement to our framework by adding PageObjectHelper. So sometimes in your project, you may have functions or methods that can be reused across different PageObjects, and having this PageObjectHelper is a good place to keep those types of functions in a single place, so you will not have duplication of this code across the framework. And in order to implement this PageObjectHelper, we will use a concept from object-oriented programming called inheritance. So let's get into it. Under the PageObject, we'll create a new class, and I call it HelperBase, HelperBase.ts. And the standard structure of this HelperBase, we will need a page fixture, we will need to create a class, field, and constructor. And let's say inside of our HelperBase, we create a function just for the demonstration that will wait for some number of seconds inside of our tests, just hard-coded wait. For example, we want to use this wait across different PageObjects. And I will create the async, and I call this method waitForNumberOfSeconds. And parameter, I will use, let's say, timeInSeconds, and it will be a number. The code will be a wait, this page, waitForTimeout, and I will provide time in seconds, multiplying by 1,000. So I will just provide the number in seconds. How many seconds do I want to wait? And here, the implementation, number of seconds multiplied by 1,000, it will be how many milliseconds we want to wait. And now, how to call this method from the PageObject? For example, let's go to the navigation page, and let's say that we want to call this method right here in the FormLayouts page. So we need to use a keyword, extendHelperBase. And VS Code automatically creates the import of this class. After we extended the HelperBase for the navigation page, we can see that constructor is right now broken. This happens because the page instance of the HelperBase is conflicting with the existing page instance of the navigation page. With this kind of inheritance construction, we will need to use the instance of a page that belongs to HelperBase, because we extend the HelperBase by navigation class page. And in order to do this, we need to use a construction called super and provide the instance, which is a page fixture. And we don't need the read-only page anymore. We can safely delete it. And now we can call this method as usual, awaitWaitForNumberOfSeconds. And look at this. It is available and visible. Even if we did not declare the constructor right here or anything like that, how we did before, for example, for the page manager, when we created the instance of each of the page, we simply used the inheritance and extended all the methods from the HelperBase. Right now it's visible inside of the navigation page. So the similar kind of refactoring we need to perform for the rest of the pages to extend the HelperBase to be able to call waitNumberOfSeconds method in there. So DatePickerPage extends HelperBase and replace this super page and remove this. And the same thing for the FormLayoutPage. FormLayoutPage extends HelperBase constructor super page and remove this field. All right, that's it. And let's run this test to make sure that everything is working how it worked before. So we should see a delay for FormsLayoutPage. We see two second delay and then script continue to work. So we know that this waitForNumberOfSeconds works successfully. And let's make a quick overview of the framework architecture for you to better understand the final design of the framework. So this is the design that we have created. So we logically separated our framework to two different areas, which is the test area and the code area. Under the test area, we just have our spec files that are pretty much our test. But the entire implementation of the code is under the code area. We have created different page objects that are responsible for different operations on each of the pages. HelperBase keep our common methods that we can use across different page objects. So we will not duplicate this code as well. And PageManager is managing the instances of all page objects for us. So we can call the PageManager inside of the test and use our page objects. This type of architecture is very useful and scalable, so you can easily implement in your real project and nicely organize your tests. All right, so let me simply summarize what we did in this lesson. We have created a HelperBase class that we can use for keeping some of the methods or functions that can be reused across different page objects. Then inside of this page object, we use a concept from object-oriented programming called inheritance when we extended a base class and then simply can read the method from this base class without creating the instance of this class. Also we change the approach how we read the instance of the page fixture. Since we use inheritance, we need to read a page fixture from the HelperBase class. And in order to do this, we need to use a constructor superPage. And that's it. After that, you simply call the methods inside of the page objects that are inside of the HelperBase as usual. All right, that's it, guys. This is the final lesson of the page object model module. And see you in the next lesson.