I am trying playwright and try to automate login feature. I have page classes, test classes and separate action class to write common actions like click,enter inputs.
My common action class
import { expect, Locator, Page } from “@playwright/test”
export default class Actions {
page:Page;
constructor(page:Page) {
this.page = page ;
}
public async enterInput(value:string,element:Locator) {
element.fill(value);
await this.page.waitForTimeout(5000);
}
public async clickButton(element:Locator) {
element.click();
await this.page.waitForTimeout(5000)
}
}
My login.page.ts class
import { Locator, Page, expect } from “@playwright/test”;
import Actions from “../common/actions”;
import * as path from “../xpaths/xpath.json”
import fs from ‘fs’;
export default class LoginPage {
page: Page;
action:Actions;
inputUsername:Locator;
inputPassword:Locator;
btnLogin:Locator;
errorText:Locator;
constructor(page:Page) {
this.page = page ;
this.action=new Actions(page);
const pathsxData = fs.readFileSync(“json path here”, “utf-8”);
const pathsx = JSON.parse(pathsxData);
this.inputUsername = this.page.locator(path.usernameInput);
this.inputPassword = this.page.locator(path.passwordInput);
this.btnLogin = this.page.locator(path.loginBtn);
this.errorText=this.page.locator(path.loginError)
}
public async login(username:string,password:string)
{
this.action.enterInput(username,this.inputUsername);
this.action.enterInput(password,this.inputPassword);
await this.action.clickButton(this.btnLogin);
}
public async successLogin(username:string,password:string,title:string){
this.login(username,password);
await expect(this.page).toHaveTitle(title);
}
public async invalidLogin(username:string,password:string,error:string){
this.login(username,password);
await expect(this.errorText).toHaveText(error);
}
public async emptyLogin(username:string,password:string,error:string){
this.login(username,password);
await expect(this.errorText).toHaveText(error);
}
}
My logintest.spec.ts
import { test , expect} from “@playwright/test”
import LoginPage from “../pages/login.page”
import * as data from “../testdata/testdata.json”
test.describe(‘Login Test’, () =>{
let login:LoginPage;
test.beforeEach(async({page}) =>{
await page.goto(“My Url”);
await page.waitForTimeout(5000)
login = new LoginPage(page);
});
test(‘invalid login-username/password both incorrect’, async () => {
login.invalidLogin(data.invalid_username,data.invalid_password,data.invalid_error);
});
test(’empty username/password login’, async()=>{
login.invalidLogin(data.invalid_username,data.invalid_password,data.invalid_error);
});
test(‘successfully login to the system’ , async () => {
login.successLogin(data.username,data.password,data.dashboard_title);
});
});
Whenever I execute the code always getting Target Closed error.Below is the error
Error: locator.fill: Target closed
=========================== logs ===========================
waiting for locator(‘xpath=//input[contains(@id,’outlined-basic’) and contains(@type,’text’)]’)
============================================================
at ..commonactions.ts:16
14 |
15 | public async enterInput(value:string,element:Locator) {
> 16 | element.fill(value);
| ^
17 | await this.page.waitForTimeout(5000);
18 | }
But when I execute code without using action class like below code executes successfully.
import { test , expect} from “@playwright/test”
import LoginPage from “../pages/login.page”
import * as data from “../testdata/testdata.json”
test.describe(‘Login Test’, () =>{
let login:LoginPage;
test.beforeEach(async({page}) =>{
console.log(page.url)
login = new LoginPage(page);
});
test(‘invalid login-username/password both incorrect’, async ({page}) => {
page.goto(“http://192.168.0.127/ussd_qa/login”);
await page.waitForTimeout(5000);
await login.inputUsername.fill(data.username);
await page.waitForTimeout(5000);
await login.inputPassword.fill(data.password);
await page.waitForTimeout(5000);
await login.btnLogin.click();
await page.waitForTimeout(5000);
await expect(login.errorText).toHaveText(data.invalid_error);
});
});
Can someone explain what is wrong here?
Source: Read More