from pathlib import Path import pytest from app.bot import parse_transaction from app.db import Database def make_database(tmp_path: Path) -> Database: database = Database(tmp_path / "test.sqlite3") database.initialize() return database def add_user(database: Database, user_id: int, name: str) -> None: database.upsert_user( user_id=user_id, first_name=name, last_name=None, username=None, ) def test_transaction_and_leaderboard(tmp_path: Path) -> None: database = make_database(tmp_path) add_user(database, 1, "Аня") item = parse_transaction( '{"v":1,"type":"transaction","kind":"income","amount":"1000.50","category":"Зарплата","occurred_at":"2026-01-01T00:00:00Z"}' ) database.add_transaction(1, item) expense = parse_transaction( '{"v":1,"type":"transaction","kind":"expense","amount":"250.25","category":"Еда","occurred_at":"2026-01-02T00:00:00Z"}' ) database.add_transaction(1, expense) summary = database.summary(1) assert summary is not None assert summary["income_cents"] == 100_050 assert summary["expense_cents"] == 25_025 assert summary["saved_percent"] == 75.0 assert database.leaderboard()[0]["nickname"] == "Аня" def test_friendship_is_symmetric_and_idempotent(tmp_path: Path) -> None: database = make_database(tmp_path) add_user(database, 3, "Три") add_user(database, 7, "Семь") assert database.add_friendship(7, 3) assert not database.add_friendship(3, 7) assert database.friend_ids(3) == [7] assert database.friend_ids(7) == [3] def test_filtered_leaderboard(tmp_path: Path) -> None: database = make_database(tmp_path) for user_id in (1, 2, 3): add_user(database, user_id, str(user_id)) result = database.leaderboard(user_ids=[1, 3]) assert [item["user_id"] for item in result] == [1, 3] @pytest.mark.parametrize( "payload", [ "not-json", '{"v":1,"type":"transaction","kind":"other","amount":"10","category":"Еда"}', '{"v":1,"type":"transaction","kind":"income","amount":"-1","category":"Зарплата"}', '{"v":1,"type":"transaction","kind":"income","amount":"10","category":""}', ], ) def test_rejects_invalid_webapp_payload(payload: str) -> None: with pytest.raises(ValueError): parse_transaction(payload)