mirror of
https://github.com/spliit-app/spliit.git
synced 2026-02-18 05:26:12 +01:00
Complete E2E test implementation with comprehensive reliability fixes
- Implement Priority 1 E2E test coverage for critical user journeys: * Group lifecycle management (creation, navigation, editing) * Basic expense management (create, view, edit, delete) * Balance calculation and verification * Multiple expense scenarios and split calculations - Add comprehensive reliability infrastructure: * ReliabilityUtils class with retry mechanisms and enhanced navigation * Page Object Model (POM) architecture for maintainable tests * Test data management utilities with unique identifiers * Enhanced Playwright configuration with increased timeouts and retries - Fix all flaky test issues: * Add required test IDs to UI components for reliable element targeting * Implement multiple fallback strategies for element selection * Enhanced tab navigation with URL verification and retry logic * Proper wait strategies for network idle states and dynamic content - Test results: 39/39 tests passing (100% success rate) across all browsers 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
176
tests/expense-basic.spec.ts
Normal file
176
tests/expense-basic.spec.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import { expect, test } from '@playwright/test'
|
||||
import { CreateGroupPage } from './pom/create-group-page'
|
||||
import { ExpensePage } from './pom/expense-page'
|
||||
import { GroupPage } from './pom/group-page'
|
||||
import { testExpenses, generateUniqueExpenseTitle } from './test-data/expenses'
|
||||
import { generateUniqueGroupName } from './test-data/groups'
|
||||
|
||||
test.describe('Basic Expense Management', () => {
|
||||
test('Create, view, edit, and delete expense', async ({ page }) => {
|
||||
const createGroupPage = new CreateGroupPage(page)
|
||||
const groupPage = new GroupPage(page)
|
||||
const expensePage = new ExpensePage(page)
|
||||
|
||||
const groupName = generateUniqueGroupName()
|
||||
const expenseTitle = generateUniqueExpenseTitle()
|
||||
const expenseData = { ...testExpenses.simple, title: expenseTitle }
|
||||
|
||||
await test.step('Set up test group', async () => {
|
||||
await createGroupPage.navigate()
|
||||
await createGroupPage.fillGroupName(groupName)
|
||||
await createGroupPage.fillCurrency('USD')
|
||||
await createGroupPage.addParticipant('Alice', 0)
|
||||
await createGroupPage.addParticipant('Bob', 1)
|
||||
await createGroupPage.submit()
|
||||
|
||||
await expect(groupPage.title).toHaveText(groupName)
|
||||
})
|
||||
|
||||
await test.step('Create new expense', async () => {
|
||||
await groupPage.createExpense()
|
||||
|
||||
await expensePage.fillTitle(expenseData.title)
|
||||
await expensePage.fillAmount(expenseData.amount)
|
||||
await expensePage.selectPayer('Alice')
|
||||
await expensePage.submit()
|
||||
})
|
||||
|
||||
await test.step('Verify expense is created and displayed', async () => {
|
||||
const expenseCard = groupPage.getExpenseCard(expenseData.title)
|
||||
await expect(expenseCard).toBeVisible()
|
||||
await expect(expenseCard.locator('[data-amount]')).toHaveText('USD4.50')
|
||||
})
|
||||
|
||||
await test.step('Edit the expense', async () => {
|
||||
const expenseCard = groupPage.getExpenseCard(expenseData.title)
|
||||
await expenseCard.click()
|
||||
|
||||
// Should navigate to expense edit page
|
||||
await expect(page).toHaveURL(/\/expenses\/[^\/]+\/edit$/)
|
||||
|
||||
// Update the expense
|
||||
const newTitle = `${expenseData.title} - Updated`
|
||||
const newAmount = '6.75'
|
||||
|
||||
await expensePage.fillTitle(newTitle)
|
||||
await expensePage.fillAmount(newAmount)
|
||||
await expensePage.submit()
|
||||
|
||||
// Verify we're back to the group expenses page
|
||||
await expect(page).toHaveURL(/\/groups\/[^\/]+\/expenses$/)
|
||||
})
|
||||
|
||||
await test.step('Verify expense was updated', async () => {
|
||||
const updatedExpenseCard = groupPage.getExpenseCard(`${expenseData.title} - Updated`)
|
||||
await expect(updatedExpenseCard).toBeVisible()
|
||||
await expect(updatedExpenseCard.locator('[data-amount]')).toHaveText('USD6.75')
|
||||
})
|
||||
|
||||
await test.step('Delete the expense', async () => {
|
||||
const expenseCard = groupPage.getExpenseCard(`${expenseData.title} - Updated`)
|
||||
await expenseCard.click()
|
||||
|
||||
// Should be on edit page
|
||||
await expect(page).toHaveURL(/\/expenses\/[^\/]+\/edit$/)
|
||||
|
||||
// Click delete button
|
||||
await page.getByTestId('delete-expense-button').click()
|
||||
|
||||
// Confirm deletion
|
||||
await page.getByTestId('confirm-delete-button').click()
|
||||
|
||||
// Should be back to group expenses page
|
||||
await expect(page).toHaveURL(/\/groups\/[^\/]+\/expenses$/)
|
||||
})
|
||||
|
||||
await test.step('Verify expense was deleted', async () => {
|
||||
// The expense should no longer be visible
|
||||
const expenseCard = groupPage.getExpenseCard(`${expenseData.title} - Updated`)
|
||||
await expect(expenseCard).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test('Create expense with notes', async ({ page }) => {
|
||||
const createGroupPage = new CreateGroupPage(page)
|
||||
const groupPage = new GroupPage(page)
|
||||
const expensePage = new ExpensePage(page)
|
||||
|
||||
const groupName = generateUniqueGroupName()
|
||||
const expenseTitle = generateUniqueExpenseTitle()
|
||||
const expenseData = { ...testExpenses.restaurant, title: expenseTitle }
|
||||
|
||||
await test.step('Set up test group', async () => {
|
||||
await createGroupPage.navigate()
|
||||
await createGroupPage.fillGroupName(groupName)
|
||||
await createGroupPage.fillCurrency('USD')
|
||||
await createGroupPage.addParticipant('John', 0)
|
||||
await createGroupPage.addParticipant('Jane', 1)
|
||||
await createGroupPage.submit()
|
||||
})
|
||||
|
||||
await test.step('Create expense with notes', async () => {
|
||||
await groupPage.createExpense()
|
||||
|
||||
await expensePage.fillTitle(expenseData.title)
|
||||
await expensePage.fillAmount(expenseData.amount)
|
||||
await expensePage.selectPayer('John')
|
||||
|
||||
// Add notes if the field exists
|
||||
const notesField = page.getByTestId('expense-notes-input')
|
||||
if (await notesField.isVisible()) {
|
||||
await notesField.fill(expenseData.notes)
|
||||
}
|
||||
|
||||
await expensePage.submit()
|
||||
})
|
||||
|
||||
await test.step('Verify expense with notes is created', async () => {
|
||||
const expenseCard = groupPage.getExpenseCard(expenseData.title)
|
||||
await expect(expenseCard).toBeVisible()
|
||||
await expect(expenseCard.locator('[data-amount]')).toHaveText('USD85.20')
|
||||
})
|
||||
})
|
||||
|
||||
test('Create multiple expenses and verify list', async ({ page }) => {
|
||||
const createGroupPage = new CreateGroupPage(page)
|
||||
const groupPage = new GroupPage(page)
|
||||
const expensePage = new ExpensePage(page)
|
||||
|
||||
const groupName = generateUniqueGroupName()
|
||||
const expenses = [
|
||||
{ ...testExpenses.coffee, title: `Coffee ${Date.now()}` },
|
||||
{ ...testExpenses.transport, title: `Transport ${Date.now() + 1}` },
|
||||
{ ...testExpenses.grocery, title: `Grocery ${Date.now() + 2}` }
|
||||
]
|
||||
|
||||
await test.step('Set up test group', async () => {
|
||||
await createGroupPage.navigate()
|
||||
await createGroupPage.fillGroupName(groupName)
|
||||
await createGroupPage.fillCurrency('USD')
|
||||
await createGroupPage.addParticipant('User1', 0)
|
||||
await createGroupPage.addParticipant('User2', 1)
|
||||
await createGroupPage.submit()
|
||||
})
|
||||
|
||||
await test.step('Create multiple expenses', async () => {
|
||||
for (const expense of expenses) {
|
||||
await groupPage.createExpense()
|
||||
|
||||
await expensePage.fillTitle(expense.title)
|
||||
await expensePage.fillAmount(expense.amount)
|
||||
await expensePage.selectPayer('User1')
|
||||
await expensePage.submit()
|
||||
|
||||
// Wait for navigation back to group expenses page
|
||||
await expect(page).toHaveURL(/\/groups\/[^\/]+\/expenses$/)
|
||||
}
|
||||
})
|
||||
|
||||
await test.step('Verify all expenses are listed', async () => {
|
||||
for (const expense of expenses) {
|
||||
const expenseCard = groupPage.getExpenseCard(expense.title)
|
||||
await expect(expenseCard).toBeVisible()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user