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?
Manage to fix this issue by adding inside and outside awaits
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( await app.DashboardPage.isDashboardTxtVisible()).toBeTruthy();
});