import { test, expect } from "@playwright/test"; const apiOk = (data: unknown) => ({ data, meta: { timestamp: new Date().toISOString(), version: "v1" }, error: null }); test.beforeEach(async ({ context, page }) => { await context.addCookies([ { name: "ledgerone_auth", value: "1", domain: "localhost", path: "/" }, ]); await page.route("**/api/auth/me", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk({ user: { id: "user_1", email: "test@example.com", name: "Test User" } })), }); }); await page.route("**/api/billing/subscription", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk({ plan: "pro", status: "active" })), }); }); }); test("transactions page supports filters, manual add, and edit", async ({ page }) => { let listResponse = apiOk({ transactions: [ { viewRef: "tx_1", description: "Coffee Bar", amount: "12.50", category: "Dining", note: "", attribution: "mine", split: { mode: "none", minePercent: 50, yoursPercent: 50, mineAmount: 0, yoursAmount: 0 }, status: "raw", hidden: false, date: "2025-01-10" } ], total: 1 }); await page.route("**/api/transactions/summary**", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk({ total: "12.50", count: 1, income: "0.00", expense: "12.50", net: "-12.50" })) }); }); await page.route("**/api/transactions/merchants**", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk([])) }); }); await page.route("**/api/transactions/cashflow**", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk([])) }); }); await page.route("**/api/transactions?*", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(listResponse) }); }); await page.route("**/api/transactions", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(listResponse) }); }); await page.route("**/api/transactions/sync", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk({ created: 1 })) }); }); await page.route("**/api/transactions/manual", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk({ id: "tx_2" })) }); }); await page.route("**/api/transactions/*/derived", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify(apiOk({})) }); }); await page.route("**/api/accounts**", async (route) => { await route.fulfill({ contentType: "application/json", body: JSON.stringify( apiOk({ accounts: [ { viewRef: "acct_1", institutionName: "Chase", accountType: "checking", mask: "1234" } ], total: 1 }) ) }); }); await page.goto("/transactions"); await expect(page.getByRole("button", { name: "Sync" })).toBeVisible(); await expect(page.getByRole("link", { name: "Export", exact: true })).toBeVisible(); await page.getByRole("button", { name: "Filters" }).click(); await expect(page.getByPlaceholder("Description...")).toBeVisible(); await page.getByRole("button", { name: "Add manual" }).click(); await expect(page.getByText("Manual transaction")).toBeVisible(); const manualForm = page.locator("form").first(); await manualForm.getByText("Description").locator("..").getByRole("textbox").fill("Manual payment"); await manualForm.getByPlaceholder("-42.50").fill("40.25"); await manualForm.getByRole("button", { name: "Save" }).click(); await expect(page.getByText("Manual transaction saved.")).toBeVisible(); await page.getByRole("button", { name: "Edit" }).click(); await page.getByPlaceholder("Category").fill("Coffee"); await page.getByPlaceholder("Note").fill("Edited note"); listResponse = apiOk({ transactions: [ { viewRef: "tx_1", description: "Coffee Bar", amount: "12.50", category: "Coffee", note: "Edited note", attribution: "mine", split: { mode: "none", minePercent: 50, yoursPercent: 50, mineAmount: 0, yoursAmount: 0 }, status: "user", hidden: false, date: "2025-01-10" } ], total: 1 }); await page.getByRole("button", { name: "Save" }).click(); await expect(page.getByText("Transaction updated.")).toBeVisible(); });