Playwright Test Script

Individual scripts have been written to test various parts of the system.

Tests

import './register.spec.ts';
import './login.spec.ts';
import './chat.spec.ts';

Common

// my-test.ts
import { test as base } from '@playwright/test';

export type TestOptions = {
  uid: number;
  name: string;
  password: string;
};

let uid_ = Date.now()

export const test = base.extend<TestOptions>({
  // Define an option and provide a default value.
  // We can later override it in the config.
  uid: [uid_, { option: true }],
  name: [uid_ + 'test-user', { option: true }],
  password: ['Test-Password-1', { option: true}]
});

Chat Test

import { test } from './common';
import { expect, Locator, Page } from '@playwright/test';


test.describe('Test Chat Page', () => {
  test.beforeEach(async ({ page, name, password }) => {
    await page.goto('/#/');
    await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
    await page.locator('input.mdc-text-field__input >> nth=1').fill(password);
    await page.locator('button.mdc-button:has-text("Login")').click()
  });

  test('Browse to Add Group Page', async ({ page }) => {
    // click add button
    await page.locator('#add-group').click()

    // check on add group page
    // TODO: found Add a Group cancel instead of Add a Group
    await expect(page.locator('h2 >> nth=1')).toHaveText(/Add a Group.*/)
  })

  test('Add Group', async ({ page, isMobile, uid }) => {
    test.skip(isMobile, "Add group feature not yet implemented for mobile")

    // click add button
    await page.locator('#add-group').click()

    // check on add group page
    await expect(page.locator('h2 >> nth=1')).toHaveText(/Add a Group.*/)
    
    // TODO: should this switch be tested?
    // await page.locator('button.mdc-switch >> nth=0');
    
    if (isMobile) {
      // TODO: implement this when complete - use #mobile-chat
    } else {      
      // enter group name (unique)
      await page.locator('#chat-panel input.mdc-text-field__input >> nth=0').fill(`${uid}-test-group`);
      await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=0')).toHaveValue(`${uid}-test-group`);

      // click create button
      await page.locator('#chat-panel button.mdc-button:has-text("Create")').click()
    }

    // check on chat page
    await expect(page.locator('h2 >> nth=1')).toHaveText('YaMa Chat')
  })

  test('Browse to Group Page', async ({ page, isMobile, uid }) => {
    test.skip(isMobile, "Browse to Group page not yet implemented for mobile")

    await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()

    // check on group page
    await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)
  })

  test('Browse to Group Settings Page', async ({ page, isMobile, uid }) => {
    test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")

    await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()

    // check on group page
    await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)

    // click settings button
    await page.locator(`button:has-text("settings")`).click()

    // check on settings page
    await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))
  })

  test('Add new channel', async ({ page, isMobile, uid }) => {
    test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")

    await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()

    // check on group page
    await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)

    // click settings button
    await page.locator(`button:has-text("settings")`).click()

    // check on settings page
    await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))

    // click the button
    await page.locator(`#chat-panel button:has-text("CREATE NEW CHANNEL")`).click()

    await page.locator('#chat-panel input.mdc-text-field__input >> nth=0').fill("NEWCHANNEL");
    await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=0')).toHaveValue("NEWCHANNEL");

    // click create button
    await page.locator(`#chat-panel button.mdc-button:has-text("CREATE")`).click()
  })

  test('Invite new member', async ({ page, isMobile, uid }) => {
    test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")

    await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()

    // check on group page
    await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)

    // click settings button
    await page.locator(`button:has-text("settings")`).click()

    // check on settings page
    await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))

    // click the button
    await page.locator(`#chat-panel button:has-text("INVITE NEW MEMBERS")`).click()

    // email
    await page.locator('#chat-panel input.mdc-text-field__input >> nth=0').fill("test2@test.com");
    await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=0')).toHaveValue("test2@test.com");
    // name
    await page.locator('#chat-panel input.mdc-text-field__input >> nth=1').fill("Test Name");
    await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=1')).toHaveValue("Test Name");
    // msg
    await page.locator('#chat-panel input.mdc-text-field__input >> nth=2').fill("message");
    await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=2')).toHaveValue("message");

    // click the button
    await page.locator(`#chat-panel button:has-text("INVITE NEW MEMBER")`).click()

    await expect(page.locator('#chat-screen')).toHaveText(' Select a group and a channel to start chatting');
  })

  test('Delete group', async ({ page, isMobile, uid }) => {
    test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")

    await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()

    // check on group page
    await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)

    // click settings button
    await page.locator(`button:has-text("settings")`).click()

    // check on settings page
    await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))

    // click the button
    await page.locator(`#chat-panel button:has-text("DELETE GROUP")`).click()

    await expect(page.locator('h3 >> nth=1')).toHaveText(/Delete Group Confirmation/)

    // click the button
    await page.locator(`#chat-panel button:has-text("DELETE GROUP")`).click()

    await expect(page.locator('#chat-screen')).toHaveText(' Select a group and a channel to start chatting');
  })

  test.afterEach(async ({ page }) => {
    await page.goto('/#/');
    await page.locator('button:has-text("Logout")').click();
  });
})

Login Test

import { test } from './common';
import { expect, Locator, Page } from '@playwright/test';

