From 1a4c5ee3e19aec3358986ec0bb6ffd91d307a69e Mon Sep 17 00:00:00 2001 From: Sebastien Castiel Date: Sat, 2 Aug 2025 10:36:42 -0400 Subject: [PATCH] Add expense creation to E2E tests using Page Object Model --- .../[groupId]/expenses/expense-card.tsx | 2 + tests/create-group.spec.ts | 43 +++++++++++++------ tests/{ => pom}/create-group-page.ts | 0 tests/pom/expense-page.ts | 31 +++++++++++++ tests/pom/group-page.ts | 21 +++++++++ 5 files changed, 84 insertions(+), 13 deletions(-) rename tests/{ => pom}/create-group-page.ts (100%) create mode 100644 tests/pom/expense-page.ts create mode 100644 tests/pom/group-page.ts diff --git a/src/app/groups/[groupId]/expenses/expense-card.tsx b/src/app/groups/[groupId]/expenses/expense-card.tsx index 0e89c37..5cf5ac6 100644 --- a/src/app/groups/[groupId]/expenses/expense-card.tsx +++ b/src/app/groups/[groupId]/expenses/expense-card.tsx @@ -44,6 +44,7 @@ export function ExpenseCard({ expense, currency, groupId }: Props) { return (
{formatCurrency(currency, expense.amount, locale)}
diff --git a/tests/create-group.spec.ts b/tests/create-group.spec.ts index e9f11b5..67bf5c1 100644 --- a/tests/create-group.spec.ts +++ b/tests/create-group.spec.ts @@ -1,21 +1,38 @@ import { expect, test } from '@playwright/test' -import { CreateGroupPage } from './create-group-page' +import { CreateGroupPage } from './pom/create-group-page' +import { ExpensePage } from './pom/expense-page' +import { GroupPage } from './pom/group-page' -test('Create a new group', async ({ page }) => { +test('Create a new group and add an expense', async ({ page }) => { const createGroupPage = new CreateGroupPage(page) + const groupPage = new GroupPage(page) + const expensePage = new ExpensePage(page) - await createGroupPage.navigate() - await createGroupPage.fillGroupName('New Test Group') - await createGroupPage.fillCurrency('USD') - await createGroupPage.fillAdditionalInfo('This is a test group.') + await test.step('Create a new group', async () => { + await createGroupPage.navigate() + await createGroupPage.fillGroupName('New Test Group') + await createGroupPage.fillCurrency('USD') + await createGroupPage.fillAdditionalInfo('This is a test group.') + await createGroupPage.addParticipant('John', 0) + await createGroupPage.addParticipant('Jane', 1) + await createGroupPage.submit() + }) - await createGroupPage.addParticipant('John', 0) - await createGroupPage.addParticipant('Jane', 1) + await test.step('Check that the group is created', async () => { + await expect(groupPage.title).toHaveText('New Test Group') + }) - await createGroupPage.submit() + await test.step('Create an expense', async () => { + await groupPage.createExpense() + await expensePage.fillTitle('Coffee') + await expensePage.fillAmount('4.5') + await expensePage.selectPayer('John') + await expensePage.submit() + }) - await page.waitForURL(/.*\/groups\/.*\/expenses/) - await expect( - page.getByRole('heading', { name: 'New Test Group' }), - ).toBeVisible() + await test.step('Check that the expense is created', async () => { + const expenseCard = groupPage.getExpenseCard('Coffee') + await expect(expenseCard).toBeVisible() + await expect(expenseCard.locator('[data-amount]')).toHaveText('USD4.50') + }) }) diff --git a/tests/create-group-page.ts b/tests/pom/create-group-page.ts similarity index 100% rename from tests/create-group-page.ts rename to tests/pom/create-group-page.ts diff --git a/tests/pom/expense-page.ts b/tests/pom/expense-page.ts new file mode 100644 index 0000000..e2cb942 --- /dev/null +++ b/tests/pom/expense-page.ts @@ -0,0 +1,31 @@ +import { Page } from '@playwright/test' + +export class ExpensePage { + constructor(private page: Page) {} + + async navigateToGroupExpenses(groupId: string) { + await this.page.goto(`http://localhost:3002/groups/${groupId}/expenses`) + } + + async fillTitle(expenseTitle: string) { + await this.page + .getByRole('textbox', { name: 'Expense title' }) + .fill(expenseTitle) + } + + async fillAmount(expenseAmount: string) { + await this.page.getByRole('textbox', { name: 'Amount' }).fill(expenseAmount) + } + + async selectPayer(payer: string) { + await this.page + .getByRole('combobox') + .filter({ hasText: 'Select a participant' }) + .click() + await this.page.getByRole('option', { name: payer, exact: true }).click() + } + + async submit() { + await this.page.getByRole('button', { name: 'Create' }).click() + } +} diff --git a/tests/pom/group-page.ts b/tests/pom/group-page.ts new file mode 100644 index 0000000..40ad59c --- /dev/null +++ b/tests/pom/group-page.ts @@ -0,0 +1,21 @@ +import { Locator, Page } from '@playwright/test' + +export class GroupPage { + page: Page + title: Locator + + constructor(page: Page) { + this.page = page + this.title = page.getByRole('main').getByRole('heading', { level: 1 }) + } + + async createExpense() { + await this.page.getByRole('link', { name: 'Create expense' }).click() + } + + getExpenseCard(expenseTitle: string) { + return this.page + .locator('[data-expense-card]') + .filter({ hasText: expenseTitle }) + } +}