mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-12 18:46:40 +07:00
backend/tests/: 33 pytest tests against a real Postgres database (aurum_test, created/migrated/dropped per run) exercised through the actual HTTP API — not sqlite, not mocks, and the real `aurum` database is never opened (app lifespan is skipped, get_session is overridden per test). Covers transaction category-kind validation, year/month/date-range filtering and pagination, dashboard summary arithmetic, budget status, cash flow, and the /transactions/years picker. e2e/: 6 Playwright specs driving a real browser against a fully separate throwaway docker-compose stack (run.sh: separate project name, database, port, and volume, torn down with `down -v` on exit) — regression coverage for the Recent Transactions month bug, the Card grid-overflow bug, the frozen-year bug, the Net Worth default range, and the Dashboard-> Transactions deep link, all fixed earlier this session. Also synced the backend's APP_VERSION constant (stale at 0.15.2, embedded in exported backups) with the frontend version.
85 lines
3.6 KiB
Python
85 lines
3.6 KiB
Python
"""Cash flow: month-by-month income vs. expense across an explicit date
|
|
range, or the full transaction history when no range is given.
|
|
"""
|
|
from decimal import Decimal
|
|
|
|
from httpx import AsyncClient
|
|
|
|
from tests.helpers import money, txn_payload
|
|
|
|
|
|
async def test_explicit_range_excludes_transactions_outside_it(client: AsyncClient, account_id, categories):
|
|
category_id = categories["Groceries"]["id"]
|
|
salary_id = categories["Salary"]["id"]
|
|
await client.post(
|
|
"/transactions", json=txn_payload(account_id, amount="1000.00", type="income", category_id=salary_id, date="2022-05-01")
|
|
)
|
|
await client.post(
|
|
"/transactions", json=txn_payload(account_id, amount="9999.00", type="income", category_id=salary_id, date="2021-01-01")
|
|
)
|
|
await client.post(
|
|
"/transactions", json=txn_payload(account_id, amount="9999.00", type="income", category_id=salary_id, date="2023-01-01")
|
|
)
|
|
|
|
resp = await client.get("/cash-flow", params={"start_date": "2022-01-01", "end_date": "2022-12-31"})
|
|
body = resp.json()
|
|
assert money(body["total_income"]) == Decimal("1000.00")
|
|
assert len(body["points"]) == 12 # every month of 2022, including zero months
|
|
assert body["start_date"] == "2022-01-01"
|
|
assert body["end_date"] == "2022-12-31"
|
|
|
|
|
|
async def test_transfers_are_excluded_from_totals(client: AsyncClient, account_id):
|
|
other = await client.post("/accounts", json={"name": "Savings", "type": "savings", "currency": "USD"})
|
|
other_id = other.json()["id"]
|
|
await client.post(
|
|
"/transactions",
|
|
json=txn_payload(account_id, type="transfer", amount="500.00", transfer_account_id=other_id, date="2022-03-01"),
|
|
)
|
|
|
|
resp = await client.get("/cash-flow", params={"start_date": "2022-01-01", "end_date": "2022-12-31"})
|
|
body = resp.json()
|
|
assert money(body["total_income"]) == 0
|
|
assert money(body["total_expense"]) == 0
|
|
|
|
|
|
async def test_no_range_falls_back_to_earliest_and_latest_transaction_dates(
|
|
client: AsyncClient, account_id, categories
|
|
):
|
|
category_id = categories["Groceries"]["id"]
|
|
await client.post("/transactions", json=txn_payload(account_id, category_id=category_id, date="2021-06-15"))
|
|
await client.post("/transactions", json=txn_payload(account_id, category_id=category_id, date="2024-02-10"))
|
|
|
|
resp = await client.get("/cash-flow")
|
|
body = resp.json()
|
|
assert body["start_date"] == "2021-06-15"
|
|
assert body["end_date"] == "2024-02-10"
|
|
|
|
|
|
async def test_no_transactions_returns_empty_points_and_null_bounds(client: AsyncClient):
|
|
resp = await client.get("/cash-flow")
|
|
body = resp.json()
|
|
assert body["points"] == []
|
|
assert body["start_date"] is None
|
|
assert body["end_date"] is None
|
|
assert money(body["total_net"]) == 0
|
|
|
|
|
|
async def test_monthly_points_split_income_and_expense_correctly(client: AsyncClient, account_id, categories):
|
|
category_id = categories["Groceries"]["id"]
|
|
salary_id = categories["Salary"]["id"]
|
|
await client.post(
|
|
"/transactions", json=txn_payload(account_id, type="income", amount="2000.00", category_id=salary_id, date="2022-04-01")
|
|
)
|
|
await client.post(
|
|
"/transactions", json=txn_payload(account_id, type="expense", amount="300.00", category_id=category_id, date="2022-04-15")
|
|
)
|
|
|
|
resp = await client.get("/cash-flow", params={"start_date": "2022-04-01", "end_date": "2022-04-30"})
|
|
point = resp.json()["points"][0]
|
|
assert point["year"] == 2022
|
|
assert point["month"] == 4
|
|
assert money(point["income"]) == Decimal("2000.00")
|
|
assert money(point["expense"]) == Decimal("300.00")
|
|
assert money(point["net"]) == Decimal("1700.00")
|