Im trying to implement Playwright/TS Page Object Model framework for a web app.
So in this case Im automating login successful scenario by asserting user can see the Dashboard text.
But Im getting the following error.
Error: locator.waitFor: Target closed
=========================== logs ===========================
waiting for getByRole('heading', { name: 'Dashboard' }) to be visible
============================================================
at ../pages/DashboardPage.ts:32
30 |
31 | async isDashboardTxtVisible(){
> 32 | await this.txtDashboard.waitFor({state: "visible"});
| ^
33 | return this.txtDashboard.isVisible();
34 | }
35 | }
at DashboardPage.isDashboardTxtVisible (/Users/ivit/Desktop/Projects/QA/Playwright/PWPOM_V4/pages/DashboardPage.ts:32:31)
at /Users/ivit/Desktop/Projects/QA/Playwright/PWPOM_V4/tests/login.spec.ts:8:34
Here is my code.
This is the spec file Im executing(login.spec.ts)
import { test, expect } from '@playwright/test';
import { App } from '../pages/App';
test("Checking whether user can logged in", async({page}) => {
const app = new App(page);
await app.LoginPage.visit();
await app.LoginPage.login("Admin","admin123");
await expect(app.DashboardPage.isDashboardTxtVisible()).toBeTruthy();
});
DashoardPage.ts
import { Locator, Page } from "@playwright/test";
export class DashboardPage {
readonly page: Page;
readonly lnkLeave: Locator;
readonly lnkPIM: Locator;
readonly txtDashboard: Locator;
constructor(page: Page){
this.page = page;
this.lnkLeave = page.getByPlaceholder('Username');
this.lnkPIM = page.getByPlaceholder('Password');
this.txtDashboard = page.getByRole('heading', { name: 'Dashboard' });
}
async clickLinkLeave(){
this.lnkLeave.click();
}
async clickLinkPIM(){
this.lnkPIM.click();
}
async isDashboardTxtVisible(){
await this.txtDashboard.waitFor({state: "visible"}); <<<< Here is the issue
return this.txtDashboard.isVisible();
}
}
LoginPage.ts
import { Locator, Page } from "@playwright/test";
export class LoginPage {
readonly page: Page;
readonly txtUsername: Locator;
readonly txtPassword: Locator;
readonly btnLogin: Locator;
constructor(page: Page){
this.page = page;
this.txtUsername = page.getByPlaceholder('Username');
this.txtPassword = page.getByPlaceholder('Password');;
this.btnLogin = page.getByRole('button', { name: ' Login' });
}
async login(username: string, password: string){
await this.txtUsername.type(username);
await this.txtPassword.type(password);
await this.btnLogin.click();
}
async visit(){
await this.page.goto("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
}
}
App,.ts (This is kind of a wrapper class, where i don’t need to create objects from a page class inside tests every time)
import { Page } from "@playwright/test";
import { LoginPage } from "./LoginPage";
import { DashboardPage } from "./DashboardPage";
export class App {
protected page: Page;
constructor(page: Page){
this.page = page;
}
public get LoginPage(): LoginPage{
return new LoginPage(this.page);
}
public get DashboardPage(): DashboardPage{
return new DashboardPage(this.page);
}
}
What is the issue here? is it that the way Im using wait? How to fix this issue?
2
Answers
Manage to fix this issue by adding inside and outside awaits
isVisible does not wait for the element to be visible like toBeVisible web assertion which is the correct way to assert something.
Example: