setSelected(p)} className="cursor-pointer hover:bg-blue-50 transition-colors">
| {p.paymentDate ? formatDate(p.paymentDate) : formatDate(p.createdAt)} |
{p.client ? `${p.client.firstName} ${p.client.lastName}` : "—"}
diff --git a/e2e/payments.spec.ts b/e2e/payments.spec.ts
index 307b6a9..3731256 100644
--- a/e2e/payments.spec.ts
+++ b/e2e/payments.spec.ts
@@ -7,31 +7,40 @@ test.describe('Payments', () => {
await page.goto('/payments');
});
- test('payments page renders', async ({ page }) => {
+ test('page renders with header and table', async ({ page }) => {
await expect(page.locator('h1:has-text("Payments")')).toBeVisible();
await expect(page.locator('table')).toBeVisible();
});
- test('payments load with amounts', async ({ page }) => {
- await page.waitForSelector('tbody tr', { timeout: 15000 });
- const rows = page.locator('tbody tr');
- const count = await rows.count();
+ test('payments list loads rows from API', async ({ page }) => {
+ await expect(page.locator('[data-testid="payment-row"]').first()).toBeVisible({ timeout: 15000 });
+ const count = await page.locator('[data-testid="payment-row"]').count();
expect(count).toBeGreaterThan(0);
});
- test('channel filter buttons work', async ({ page }) => {
+ test('channel filter buttons exist and toggle active state', async ({ page }) => {
const cashBtn = page.locator('button:has-text("CASH")').first();
+ await expect(cashBtn).toBeVisible();
await cashBtn.click();
- await page.waitForTimeout(500);
- await expect(page.locator('h1:has-text("Payments")')).toBeVisible();
- // All filter works
- await page.locator('button:has-text("All")').click();
+ await expect(cashBtn).toHaveClass(/bg-blue-600/);
+ // Reset to All
+ await page.locator('button:has-text("All")').first().click();
});
test('clicking payment row opens detail modal', async ({ page }) => {
- await page.waitForSelector('tbody tr', { timeout: 15000 });
- await page.locator('tbody tr').first().click();
- await page.waitForTimeout(300);
- await expect(page.locator('text=Payment Details')).toBeVisible();
+ await expect(page.locator('[data-testid="payment-row"]').first()).toBeVisible({ timeout: 15000 });
+ await page.locator('[data-testid="payment-row"]').first().click();
+ await expect(page.locator('text=Payment Details')).toBeVisible({ timeout: 5000 });
+ // Check modal has key fields
+ await expect(page.locator('text=Amount')).toBeVisible();
+ await expect(page.locator('text=Method')).toBeVisible();
+ });
+
+ test('detail modal closes on close button', async ({ page }) => {
+ await expect(page.locator('[data-testid="payment-row"]').first()).toBeVisible({ timeout: 15000 });
+ await page.locator('[data-testid="payment-row"]').first().click();
+ await expect(page.locator('text=Payment Details')).toBeVisible({ timeout: 5000 });
+ await page.locator('button:has-text("Close")').click();
+ await expect(page.locator('text=Payment Details')).not.toBeVisible({ timeout: 5000 });
});
});
|