diff --git a/playwright.config.ts b/playwright.config.ts index 4f354ee2..2ce2b461 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -20,6 +20,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 */ + timeout: 15000, reporter: process.env.CI ? [ ['html', { open: 'never' }], diff --git a/tests/helpers/elements.ts b/tests/helpers/elements.ts index c346bc06..e13dfb05 100644 --- a/tests/helpers/elements.ts +++ b/tests/helpers/elements.ts @@ -1,32 +1,35 @@ import { test, expect, type Page } from '@playwright/test'; -export const selectDate = async ( +export const selectDate = ( page: Page, label: string, value: { day: string; month: string; year: string } -) => { - const dateField = page.getByLabel(label); - await page.getByText(label).click(); - await page.keyboard.type(value.month); - await page.waitForTimeout(50); - await page.keyboard.type(value.day); - await page.waitForTimeout(50); - await page.keyboard.type(value.year); - await page.waitForTimeout(50); - await expect(dateField.locator('input')).toHaveValue( - `${value.year}-${value.month}-${value.day}` - ); -}; +) => + test.step(`Pick ${label} on Date Picker`, async () => { + const dateField = page.getByLabel(label); + await page.getByText(label).click(); + await page.keyboard.type(value.month); + await page.waitForTimeout(50); + await page.keyboard.type(value.day); + await page.waitForTimeout(50); + await page.keyboard.type(value.year); + await page.waitForTimeout(50); + await expect(dateField.locator('input')).toHaveValue( + `${value.year}-${value.month}-${value.day}` + ); + }); export const selectOption = (page: Page, label: string, option: string) => test.step(`Select ${option} from ${label}`, async () => { const selectInput = page.getByLabel(label, { exact: true }); + // seems to be needed to properly handle click and opening select items + await selectInput.scrollIntoViewIfNeeded(); await expect(selectInput).toBeVisible(); - await expect(async () => { - await selectInput.scrollIntoViewIfNeeded(); - await selectInput.click(); - await page.getByRole('option', { name: option }).click(); - }).toPass(); + await selectInput.click(); + // seems the only way to reliably get focus + await page.keyboard.press('ArrowDown'); + + await page.getByRole('option', { name: option }).click(); }); export const selectOnlyTag = ( diff --git a/tests/transactions/form-submission.spec.ts b/tests/transactions/form-submission.spec.ts index 18e261b1..261152c7 100644 --- a/tests/transactions/form-submission.spec.ts +++ b/tests/transactions/form-submission.spec.ts @@ -1,6 +1,5 @@ import { test, expect } from '@playwright/test'; -import { selectOption } from '../helpers/elements'; import { navigateTo } from '../helpers/navigate'; import { addDefaultAccount, addGenericTransaction, selectOnly } from './helper'; @@ -25,7 +24,7 @@ test('submits simple transaction', async ({ page }, testInfo) => { test('check income is listed in income tab after submit', async ({ page }) => { await addGenericTransaction(page, { value: '55.00', - extraActions: [selectOption(page, 'Transaction Type', 'Income')] + extraActions: [{ fn: 'selectOption', args: ['Transaction Type', 'Income'] }] }); await selectOnly(page, 'Income'); @@ -38,7 +37,9 @@ test('check expense is listed in expense tab after submit', async ({ }) => { await addGenericTransaction(page, { value: '67.00', - extraActions: [selectOption(page, 'Transaction Type', 'Expense')] + extraActions: [ + { fn: 'selectOption', args: ['Transaction Type', 'Expense'] } + ] }); await selectOnly(page, 'Expenses'); @@ -51,7 +52,9 @@ test('check transfer is listed in transfer tab after submit', async ({ }) => { await addGenericTransaction(page, { value: '53', - extraActions: [selectOption(page, 'Transaction Type', 'Transfer')] + extraActions: [ + { fn: 'selectOption', args: ['Transaction Type', 'Transfer'] } + ] }); await selectOnly(page, 'Transfers'); diff --git a/tests/transactions/helper.ts b/tests/transactions/helper.ts index c32bbf49..7f1fcc25 100644 --- a/tests/transactions/helper.ts +++ b/tests/transactions/helper.ts @@ -13,21 +13,33 @@ export const addDefaultAccount = async (page: Page) => { }); }; -export const addGenericTransaction = async ( +type SelectOptionsParams = Parameters; +type ExtraActions = { + fn: 'selectOption'; + args: [SelectOptionsParams[1], SelectOptionsParams[2]]; +}[]; + +export const addGenericTransaction = ( page: Page, - { value, extraActions }: { value: string; extraActions: Promise[] } = { + { + value, + extraActions + }: { + value: string; + extraActions: ExtraActions; + } = { value: '55.00', extraActions: [] } -) => { - await test.step('Add Generic Transaction', async () => { - const addButton = page.getByText('Add Transaction'); - await addButton.click(); - +) => + test.step('Add Generic Transaction', async () => { + await page.getByText('Add Transaction').click(); + // confirms the form is loaded and stable await expect(page.getByText('Add a Transaction')).toBeAttached(); await page.getByLabel('description').fill('test transaction'); await page.getByLabel('Category').fill('generic'); + await selectOption(page, 'Account', 'Test Account Submission'); await selectOption(page, 'Repeat Type', 'No Repeating'); @@ -39,7 +51,11 @@ export const addGenericTransaction = async ( if (extraActions) { for (let pageAction of extraActions) { - await pageAction; + if (pageAction.fn === 'selectOption') { + // the tracing and actions gets real weird if we don't specifically + // pass it and call it here + await selectOption(page, pageAction.args[0], pageAction.args[1]); + } } } @@ -47,7 +63,6 @@ export const addGenericTransaction = async ( await page.keyboard.press('Enter'); await expect(page.locator('table').getByText(value)).toBeVisible(); }); -}; const possibleTransactionTypes = ['Income', 'Expenses', 'Transfers'] as const; export const selectOnly = ( diff --git a/tests/transactions/transaction-delete.spec.ts b/tests/transactions/transaction-delete.spec.ts index 066f5e5e..a6ad0c07 100644 --- a/tests/transactions/transaction-delete.spec.ts +++ b/tests/transactions/transaction-delete.spec.ts @@ -9,19 +9,23 @@ test.beforeEach(async ({ page }) => { await page.goto('/'); await addDefaultAccount(page); await navigateTo(page, 'Planning'); + await page.getByText('Add Transaction').click(); + // confirms the form is loaded and stable + await expect(page.getByText('Add a Transaction')).toBeAttached(); - await selectOption(page, 'Account', 'Test Account Submission'); - await page.getByLabel('value').first().fill('55'); + await selectOption(page, 'Account', 'Test Account Submission'); // + await page.getByLabel('value').first().fill('55'); // await page.getByLabel('ending').click(); await selectDate(page, 'Start Date', { + // month: '01', day: '01', year: '2024' }); - await selectOption(page, 'Repeat Type', 'No Repeating'); - await page.getByLabel('Category').fill('generic'); - await page.getByLabel('description').fill('test transaction'); + await selectOption(page, 'Repeat Type', 'No Repeating'); // + await page.getByLabel('Category').fill('generic'); // + await page.getByLabel('description').fill('test transaction'); // await page.keyboard.press('Enter'); });