ledgerone_frontend/tests/transactions.spec.ts

151 lines
4.7 KiB
TypeScript

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();
});