Navigation Page Object | Bondar Academy
Course: Playwright UI Testing with TypeScript
Module: Page Objects
Instructor: Artem Bondar
Lesson Summary
In this lesson, we enhance the NavigationPage object by adding methods for navigating to different pages and implementing custom logic to validate the menu's status (collapsed or expanded). Here are the key points covered: New Navigation Methods Created methods for navigation to DatePickerPage , SmartTable , ToolTip , and ToasterPage . Utilized existing code from previous lessons for consistency. Handling Menu State We encountered an issue where the menu collapsed when navigating to the DatePickerPage . This was due to the sequence of clicks collapsing the menu item. To resolve this, we implemented logic to: Check the aria-expanded attribute of the menu item. Expand the menu only if it is collapsed before selecting the desired page. Implementation Details private async selectGroupMenuItem(groupItemTitle: string) { const groupMenuItem = this.page.getByTitle(groupItemTitle); const expandedState = await groupMenuItem.getAttribute('aria-expanded'); if (expandedState === 'false') { await groupMenuItem.click(); } } We then called this helper method in our main navigation methods, ensuring that the menu state is checked before any clicks are made. Testing and Refactoring After implementing the changes, we ran tests to confirm that: All pages could be navigated to successfully. The menu state was correctly handled, allowing smooth navigation. In summary, we improved the NavigationPage methods to be more intelligent, allowing navigation regardless of the menu's state. This ensures robust page transitions in our test application. Thank you for watching, and see you in the next lesson!
Video Transcript
In this lesson, we continue working with NavigationPage object and we will add more methods related to navigation to a different pages. And also we will create a custom logic that will be responsible for validation of the status is the menu collapsed or expanded. And based on the status, the behavior of the method will be designed. So let's get into it. So let's create other methods that relate it to navigation on the different pages that we used before in our lesson like DatePickerPage. What else did we use? SmartTable, ToolTip, ToasterPage. And let's create those. So NavigationPage. So I have just created an empty methods for each of menu items and let me simply copy-paste the code from the previous lesson. So ToasterPage is this one. ToolTipPage is this one. SmartTable SmartTable And DatePickerPage Okay, and also I will need to change everywhere this.page to make it working. So I will just copy-paste the code from the previous lesson. All right, looks good right here. Now let's try to use for example navigation to the DatePickerPage. Go into our spec file and I put await navigateTo. And we have all the methods that we created inside of the page object available. And let me run this test just to make sure that it is working. Yeah, it worked. FormsLayout was selected first, but then DatePicker was selected. But if you notice the menu is just kind of shaked a little bit. So let me show you what I meant. For example, for here DatePickerPage, I will add a little delay between the steps. page waitForTimeout And let's say I add one second delay between clicking on the form and then navigating to the DatePickerPage. And let me show you what's gonna happen. And look at this. Now the menu item is collapsed and test is actually trying to run but not able to. So DatePickerPage is not selected simply because our menu item is collapsed. And why it is collapsed? Because it's following exactly what our code is doing. So click on the forms menu item and then click on the DatePicker. But because we already clicked on the forms in FormsLayoutPage method, when we try to navigate to the DatePickerPage, it's clicking on the forms again, and it's technically collapsing this menu item, not allowing to select a DatePickerPage for us. It worked before without a delay timeout just because PlayWrite runs the code really really quick and it's selecting DatePicker before the menu item collapses, so it's able to click at the very last moment. And this is a problem because our method should be smart enough to understand the state of the forms menu item. Is it expanded or is it collapsed? And if menu item is expanded, then it should not click on the forms again to collapse this item. And this is the logic that we will add inside of the PageObject right now to handle this kind of behavior. So let me make a right click, inspect, and look at the DOM what happens when I click on the menu item expanding it or collapsing it. So when I click on this, we have this attribute AreaExpanded, which changes the value from true when it's expanded to false when it is collapsed. So we can use the value of this attribute to control the flow of our code. And if the menu is collapsed, we want to expand it. And if it's already expanded, we want to skip the step on clicking on the group item and just select the item itself. So let's go and do this. And for that, let's create another method that will be a helper method inside of this PageObject. And since this method will be used only by the methods related to this PageObject, we want to make this method private and not visible outside of this class. So we call private async and let's say call this method select group menu item. Okay, this will be our method. Our method will expect the name of the group that we want to select. And I will call this property group item title and the type of the data will be a string. Okay, the next step we need to create a locator for this group item. We probably can use this get by text, but I think more precisely would be used to make sure that we will select this particular element, which starts with anchor tag and has a title forms. So we can use a different locator and get by title. And I create a new constant, const group menu item equals to this page get by title and title will be the value that we're gonna pass inside of this method, which is group item title. The next step we need to get the value of this property, which is area extended. It's either true or is it false? A new constant is created. Let's say I call it expanded state equals to group menu item dot get attribute and I provide the value of the attribute from the code, which is area expanded. Okay, and then I need to create a condition. Based on this value, is it true or false? I can either click on group menu item or skip this step. If expanded state is equals to false, it means this menu item is collapsed. Okay, why is it highlighted? Okay, because I forgot to put a weight over here. So you see how easy is it to lose this concentration and forget to put the weight? This is one of the most common mistakes that you may see. So if expanded state is false, then we want to do what is a weight group menu item dot click. So we want to expand it. That's it. And now we need to call this helper method inside of the main method, replacing the command that we had before. So weight this dot select group menu item and then I pass the name for this group menu item, which is forms. And then I pass the name for this group menu item, which is forms. Right here. And the same thing we need to do right here. And we don't need this anymore. And I'm replacing this. So we technically replace the line where we call the forms group menu item with a smart method that will check So now let's run our test one more time and see if it's working or not. So I put the timeout back to one second and now it should successfully select first form layouts page and then date picker page. Let's check this out. So forms layout selected and then date picker selected. You see right now it worked perfectly fine. Our method verifies if forms expanded or collapsed and now our page object methods are smart and can be used in any test safely without being afraid that menu can be expanded or collapsed. So let me make a quick refactoring for the rest of the methods inside of our page object. All right, we did this and now let's make sure that all of those methods work as expected and we call them inside of our spec file. So navigate to the date picker page, navigate to what else? Smart table page, await, navigate to toaster page and the last one await navigate to tooltip page and let's run this test. All right, it worked successfully. All menu items are expanded and the tooltip page is selected. It means that all methods worked just fine. All right, so let's quickly summarize what we did in this lesson. We added more usable methods into navigation page. We made those methods smart enough to be able to select any page inside of our menu regardless the state of the main menu. Is it expanded or collapsed? So we created internal method that will check the state of the main menu. Is it expanded or collapsed? And then based on the state it's either click on this menu item or we'll skip this item selecting the actual item from the menu either tooltip, toaster, smart table, date picker or form layouts. And then we can successfully call our page object methods to navigate across the pages in test application. All right. Thank you guys and see you in the next lesson.