Files
finance/backend/tests/test_ledger_properties.py
T
k1nq d582f15681 feat: add tests for import polling, login page, money utilities, and query keys
- Implemented tests for import polling functionality, ensuring correct behavior for active and terminal import statuses.
- Created tests for the login page, validating user interactions and error handling.
- Added unit tests for money utility functions, covering parsing, formatting, and summation of monetary values.
- Developed tests for query keys, ensuring proper scoping and invalidation roots.

chore: setup testing environment and configuration

- Added setup file for testing with Vitest and Testing Library.
- Configured TypeScript and Vite for the frontend project.
- Created Docker and Nginx configurations for local development and production environments.
- Established a PostgreSQL initialization script for setting up application roles.

docs: add README and environment configuration for infra

- Included README for the infra directory, detailing local development setup and service descriptions.
- Created an example environment configuration file for local development with placeholders for sensitive information.
2026-09-14 09:26:33 +05:00

156 lines
4.1 KiB
Python

from datetime import date
import pytest
from hypothesis import HealthCheck, given, settings
from hypothesis import strategies as st
from sqlalchemy.orm import Session
from app.errors import AppError
from app.identity.models import User
from app.ledger.models import Posting
from app.ledger.service import (
account_balance,
create_account,
create_expense,
create_income,
create_refund,
create_transfer,
get_account,
)
from app.spaces.service import create_space
def seed(db: Session):
user = User(email="owner@example.test", password_hash="unused-in-domain-tests")
db.add(user)
db.flush()
space = create_space(db, user=user, name="Personal")
return user, space
@given(amount=st.integers(min_value=1, max_value=10**12))
@settings(suppress_health_check=[HealthCheck.function_scoped_fixture])
def test_transfer_postings_conserve_money(db: Session, amount: int) -> None:
db.rollback()
user, space = seed(db)
source = create_account(
db,
space_id=space.id,
user=user,
name="Debit",
kind="debit",
opened_on=date(2026, 1, 1),
opening_amount_kopecks=amount,
)
target = create_account(
db,
space_id=space.id,
user=user,
name="Cash",
kind="cash",
opened_on=date(2026, 1, 1),
)
operation = create_transfer(
db,
space_id=space.id,
user=user,
source_account_id=source.id,
target_account_id=target.id,
amount_kopecks=amount,
occurred_on=date(2026, 1, 2),
)
db.flush()
postings = db.query(Posting).filter_by(operation_id=operation.id).all()
assert len(postings) == 2
assert sum(item.amount_kopecks for item in postings) == 0
assert account_balance(db, source) == 0
assert account_balance(db, target) == amount
db.rollback()
def test_credit_expense_is_negative_balance_and_refund_is_capped(db: Session) -> None:
user, space = seed(db)
card = create_account(
db,
space_id=space.id,
user=user,
name="Credit",
kind="credit",
opened_on=date(2026, 2, 1),
)
expense = create_expense(
db,
space_id=space.id,
user=user,
account_id=card.id,
amount_kopecks=12_345,
occurred_on=date(2026, 2, 2),
)
assert account_balance(db, card) == -12_345
create_refund(
db,
space_id=space.id,
user=user,
parent_operation_id=expense.id,
amount_kopecks=2_345,
occurred_on=date(2026, 2, 3),
)
assert account_balance(db, card) == -10_000
with pytest.raises(AppError, match="Refund exceeds"):
create_refund(
db,
space_id=space.id,
user=user,
parent_operation_id=expense.id,
amount_kopecks=10_001,
occurred_on=date(2026, 2, 4),
)
def test_cross_space_lookup_fails_closed(db: Session) -> None:
user, first = seed(db)
other = create_space(db, user=user, name="Other")
account = create_account(
db,
space_id=first.id,
user=user,
name="Cash",
kind="cash",
opened_on=date(2026, 1, 1),
)
with pytest.raises(AppError) as exc:
get_account(db, space_id=other.id, account_id=account.id)
assert exc.value.code == "LEDGER_ACCOUNT_NOT_FOUND"
def test_idempotency_key_prevents_duplicate_income(db: Session) -> None:
user, space = seed(db)
account = create_account(
db,
space_id=space.id,
user=user,
name="Debit",
kind="debit",
opened_on=date(2026, 1, 1),
)
first = create_income(
db,
space_id=space.id,
user=user,
account_id=account.id,
amount_kopecks=50_000,
occurred_on=date(2026, 1, 5),
request_key="retry-1",
)
second = create_income(
db,
space_id=space.id,
user=user,
account_id=account.id,
amount_kopecks=50_000,
occurred_on=date(2026, 1, 5),
request_key="retry-1",
)
assert first.id == second.id
assert account_balance(db, account) == 50_000