Playwright framework implementation - Part 2

Playwright framework implementation - Part 2

Hoping the you have completed part 1 of the post, let’s move on to part 2!!

In this post, let’s tryin make use of the files that we haven’t used in the part 1. We are gonna create a new test for creating a new user and checking whether the user is landed in the My Account page after sign up

First things first. Creating the files that we need for the next test. Run the below command from the project directory

cd src/apps/automation-practice && touch data/create-account.data.json && touch data/my-account.data.json && touch locators/create-account.locator.ts && touch locators/my-account.locator.ts && touch pages/create-account.page.ts && touch pages/my-account.page.ts && touch tests/create-account.spec.ts && touch tests/my-account.spec.ts

Let’s take a moment to plan on how to tackle the sign-up functionality. We know that we need a unique email and password everytime we need to test this. Considering this, let’s use an existing package named faker-js. faker-js is a package that is used to provide dummy but valid data for testing. Fortunately, this package is already part of the package.json file and no action needed for this 😇

Now that we know that we need to create unique test data for every run, we also need to persist the existing data, so that we can use it later.

Well, good news! We have that as well covered in the framework

Step # 1

Starting with adding test data to the *.data.json files

As we discussed, the test data for new account creation is gonna use the faker-js, all we have to do is add an empty array to src/apps/automation-practice/data/create-account.data.json as below

[]

And for the My Account page validation, we are going to validate whether the user is navigated to the My Account page after sign up. All we are doing here is to verify the title of the page matches with the My Account page title. Add the below to src/apps/automation-practice/data/my-account.data.json file

{
  "title": "My Account Magento Commerce - website to practice selenium | demo website for automation testing | selenium practice sites"
}

Step # 2

Now that we have the test data task out of our way, let’s close the creation of page objects task by updating the *.locator.json files. Add the below code to src/apps/automation-practice/locators/create-account.locator.ts

export const firstNameEdit = 'input[name="firstname"]';
export const lastNameEdit = 'input[name="lastname"]';
export const emailEdit = 'input[name="email"]';
export const passwordEdit = 'input[name="password"]';
export const passwordConfirm = 'input[name="password_confirmation"]';
export const createAccountButton = 'button:has-text("Create an Account")';

Since, we are only validating the title in the My Account page and not any elements within the page, we can ignore the src/apps/automation-practice/locators/my-account.locator.ts file for now

Step # 3

Start creating the necessary steps for the test. Add the below code to src/apps/automation-practice/pages/create-account.page.ts

import path from "path";
import fs from "fs";
import type { Page, TestInfo } from "@playwright/test";
import { test } from "../fixtures";
import * as locators from "../locators/create-account.locator";
import * as actions from "@utils/base/web/actions";
import { appendFile } from "@home/src/utils/functions/file";
import { faker } from "@faker-js/faker";

export default class CreateAccountPage {
  constructor(public page: Page, public workerInfo: TestInfo) {}

  async createAccount() {
    const dataFilePath = path.join(
      __dirname,
      "..",
      "data",
      "create-account.data.json"
    );

    const firstName = faker.name.firstName();
    const lastName = faker.name.lastName();
    const email = faker.internet.email();
    const password = faker.internet.password();

    const account = {
      firstName,
      lastName,
      email,
      password,
      confirmPassword: password,
    };
    await appendFile(dataFilePath, account);

    const data = JSON.parse(fs.readFileSync(dataFilePath, "utf-8"));

    await test.step(
      this.workerInfo.project.name +
        ": Enter first name: " +
        data[data.length - 1].firstName,
      async () =>
        await actions.fill(
          this.page,
          locators.firstNameEdit,
          data[data.length - 1].firstName,
          this.workerInfo
        )
    );

    await test.step(
      this.workerInfo.project.name +
        ": Enter last name: " +
        data[data.length - 1].lastName,
      async () =>
        await actions.fill(
          this.page,
          locators.lastNameEdit,
          data[data.length - 1].lastName,
          this.workerInfo
        )
    );

    await test.step(
      this.workerInfo.project.name +
        ": Enter email: " +
        data[data.length - 1].email,
      async () =>
        await actions.fill(
          this.page,
          locators.emailEdit,
          data[data.length - 1].email,
          this.workerInfo
        )
    );

    await test.step(
      this.workerInfo.project.name +
        ": Enter password: " +
        data[data.length - 1].password,
      async () =>
        await actions.fill(
          this.page,
          locators.passwordEdit,
          data[data.length - 1].password,
          this.workerInfo
        )
    );

    await test.step(
      this.workerInfo.project.name +
        ": Enter confirm password: " +
        data[data.length - 1].confirmPassword,
      async () =>
        await actions.fill(
          this.page,
          locators.passwordConfirm,
          data[data.length - 1].confirmPassword,
          this.workerInfo
        )
    );

    await test.step(
      this.workerInfo.project.name + ": Click create account button ",
      async () =>
        await actions.clickElement(
          this.page,
          locators.createAccountButton,
          this.workerInfo
        )
    );
  }
}

