From 02f9a379e20def2ce1fe21922ae245f4b9d2790e Mon Sep 17 00:00:00 2001 From: Sudip Bhattarai Date: Sun, 17 Nov 2024 18:10:00 +0545 Subject: [PATCH] Test: Loop over all user-types --- integration_test/lib/fixtures/poll.ts | 26 ++-- integration_test/lib/helpers/auth.ts | 4 +- integration_test/lib/helpers/page.ts | 7 + integration_test/lib/helpers/userRoles.ts | 72 ++++++++++ integration_test/tests/0-common/comon.spec.ts | 124 +++++++++++------- 5 files changed, 176 insertions(+), 57 deletions(-) create mode 100644 integration_test/lib/helpers/userRoles.ts diff --git a/integration_test/lib/fixtures/poll.ts b/integration_test/lib/fixtures/poll.ts index e73246a..a13cdb0 100644 --- a/integration_test/lib/fixtures/poll.ts +++ b/integration_test/lib/fixtures/poll.ts @@ -8,6 +8,7 @@ import { } from '@helpers/page'; import HomePage from '@pages/homePage'; import PollPage from '@pages/pollPage'; +import {Page} from "@playwright/test"; type pollEnableType = | 'CreatePoll' @@ -29,6 +30,7 @@ export const test = base.extend({ wallet: organizerWallet, }); + let pages: Page[] = []; const homePage = new HomePage(organizerPage); await homePage.goto(); const organizerPollPage = new PollPage(organizerPage); @@ -54,18 +56,17 @@ export const test = base.extend({ 'vote-no-button', 'vote-abstain-button', ]; + pages = [delegatePage, delegate2Page, delegate3Page]; await Promise.all( - [delegatePage, delegate2Page, delegate3Page].map( - async (userPage, index) => { - const userPollPage = new PollPage(userPage); - await userPollPage.goto(pollId); - // cast vote - await userPage.getByTestId(votes[index]).click(); - await userPage.getByText('Vote recorded').isVisible(); - await userPage.close(); - } - ) + pages.map(async (userPage, index) => { + const userPollPage = new PollPage(userPage); + await userPollPage.goto(pollId); + // cast vote + await userPage.getByTestId(votes[index]).click(); + await userPage.getByText('Vote recorded').isVisible(); + // await userPage.close(); + }) ); await organizerPollPage.goto(pollId); await organizerPollPage.endVoting(); @@ -74,6 +75,11 @@ export const test = base.extend({ await use(pollId); + await Promise.all( + pages.map(async (userPage) => { + userPage.close(); + }) + ); // cleanup if (pollType !== 'NoAction') { await organizerPollPage.deletePoll(); diff --git a/integration_test/lib/helpers/auth.ts b/integration_test/lib/helpers/auth.ts index 9adc356..9ecf047 100644 --- a/integration_test/lib/helpers/auth.ts +++ b/integration_test/lib/helpers/auth.ts @@ -20,10 +20,10 @@ export async function createAuth({ await importWallet(page, wallet); await page.route('/api/getUser/*', (route, request) => { - const userId = request.url().split('/').pop(); + const userId = request.url().split('/').pop(); if (userId) { page.evaluate((id) => { - localStorage.setItem('userId', id); + localStorage.setItem('userId', id); }, userId); } route.continue(); diff --git a/integration_test/lib/helpers/page.ts b/integration_test/lib/helpers/page.ts index 9d802e7..3ede9a7 100644 --- a/integration_test/lib/helpers/page.ts +++ b/integration_test/lib/helpers/page.ts @@ -8,6 +8,7 @@ import { delegate2Wallet, delegate3Wallet, delegateWallet, + organizerWallet, } from '@constants/staticWallets'; interface NewPageConfig { @@ -37,6 +38,12 @@ export async function createNewPageWithWallet( return newPage; } +export async function newOrganizerPage(browser) { + return await createNewPageWithWallet(browser, { + storageState: '.auth/organizer.json', + wallet: organizerWallet, + }); +} export async function newDelegatePage(browser) { return await createNewPageWithWallet(browser, { diff --git a/integration_test/lib/helpers/userRoles.ts b/integration_test/lib/helpers/userRoles.ts new file mode 100644 index 0000000..064f974 --- /dev/null +++ b/integration_test/lib/helpers/userRoles.ts @@ -0,0 +1,72 @@ +import { + newAlternate2Page, + newDelegatePage, + newOrganizerPage, +} from '@helpers/page'; + +import { Page } from '@playwright/test'; + +type UserRole = + | 'Delegate' + | 'Alternate' + | 'Organizer' + | 'Anonymous' + | 'Voter' + | 'All'; + +export function getUserPages(browser, userRole?: UserRole): Promise { + // setup + let users: Promise[] = []; + if (userRole == 'Delegate') { + users.push(newOrganizerPage(browser)); + } else if (userRole == 'Alternate') { + users.push(newOrganizerPage(browser)); + } else if (userRole == 'Organizer') { + users.push(newOrganizerPage(browser)); + } else if (userRole == 'All' || userRole == undefined) { + users = [ + newOrganizerPage(browser), + newAlternate2Page(browser), + newDelegatePage(browser), + browser.newPage(), + ]; + } + return Promise.all(users); +} + +export function forEachUser( + handler: (user: { + role: string; + loader: (browser: unknown) => Promise; + }) => unknown +) { + const users: { + role: string; + handler: (browser: unknown) => Promise; + }[] = [ + { + role: 'Alternate', + handler: (browser) => newAlternate2Page(browser), + }, + { + role: 'Delegate', + handler: (browser) => newAlternate2Page(browser), + }, + { + role: 'Organizer', + handler: (browser) => newAlternate2Page(browser), + }, + { + role: 'Anonymous', + handler: (browser) => browser.newPage(), + }, + ]; + users.forEach((u) => { + handler({ + role: u.role, + loader: (browser) => { + return u.handler(browser); + }, + }); + }); +} diff --git a/integration_test/tests/0-common/comon.spec.ts b/integration_test/tests/0-common/comon.spec.ts index 667bb9f..cfca0d1 100644 --- a/integration_test/tests/0-common/comon.spec.ts +++ b/integration_test/tests/0-common/comon.spec.ts @@ -1,6 +1,7 @@ import { setAllureEpic } from '@helpers/allure'; -import { expect, Page } from '@playwright/test'; +import { expect, Locator, Page } from '@playwright/test'; import { test } from '@fixtures/poll'; +import { forEachUser, getUserPages } from '@helpers/userRoles'; test.beforeEach(async () => { await setAllureEpic('0. All Users'); @@ -19,40 +20,50 @@ test.describe('Polls', () => { * Acceptance Criteria: Given that I am looking at a given poll, when I look at it, then I can see its status */ test('0-1A-1. Given any user, can view poll status in home page', async ({ - page, + browser, pollId, }) => { - await page.goto('/'); - await page.waitForSelector('[data-testid^="poll-card-"]'); + const pages = await getUserPages(browser); + + await Promise.all( + pages.map(async (page) => { + await page.goto('/'); + await page.waitForSelector('[data-testid^="poll-card-"]'); - const pollCards = page.locator('[data-testid^="poll-card-"]'); + const pollCards = page.locator('[data-testid^="poll-card-"]'); - const pollCardCount = await pollCards.count(); - expect(pollCardCount).toBeGreaterThan(0); + const pollCardCount = await pollCards.count(); + expect(pollCardCount).toBeGreaterThan(0); - // Check that each poll card has a 'poll-status-chip' with "Concluded" or "Pending" - for (let i = 0; i < pollCardCount; i++) { - const statusChip = pollCards - .nth(i) - .locator('[data-testid="poll-status-chip"]'); + // Check that each poll card has a 'poll-status-chip' with "Concluded" or "Pending" + for (let i = 0; i < pollCardCount; i++) { + const statusChip = pollCards + .nth(i) + .locator('[data-testid="poll-status-chip"]'); - await expect(statusChip).toBeVisible(); + await expect(statusChip).toBeVisible(); - const statusText = await statusChip.textContent(); - expect(['Concluded', 'Pending', 'Voting']).toContain(statusText); - } + const statusText = await statusChip.textContent(); + expect(['Concluded', 'Pending', 'Voting']).toContain(statusText); + } + }) + ); }); - test('0-1A-2. Given any user, can view poll status in poll page', async ({ - page, - pollId, - }) => { - await page.goto(`/polls/${pollId}`); - const pollPageStatusChip = page.getByTestId('poll-page-status-chip'); - await expect(pollPageStatusChip).toBeVisible(); + forEachUser((user) => { + test(`0-1A-2. Given ${user.role} user, can view poll status in poll page`, async ({ + pollId, + browser, + }) => { + const page = await user.loader(browser); + await page.goto(`/polls/${pollId}`); - const statusText = await pollPageStatusChip.textContent(); - expect(['Concluded', 'Pending', 'Voting']).toContain(statusText); + const pollPageStatusChip = page.getByTestId('poll-page-status-chip'); + await expect(pollPageStatusChip).toBeVisible(); + + const statusText = await pollPageStatusChip.textContent(); + expect(['Concluded', 'Pending', 'Voting']).toContain(statusText); + }); }); }); test.describe('Polls', () => { @@ -77,26 +88,32 @@ test.describe('Polls', () => { * *results of a poll should never be displayed before the close of a poll */ test('0-1B. Given any user, can view poll results', async ({ - page, + browser, pollId, }) => { - await page.goto(`/polls/${pollId}`); - const pollPageStatusChip = page.getByTestId('poll-page-status-chip'); - await expect(pollPageStatusChip).toBeVisible(); - - await expect(page.getByTestId('results-yes')).toBeVisible(); - await page.getByTestId('results-no').isVisible(); - await page.getByTestId('results-abstain').isVisible(); - await page.goto(`/polls/${pollId}`); - - const yesCount = page.getByTestId('yes-count'); - const noCount = page.getByTestId('no-count'); - const abstainCount = page.getByTestId('abstain-count'); - - // Assert the text content for each count - await expect(yesCount).toHaveText('1'); - await expect(noCount).toHaveText('1'); - await expect(abstainCount).toHaveText('1'); + const pages = await getUserPages(browser); + + await Promise.all( + pages.map(async (page) => { + await page.goto(`/polls/${pollId}`); + const pollPageStatusChip = page.getByTestId('poll-page-status-chip'); + await expect(pollPageStatusChip).toBeVisible(); + + await expect(page.getByTestId('results-yes')).toBeVisible(); + await page.getByTestId('results-no').isVisible(); + await page.getByTestId('results-abstain').isVisible(); + await page.goto(`/polls/${pollId}`); + + const yesCount = page.getByTestId('yes-count'); + const noCount = page.getByTestId('no-count'); + const abstainCount = page.getByTestId('abstain-count'); + + // Assert the text content for each count + await expect(yesCount).toHaveText('1'); + await expect(noCount).toHaveText('1'); + await expect(abstainCount).toHaveText('1'); + }) + ); }); }); @@ -160,7 +177,7 @@ test.describe('User profile', () => { * Description: By going to the profile page of a delegate or alternate I can review their voting record * * User Story: As an observer I want to know how a given delegate or alternate has voted, so that I can examine their record - * + *` * Acceptance Criteria 1: Given that I am on the page listing delegates and alternates, when I press on a given delegate or alternate, then I will go to their profile page and see their voting record * * Acceptance Criteria 2: Given that I am on the results page of a closed poll, when I press on the tile of a given voter, then I am taken to their profile page and can see their voting record @@ -169,7 +186,24 @@ test.describe('User profile', () => { test('0-2A-1. Can navigate to user profile from delegate/alternate listing page', async ({ page, }) => { - throw new Error('Not Implemented'); + await page.goto('/'); + const table = page.getByTestId('representatives-table'); + // Locate the buttons + const delegates = await table + .locator('[data-testid^="delegate-name-"]') + .all(); + + const alternates = await table + .locator('[data-testid^="alternate-name-"]') + .all(); + + await Promise.all( + [...delegates, ...alternates].map(async (rep: Locator) => { + const href = await rep.locator('a').getAttribute('href'); + await expect(href).toMatch('//representatives/d+$/'); + }) + ); + // should navigate to /representatives/xx }); test('0-2A-1. Can navigate to user profile from voter view in poll results page', async ({