From 35770b11e06d2130f05db9a0c45a2e8e531283dc Mon Sep 17 00:00:00 2001 From: Dev Singh Date: Fri, 10 Jan 2025 21:20:33 -0600 Subject: [PATCH 1/7] reorder the e2e tests directory --- playwright.config.ts | 2 +- {e2e => tests/e2e}/base.ts | 0 {e2e/tests => tests/e2e}/login.spec.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename {e2e => tests/e2e}/base.ts (100%) rename {e2e/tests => tests/e2e}/login.spec.ts (97%) diff --git a/playwright.config.ts b/playwright.config.ts index 31747257..61d774b5 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,7 +1,7 @@ import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ - testDir: './e2e/tests', + testDir: './tests/e2e/', /* Run tests in files in parallel */ fullyParallel: false, /* Fail the build on CI if you accidentally left test.only in the source code. */ diff --git a/e2e/base.ts b/tests/e2e/base.ts similarity index 100% rename from e2e/base.ts rename to tests/e2e/base.ts diff --git a/e2e/tests/login.spec.ts b/tests/e2e/login.spec.ts similarity index 97% rename from e2e/tests/login.spec.ts rename to tests/e2e/login.spec.ts index 84531599..75bf4f87 100644 --- a/e2e/tests/login.spec.ts +++ b/tests/e2e/login.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test'; -import { test } from '../base'; +import { test } from './base'; import { describe } from 'node:test'; describe("Login tests", () => { From 57151d04355610c68a1a1a0a3a0a86a0d842312e Mon Sep 17 00:00:00 2001 From: Dev Singh Date: Fri, 10 Jan 2025 21:23:08 -0600 Subject: [PATCH 2/7] fix linting/formatting --- tests/e2e/base.ts | 40 +++++++++++++++++++++-------------- tests/e2e/login.spec.ts | 46 +++++++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/tests/e2e/base.ts b/tests/e2e/base.ts index f85d0856..d767f7e2 100644 --- a/tests/e2e/base.ts +++ b/tests/e2e/base.ts @@ -1,4 +1,4 @@ -import { test as base } from '@playwright/test'; +import { test as base } from "@playwright/test"; import { SecretsManagerClient, GetSecretValueCommand, @@ -25,32 +25,40 @@ export const getSecretValue = async ( }; async function getSecrets() { - let response = { PLAYWRIGHT_USERNAME: '', PLAYWRIGHT_PASSWORD: '' } + let response = { PLAYWRIGHT_USERNAME: "", PLAYWRIGHT_PASSWORD: "" }; let keyData; if (!process.env.PLAYWRIGHT_USERNAME || !process.env.PLAYWRIGHT_PASSWORD) { - keyData = await getSecretValue('infra-core-api-config') + keyData = await getSecretValue("infra-core-api-config"); } - response['PLAYWRIGHT_USERNAME'] = process.env.PLAYWRIGHT_USERNAME || (keyData ? keyData['playwright_username'] : ''); - response['PLAYWRIGHT_PASSWORD'] = process.env.PLAYWRIGHT_PASSWORD || (keyData ? keyData['playwright_password'] : ''); + response["PLAYWRIGHT_USERNAME"] = + process.env.PLAYWRIGHT_USERNAME || + (keyData ? keyData["playwright_username"] : ""); + response["PLAYWRIGHT_PASSWORD"] = + process.env.PLAYWRIGHT_PASSWORD || + (keyData ? keyData["playwright_password"] : ""); return response; } const secrets = await getSecrets(); async function becomeUser(page) { - await page.goto('https://manage.qa.acmuiuc.org/login'); - await page.getByRole('button', { name: 'Sign in with Illinois NetID' }).click(); - await page.getByPlaceholder('NetID@illinois.edu').click(); - await page.getByPlaceholder('NetID@illinois.edu').fill(secrets['PLAYWRIGHT_USERNAME']); - await page.getByPlaceholder('NetID@illinois.edu').press('Enter'); - await page.getByPlaceholder('Password').click(); - await page.getByPlaceholder('Password').fill(secrets['PLAYWRIGHT_PASSWORD']); - await page.getByRole('button', { name: 'Sign in' }).click(); - await page.getByRole('button', { name: 'No' }).click(); + await page.goto("https://manage.qa.acmuiuc.org/login"); + await page + .getByRole("button", { name: "Sign in with Illinois NetID" }) + .click(); + await page.getByPlaceholder("NetID@illinois.edu").click(); + await page + .getByPlaceholder("NetID@illinois.edu") + .fill(secrets["PLAYWRIGHT_USERNAME"]); + await page.getByPlaceholder("NetID@illinois.edu").press("Enter"); + await page.getByPlaceholder("Password").click(); + await page.getByPlaceholder("Password").fill(secrets["PLAYWRIGHT_PASSWORD"]); + await page.getByRole("button", { name: "Sign in" }).click(); + await page.getByRole("button", { name: "No" }).click(); } export const test = base.extend<{ becomeUser: (page) => Promise }>({ - becomeUser: async ({ }, use) => { - use(becomeUser) + becomeUser: async ({}, use) => { + use(becomeUser); }, }); diff --git a/tests/e2e/login.spec.ts b/tests/e2e/login.spec.ts index 75bf4f87..e0aeab52 100644 --- a/tests/e2e/login.spec.ts +++ b/tests/e2e/login.spec.ts @@ -1,20 +1,34 @@ - -import { expect } from '@playwright/test'; -import { test } from './base'; -import { describe } from 'node:test'; +import { expect } from "@playwright/test"; +import { test } from "./base"; +import { describe } from "node:test"; describe("Login tests", () => { - test('A user can login and view the home screen', async ({ page, becomeUser }) => { + test("A user can login and view the home screen", async ({ + page, + becomeUser, + }) => { await becomeUser(page); - await expect(page.locator('a').filter({ hasText: 'Management Portal DEV ENV' })).toBeVisible(); - await expect(page.locator('a').filter({ hasText: 'Events' })).toBeVisible(); - await expect(page.locator('a').filter({ hasText: 'Ticketing/Merch' })).toBeVisible(); - await expect(page.locator('a').filter({ hasText: 'IAM' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'ACM Logo Management Portal' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'P', exact: true })).toBeVisible(); - await page.getByRole('link', { name: 'P', exact: true }).click(); - await expect(page.getByLabel('PMy Account')).toContainText('Name Playwright Core User'); - await expect(page.getByLabel('PMy Account')).toContainText('Emailcore-e2e-testing@acm.illinois.edu'); - expect(page.url()).toEqual('https://manage.qa.acmuiuc.org/home'); + await expect( + page.locator("a").filter({ hasText: "Management Portal DEV ENV" }), + ).toBeVisible(); + await expect(page.locator("a").filter({ hasText: "Events" })).toBeVisible(); + await expect( + page.locator("a").filter({ hasText: "Ticketing/Merch" }), + ).toBeVisible(); + await expect(page.locator("a").filter({ hasText: "IAM" })).toBeVisible(); + await expect( + page.getByRole("link", { name: "ACM Logo Management Portal" }), + ).toBeVisible(); + await expect( + page.getByRole("link", { name: "P", exact: true }), + ).toBeVisible(); + await page.getByRole("link", { name: "P", exact: true }).click(); + await expect(page.getByLabel("PMy Account")).toContainText( + "Name Playwright Core User", + ); + await expect(page.getByLabel("PMy Account")).toContainText( + "Emailcore-e2e-testing@acm.illinois.edu", + ); + expect(page.url()).toEqual("https://manage.qa.acmuiuc.org/home"); }); -}) +}); From 138e7736d64bb6c8cefbd63a2da8339658bbff9f Mon Sep 17 00:00:00 2001 From: Dev Singh Date: Fri, 10 Jan 2025 21:32:34 -0600 Subject: [PATCH 3/7] add data-testid to events table --- src/ui/pages/events/ViewEvents.page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/pages/events/ViewEvents.page.tsx b/src/ui/pages/events/ViewEvents.page.tsx index a77f9537..0d1334f9 100644 --- a/src/ui/pages/events/ViewEvents.page.tsx +++ b/src/ui/pages/events/ViewEvents.page.tsx @@ -169,7 +169,7 @@ export const ViewEventsPage: React.FC = () => { {showPrevious ? 'Hide Previous Events' : 'Show Previous Events'} - +
Title From b0cc9e4b65ba2d94497846b63f8e9bf4fe5d1cce Mon Sep 17 00:00:00 2001 From: Dev Singh Date: Fri, 10 Jan 2025 21:50:57 -0600 Subject: [PATCH 4/7] add a basic upcoming events view test --- playwright.config.ts | 2 +- tests/e2e/base.ts | 16 ++++++++++++++- tests/e2e/events.spec.ts | 43 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/events.spec.ts diff --git a/playwright.config.ts b/playwright.config.ts index 61d774b5..6610300d 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -11,7 +11,7 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: process.env.CI ? 'github' : 'html', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ diff --git a/tests/e2e/base.ts b/tests/e2e/base.ts index d767f7e2..efcb60c3 100644 --- a/tests/e2e/base.ts +++ b/tests/e2e/base.ts @@ -57,8 +57,22 @@ async function becomeUser(page) { await page.getByRole("button", { name: "No" }).click(); } +export async function getUpcomingEvents() { + const data = await fetch('https://infra-core-api.aws.qa.acmuiuc.org/api/v1/events?upcomingOnly=true'); + return await data.json() as Record[]; +} + +export async function getAllEvents() { + const data = await fetch('https://infra-core-api.aws.qa.acmuiuc.org/api/v1/events'); + return await data.json() as Record[]; +} + +export function capitalizeFirstLetter(string: string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + export const test = base.extend<{ becomeUser: (page) => Promise }>({ - becomeUser: async ({}, use) => { + becomeUser: async ({ }, use) => { use(becomeUser); }, }); diff --git a/tests/e2e/events.spec.ts b/tests/e2e/events.spec.ts new file mode 100644 index 00000000..f423953d --- /dev/null +++ b/tests/e2e/events.spec.ts @@ -0,0 +1,43 @@ +import { expect } from "@playwright/test"; +import { capitalizeFirstLetter, getUpcomingEvents, test } from "./base"; +import { describe } from "node:test"; + +describe("Events tests", () => { + test("A user can login and view the upcoming events", async ({ + page, + becomeUser, + }) => { + await becomeUser(page); + await page.locator('a').filter({ hasText: 'Events' }).click(); + await expect(page.getByRole('heading')).toContainText('Core Management Service (NonProd)'); + await expect(page.getByRole('button', { name: 'New Calendar Event' })).toBeVisible(); + await expect(page.getByRole('button', { name: 'Show Previous Events' })).toBeVisible(); + + const table = page.getByTestId('events-table'); + await expect(table).toBeVisible(); + + const rows = await table.locator('tbody tr').all(); + const expectedTableData = await getUpcomingEvents(); + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + const expectedData = expectedTableData[i]; + + const title = await row.locator('td:nth-child(1)').innerText(); + const location = await row.locator('td:nth-child(4)').innerText(); + const description = await row.locator('td:nth-child(5)').innerText(); + const host = await row.locator('td:nth-child(6)').innerText(); + const featured = await row.locator('td:nth-child(7)').innerText(); + const repeats = await row.locator('td:nth-child(8)').innerText(); + + expect(title).toEqual(expectedData.title); + expect(location).toEqual(expectedData.location); + expect(description).toEqual(expectedData.description); + expect(host).toEqual(expectedData.host); + expect(featured).toEqual(expectedData.featured ? "Yes" : "No"); + expect(repeats).toEqual(capitalizeFirstLetter(expectedData.repeats)); + } + + expect(page.url()).toEqual("https://manage.qa.acmuiuc.org/events/manage"); + }); +}); From bbf2e69abb85808c86c5e1e446fd4833d82cc422 Mon Sep 17 00:00:00 2001 From: Dev Singh Date: Fri, 10 Jan 2025 21:55:41 -0600 Subject: [PATCH 5/7] update --- .husky/pre-commit | 4 +--- tests/e2e/base.ts | 22 +++++++++++++--------- tests/e2e/events.spec.ts | 31 ++++++++++++++++++------------- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 64947b3a..de2afa02 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,6 +1,3 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - # Get all staged files STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR) @@ -8,6 +5,7 @@ if [ -n "$STAGED_FILES" ]; then echo "Running lint with fix on staged files..." # Run lint on all files (modifies files in the working directory) yarn lint --fix + yarn prettier:write echo "Re-adding originally staged files to the staging area..." # Re-add only the originally staged files diff --git a/tests/e2e/base.ts b/tests/e2e/base.ts index efcb60c3..a1b9746d 100644 --- a/tests/e2e/base.ts +++ b/tests/e2e/base.ts @@ -41,6 +41,10 @@ async function getSecrets() { const secrets = await getSecrets(); +export function capitalizeFirstLetter(string: string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + async function becomeUser(page) { await page.goto("https://manage.qa.acmuiuc.org/login"); await page @@ -58,21 +62,21 @@ async function becomeUser(page) { } export async function getUpcomingEvents() { - const data = await fetch('https://infra-core-api.aws.qa.acmuiuc.org/api/v1/events?upcomingOnly=true'); - return await data.json() as Record[]; + const data = await fetch( + "https://infra-core-api.aws.qa.acmuiuc.org/api/v1/events?upcomingOnly=true", + ); + return (await data.json()) as Record[]; } export async function getAllEvents() { - const data = await fetch('https://infra-core-api.aws.qa.acmuiuc.org/api/v1/events'); - return await data.json() as Record[]; -} - -export function capitalizeFirstLetter(string: string) { - return string.charAt(0).toUpperCase() + string.slice(1); + const data = await fetch( + "https://infra-core-api.aws.qa.acmuiuc.org/api/v1/events", + ); + return (await data.json()) as Record[]; } export const test = base.extend<{ becomeUser: (page) => Promise }>({ - becomeUser: async ({ }, use) => { + becomeUser: async ({}, use) => { use(becomeUser); }, }); diff --git a/tests/e2e/events.spec.ts b/tests/e2e/events.spec.ts index f423953d..2b6bad0b 100644 --- a/tests/e2e/events.spec.ts +++ b/tests/e2e/events.spec.ts @@ -8,27 +8,32 @@ describe("Events tests", () => { becomeUser, }) => { await becomeUser(page); - await page.locator('a').filter({ hasText: 'Events' }).click(); - await expect(page.getByRole('heading')).toContainText('Core Management Service (NonProd)'); - await expect(page.getByRole('button', { name: 'New Calendar Event' })).toBeVisible(); - await expect(page.getByRole('button', { name: 'Show Previous Events' })).toBeVisible(); + await page.locator("a").filter({ hasText: "Events" }).click(); + await expect(page.getByRole("heading")).toContainText( + "Core Management Service (NonProd)", + ); + await expect( + page.getByRole("button", { name: "New Calendar Event" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "Show Previous Events" }), + ).toBeVisible(); - const table = page.getByTestId('events-table'); + const table = page.getByTestId("events-table"); await expect(table).toBeVisible(); - const rows = await table.locator('tbody tr').all(); + const rows = await table.locator("tbody tr").all(); const expectedTableData = await getUpcomingEvents(); for (let i = 0; i < rows.length; i++) { const row = rows[i]; const expectedData = expectedTableData[i]; - - const title = await row.locator('td:nth-child(1)').innerText(); - const location = await row.locator('td:nth-child(4)').innerText(); - const description = await row.locator('td:nth-child(5)').innerText(); - const host = await row.locator('td:nth-child(6)').innerText(); - const featured = await row.locator('td:nth-child(7)').innerText(); - const repeats = await row.locator('td:nth-child(8)').innerText(); + const title = await row.locator("td:nth-child(1)").innerText(); + const location = await row.locator("td:nth-child(4)").innerText(); + const description = await row.locator("td:nth-child(5)").innerText(); + const host = await row.locator("td:nth-child(6)").innerText(); + const featured = await row.locator("td:nth-child(7)").innerText(); + const repeats = await row.locator("td:nth-child(8)").innerText(); expect(title).toEqual(expectedData.title); expect(location).toEqual(expectedData.location); From 1997364be46a416bc2f12c043908e3daf860f3b2 Mon Sep 17 00:00:00 2001 From: Dev Singh Date: Fri, 10 Jan 2025 21:58:26 -0600 Subject: [PATCH 6/7] fix pre-commit --- .husky/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index de2afa02..081670e4 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -5,7 +5,7 @@ if [ -n "$STAGED_FILES" ]; then echo "Running lint with fix on staged files..." # Run lint on all files (modifies files in the working directory) yarn lint --fix - yarn prettier:write + npx prettier --write $STAGED_FILES || true # skip files that don't have valid parsers echo "Re-adding originally staged files to the staging area..." # Re-add only the originally staged files From 68b503bfa377e259839bb49c6aa979f988770ee7 Mon Sep 17 00:00:00 2001 From: Dev Singh Date: Fri, 10 Jan 2025 21:59:47 -0600 Subject: [PATCH 7/7] Revert "fix pre-commit" This reverts commit 1997364be46a416bc2f12c043908e3daf860f3b2. --- .husky/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 081670e4..de2afa02 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -5,7 +5,7 @@ if [ -n "$STAGED_FILES" ]; then echo "Running lint with fix on staged files..." # Run lint on all files (modifies files in the working directory) yarn lint --fix - npx prettier --write $STAGED_FILES || true # skip files that don't have valid parsers + yarn prettier:write echo "Re-adding originally staged files to the staging area..." # Re-add only the originally staged files