Add the below code to src/apps/automation-practice/pages/my-account.page.ts

import type { Page, TestInfo } from "@playwright/test";
import * as data from "../data/my-account.data.json";
import * as actions from "@utils/base/web/actions";

export default class MyAccountPage {
  constructor(public page: Page, public workerInfo: TestInfo) {}

  async verifyPageTitle() {
    await actions.verifyPageTitle(this.page, data.title, this.workerInfo);
  }
}

Step # 4

Updating fixtures. Once we have added the steps that needs to be performed for the test, it’s time for us to update the fixtures. Your src/apps/automation-practice/fixtures/index.ts file should looks like below

import { test as baseTest } from "@playwright/test";
import CommonPage from "@common/pages/common.page";
import HomePage from "../pages/home.page";
import CreateAccountPage from "../pages/create-account.page";
import MyAccountPage from "../pages/my-account.page";

type pages = {
  commonPage: CommonPage;
  homePage: HomePage;
  createAccountPage: CreateAccountPage;
  myAccountPage: MyAccountPage;
};

const testPages = baseTest.extend<pages>({
  commonPage: async ({ page }, use, workerInfo) =>
    await use(new CommonPage(page, workerInfo)),
  homePage: async ({ page }, use, workerInfo) =>
    await use(new HomePage(page, workerInfo)),
  createAccountPage: async ({ page }, use, workerInfo) =>
    await use(new CreateAccountPage(page, workerInfo)),
  myAccountPage: async ({ page }, use, workerInfo) =>
    await use(new MyAccountPage(page, workerInfo)),
});

export const test = testPages;
export const expect = testPages.expect;
export const describe = testPages.describe;

Step # 5

Time to create our test. Before we add the test code to the *.spec.ts files, we need to add the locators in src/apps/automation-practice/locators/home.locator.ts to click on the Create Account link in home page

Add the below code to src/apps/automation-practice/locators/home.locator.ts

export const createAccountLink = "text=Create an Account";

Add the below code to src/apps/automation-practice/tests/create-account.spec.ts

import { test, describe } from "../fixtures";
import * as homePageLocators from "../locators/home.locator";
import * as createAccountLocators from "../locators/create-account.locator";

test.beforeEach(async ({ homePage }) => {
  await homePage.navigateToAutomationPractice();
});

describe("New Account", () => {
  test("Create new account", async ({
    homePage,
    commonPage,
    createAccountPage,
    myAccountPage,
  }) => {
    await homePage.clickLink(homePageLocators.createAccountLink);
    await commonPage.waitForAnimationEnd(
      createAccountLocators.createAccountButton
    );
    await createAccountPage.createAccount();
    await myAccountPage.verifyPageTitle();
  });
});

Add the below code to src/apps/automation-practice/tests/my-account.spec.ts

import { test, describe } from "../fixtures";

describe("My Account", () => {
  test("Verify account page url and title", async ({ myAccountPage }) => {
    await myAccountPage.verifyPageTitle();
  });
});

Time to test 🍹

Step # 6

Change the testMatch option in src/apps/automation-practice/playwright.config.ts as below

testMatch: "tests/create-account.spec.ts",

and run yarn test:automation-practice

Hoping that you have done everything right until now, you would now be able to see something like below

playwright-framework-implementation-part-2-screenshot-01

And you should be able to see the newly created users test data in src/apps/automation-practice/data/create-account.data.json

That’s all for today. Happie coding 📣