""" Pricing API Tests Tests for the admin pricing configuration endpoints. """ import pytest from repositories.pricing import PricingRepository class TestPricingPermissions: """Test that only admins can access pricing endpoints.""" @pytest.mark.asyncio async def test_admin_can_get_pricing(self, client_factory, admin_user): """Admin can access GET pricing endpoint.""" # Seed pricing config first async with client_factory.get_db_session() as db: repo = PricingRepository(db) await repo.create_or_update( premium_buy=5, premium_sell=5, small_trade_threshold_eur=20000, small_trade_extra_premium=2, eur_min_buy=10000, eur_max_buy=300000, eur_min_sell=10000, eur_max_sell=300000, ) async with client_factory.create(cookies=admin_user["cookies"]) as client: response = await client.get("/api/admin/pricing") assert response.status_code == 200 data = response.json() assert "premium_buy" in data assert "premium_sell" in data assert data["premium_buy"] == 5 @pytest.mark.asyncio async def test_regular_user_cannot_get_pricing(self, client_factory, regular_user): """Regular user cannot access GET pricing endpoint.""" async with client_factory.create(cookies=regular_user["cookies"]) as client: response = await client.get("/api/admin/pricing") assert response.status_code == 403 @pytest.mark.asyncio async def test_unauthenticated_cannot_get_pricing(self, client): """Unauthenticated user cannot access GET pricing endpoint.""" response = await client.get("/api/admin/pricing") assert response.status_code == 401 @pytest.mark.asyncio async def test_admin_can_update_pricing(self, client_factory, admin_user): """Admin can access PUT pricing endpoint.""" # Seed pricing config first async with client_factory.get_db_session() as db: repo = PricingRepository(db) await repo.create_or_update( premium_buy=5, premium_sell=5, small_trade_threshold_eur=20000, small_trade_extra_premium=2, eur_min_buy=10000, eur_max_buy=300000, eur_min_sell=10000, eur_max_sell=300000, ) async with client_factory.create(cookies=admin_user["cookies"]) as client: response = await client.put( "/api/admin/pricing", json={ "premium_buy": 7, "premium_sell": 6, "small_trade_threshold_eur": 25000, "small_trade_extra_premium": 3, "eur_min_buy": 15000, "eur_max_buy": 350000, "eur_min_sell": 12000, "eur_max_sell": 320000, }, ) assert response.status_code == 200 data = response.json() assert data["premium_buy"] == 7 assert data["premium_sell"] == 6 @pytest.mark.asyncio async def test_regular_user_cannot_update_pricing( self, client_factory, regular_user ): """Regular user cannot access PUT pricing endpoint.""" async with client_factory.create(cookies=regular_user["cookies"]) as client: response = await client.put( "/api/admin/pricing", json={ "premium_buy": 7, "premium_sell": 6, "small_trade_threshold_eur": 25000, "small_trade_extra_premium": 3, "eur_min_buy": 15000, "eur_max_buy": 350000, "eur_min_sell": 12000, "eur_max_sell": 320000, }, ) assert response.status_code == 403 @pytest.mark.asyncio async def test_unauthenticated_cannot_update_pricing(self, client): """Unauthenticated user cannot access PUT pricing endpoint.""" response = await client.put( "/api/admin/pricing", json={ "premium_buy": 7, "premium_sell": 6, "small_trade_threshold_eur": 25000, "small_trade_extra_premium": 3, "eur_min_buy": 15000, "eur_max_buy": 350000, "eur_min_sell": 12000, "eur_max_sell": 320000, }, ) assert response.status_code == 401 class TestPricingValidation: """Test validation of pricing configuration updates.""" @pytest.mark.asyncio async def test_update_with_valid_data(self, client_factory, admin_user): """Update with valid data succeeds.""" # Seed pricing config first async with client_factory.get_db_session() as db: repo = PricingRepository(db) await repo.create_or_update( premium_buy=5, premium_sell=5, small_trade_threshold_eur=20000, small_trade_extra_premium=2, eur_min_buy=10000, eur_max_buy=300000, eur_min_sell=10000, eur_max_sell=300000, ) async with client_factory.create(cookies=admin_user["cookies"]) as client: response = await client.put( "/api/admin/pricing", json={ "premium_buy": 10, "premium_sell": 8, "small_trade_threshold_eur": 30000, "small_trade_extra_premium": 5, "eur_min_buy": 20000, "eur_max_buy": 400000, "eur_min_sell": 15000, "eur_max_sell": 350000, }, ) assert response.status_code == 200 data = response.json() assert data["premium_buy"] == 10 assert data["premium_sell"] == 8 @pytest.mark.asyncio async def test_premium_out_of_range_rejected(self, client_factory, admin_user): """Premium values outside -100 to 100 are rejected.""" # Seed pricing config first async with client_factory.get_db_session() as db: repo = PricingRepository(db) await repo.create_or_update( premium_buy=5, premium_sell=5, small_trade_threshold_eur=20000, small_trade_extra_premium=2, eur_min_buy=10000, eur_max_buy=300000, eur_min_sell=10000, eur_max_sell=300000, ) async with client_factory.create(cookies=admin_user["cookies"]) as client: # Test premium_buy > 100 response = await client.put( "/api/admin/pricing", json={ "premium_buy": 101, "premium_sell": 5, "small_trade_threshold_eur": 20000, "small_trade_extra_premium": 2, "eur_min_buy": 10000, "eur_max_buy": 300000, "eur_min_sell": 10000, "eur_max_sell": 300000, }, ) assert response.status_code == 400 # Test premium_buy < -100 response = await client.put( "/api/admin/pricing", json={ "premium_buy": -101, "premium_sell": 5, "small_trade_threshold_eur": 20000, "small_trade_extra_premium": 2, "eur_min_buy": 10000, "eur_max_buy": 300000, "eur_min_sell": 10000, "eur_max_sell": 300000, }, ) assert response.status_code == 400 @pytest.mark.asyncio async def test_min_greater_than_max_rejected(self, client_factory, admin_user): """Min >= Max is rejected.""" # Seed pricing config first async with client_factory.get_db_session() as db: repo = PricingRepository(db) await repo.create_or_update( premium_buy=5, premium_sell=5, small_trade_threshold_eur=20000, small_trade_extra_premium=2, eur_min_buy=10000, eur_max_buy=300000, eur_min_sell=10000, eur_max_sell=300000, ) async with client_factory.create(cookies=admin_user["cookies"]) as client: # Test eur_min_buy >= eur_max_buy response = await client.put( "/api/admin/pricing", json={ "premium_buy": 5, "premium_sell": 5, "small_trade_threshold_eur": 20000, "small_trade_extra_premium": 2, "eur_min_buy": 300000, "eur_max_buy": 300000, "eur_min_sell": 10000, "eur_max_sell": 300000, }, ) assert response.status_code == 400 @pytest.mark.asyncio async def test_negative_amounts_rejected(self, client_factory, admin_user): """Negative amounts are rejected.""" # Seed pricing config first async with client_factory.get_db_session() as db: repo = PricingRepository(db) await repo.create_or_update( premium_buy=5, premium_sell=5, small_trade_threshold_eur=20000, small_trade_extra_premium=2, eur_min_buy=10000, eur_max_buy=300000, eur_min_sell=10000, eur_max_sell=300000, ) async with client_factory.create(cookies=admin_user["cookies"]) as client: # Test negative eur_min_buy response = await client.put( "/api/admin/pricing", json={ "premium_buy": 5, "premium_sell": 5, "small_trade_threshold_eur": 20000, "small_trade_extra_premium": 2, "eur_min_buy": -1000, "eur_max_buy": 300000, "eur_min_sell": 10000, "eur_max_sell": 300000, }, ) assert response.status_code == 400 @pytest.mark.asyncio async def test_zero_amounts_rejected(self, client_factory, admin_user): """Zero amounts are rejected.""" # Seed pricing config first async with client_factory.get_db_session() as db: repo = PricingRepository(db) await repo.create_or_update( premium_buy=5, premium_sell=5, small_trade_threshold_eur=20000, small_trade_extra_premium=2, eur_min_buy=10000, eur_max_buy=300000, eur_min_sell=10000, eur_max_sell=300000, ) async with client_factory.create(cookies=admin_user["cookies"]) as client: # Test zero eur_min_buy response = await client.put( "/api/admin/pricing", json={ "premium_buy": 5, "premium_sell": 5, "small_trade_threshold_eur": 20000, "small_trade_extra_premium": 2, "eur_min_buy": 0, "eur_max_buy": 300000, "eur_min_sell": 10000, "eur_max_sell": 300000, }, ) assert response.status_code == 400 @pytest.mark.asyncio async def test_get_when_no_config_returns_404(self, client_factory, admin_user): """GET returns 404 when no config exists.""" async with client_factory.create(cookies=admin_user["cookies"]) as client: response = await client.get("/api/admin/pricing") assert response.status_code == 404 @pytest.mark.asyncio async def test_update_creates_config_if_none_exists( self, client_factory, admin_user ): """PUT creates config if none exists.""" async with client_factory.create(cookies=admin_user["cookies"]) as client: response = await client.put( "/api/admin/pricing", json={ "premium_buy": 5, "premium_sell": 5, "small_trade_threshold_eur": 20000, "small_trade_extra_premium": 2, "eur_min_buy": 10000, "eur_max_buy": 300000, "eur_min_sell": 10000, "eur_max_sell": 300000, }, ) assert response.status_code == 200 data = response.json() assert data["premium_buy"] == 5 # Verify it was created response = await client.get("/api/admin/pricing") assert response.status_code == 200