test.describe('Test Login Page', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/#/');
  });

  test('Browse to Login Page', async ({ page }) => {
    // check on login page
    await expect(page.locator('button.mdc-button')).toHaveText("Login")
  })

  test('Use Login Form - Success', async ({ page, name, password }) => {
    // enter username
    await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
    await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name);
    
    // enter password
    await page.locator('input.mdc-text-field__input >> nth=1').fill(password);
    await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue(password);
    
    // click login button
    await page.locator('button.mdc-button').click()

    // check on chat page
    await expect(page.locator('h2 >> nth=1')).toContainText('YaMa Chat')
  })

  test('Use Login Form - Invalid Data', async ({ page, name, password }) => {
    // enter username
    await page.locator('input.mdc-text-field__input >> nth=0').fill(name + "wrong");
    await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name + "wrong");

    // enter password
    await page.locator('input.mdc-text-field__input >> nth=1').fill(password);
    await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue(password);

    // click login button
    await Promise.all([
        page.locator('button.mdc-button').click(),
        page.waitForResponse(response => response.status() === 401),
    ])
  })

  test('Browse to Register Form', async ({ page }) => {
    // click register link
    await page.locator('a:has-text("Create Account")').click()

    // check on register page
    await expect(page.locator('h1 >> nth=1')).toHaveText('Create Account')
  })
})

Registration Test

import { test } from './common';
import { expect, Locator, Page } from '@playwright/test';

test.describe('Test Register Page', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/#/register/');
  });

  test('Use Register Form - Success', async ({ page, name, password }) => {
    // enter name
    await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
    await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name);
    
    // enter date of birth
    await page.locator('input.mdc-text-field__input >> nth=1').fill('1970-01-01');
    await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue('1970-01-01');
    
    // enter phone number
    await page.locator('input.mdc-text-field__input >> nth=2').fill('12345');
    await expect(page.locator('input.mdc-text-field__input >> nth=2')).toHaveValue('12345');

    // enter email address (unique)
    await page.locator('input.mdc-text-field__input >> nth=3').fill(name + '@test.com');
    await expect(page.locator('input.mdc-text-field__input >> nth=3')).toHaveValue(name + '@test.com');

    // enter username (unique)
    await page.locator('input.mdc-text-field__input >> nth=4').fill(name);
    await expect(page.locator('input.mdc-text-field__input >> nth=4')).toHaveValue(name);

    // enter password
    await page.locator('input.mdc-text-field__input >> nth=5').fill(password);
    await expect(page.locator('input.mdc-text-field__input >> nth=5')).toHaveValue(password);

    // confirm password
    await page.locator('input.mdc-text-field__input >> nth=6').fill(password);
    await expect(page.locator('input.mdc-text-field__input >> nth=6')).toHaveValue(password);

    // click register button
    await Promise.all([
        page.locator('button.mdc-button').click(),
        page.waitForResponse(response => response.status() === 200),
    ])
    // need a way to check if the registration is done, until then
    await page.evaluate(() => {
        return new Promise((resolve) => setTimeout(resolve, 5000));
    })

    // check on email verification page
    await expect(page.locator('h1 >> nth=2')).toHaveText('Email Verification')
  })
  
  test('Use Register Form - Invalid Data', async ({ page, name }) => {
    // get unique identifier
    const uid = Date.now();

    // enter name
    await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
    await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name);
    
    // enter invalid date of birth
    await page.locator('input.mdc-text-field__input >> nth=1').fill('2070-01-01');
    await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue('2070-01-01');
    
    // enter phone number
    await page.locator('input.mdc-text-field__input >> nth=2').fill('12345');
    await expect(page.locator('input.mdc-text-field__input >> nth=2')).toHaveValue('12345');
    
    // enter invalid email address (unique)
    await page.locator('input.mdc-text-field__input >> nth=3').fill(name);
    await expect(page.locator('input.mdc-text-field__input >> nth=3')).toHaveValue(name);

    // enter username (unique)
    await page.locator('input.mdc-text-field__input >> nth=4').fill(name + '@test-user.com');
    await expect(page.locator('input.mdc-text-field__input >> nth=4')).toHaveValue(name + '@test-user.com');

    // enter invalid password
    await page.locator('input.mdc-text-field__input >> nth=5').fill('password1');
    await expect(page.locator('input.mdc-text-field__input >> nth=5')).toHaveValue('password1');

    // confirm invalid password
    await page.locator('input.mdc-text-field__input >> nth=6').fill('password2');
    await expect(page.locator('input.mdc-text-field__input >> nth=6')).toHaveValue("password2");

    // check error messages
    await expect(page.locator('div#dob-error.input_error.invalid')).toHaveText('Invalid date of birth.');
    await expect(page.locator('div#email-error.input_error.invalid')).toHaveText('Please enter a valid email address.');
    await expect(page.locator('div#username-error.input_error.invalid')).toHaveText('Usernames must have at least 3 characters and contain no spaces or the \'@\' symbol.');
    await expect(page.locator('div#password-error.input_error.invalid')).toHaveText('Passwords must have at least 8 characters. Please use lower-case and upper-case characters, numbers, and special characters.');
    
    // click register button
    await page.locator('button.mdc-button').click()
    await page.waitForLoadState('load');

    // check on register page
    await expect(page.locator('h1 >> nth=1')).toHaveText('Create Account')

    // check error messages
    await expect(page.locator('div#confirmation-error.input_error.invalid')).toHaveText('The entered passwords do not match.');
  })
})