Files
resolutionflow/backend/tests/test_billing_service.py

81 lines
2.7 KiB
Python

import uuid
import pytest
from datetime import datetime, timezone
from sqlalchemy import select, delete
from app.models.subscription import Subscription
from app.services.billing import BillingService
@pytest.mark.asyncio
async def test_start_trial_creates_trialing_pro_subscription(test_db):
"""Direct service test — bypasses register, creates account inline."""
from app.models.account import Account
account = Account(name="DirectTest", display_code="DIRECT01")
test_db.add(account)
await test_db.flush()
sub = await BillingService.start_trial(test_db, account.id)
assert sub.plan == "pro"
assert sub.status == "trialing"
assert sub.current_period_end is not None
assert sub.current_period_end > datetime.now(timezone.utc)
@pytest.mark.asyncio
async def test_start_trial_is_idempotent(test_db):
from app.models.account import Account
account = Account(name="Idempo", display_code="IDEMPO01")
test_db.add(account)
await test_db.flush()
sub1 = await BillingService.start_trial(test_db, account.id)
sub2 = await BillingService.start_trial(test_db, account.id)
assert sub1.id == sub2.id
rows = (await test_db.execute(
select(Subscription).where(Subscription.account_id == account.id)
)).scalars().all()
assert len(rows) == 1
@pytest.mark.asyncio
async def test_register_creates_trial_subscription(client, test_db):
"""Registering a brand-new shop (no invite code) yields a Pro/trialing sub."""
response = await client.post("/api/v1/auth/register", json={
"email": "newshop@example.com",
"password": "Verystrong1Pwd",
"name": "New Shop",
})
assert response.status_code in (200, 201), response.json()
body = response.json()
account_id = uuid.UUID(body["account_id"])
sub = (await test_db.execute(
select(Subscription).where(Subscription.account_id == account_id)
)).scalar_one()
assert sub.plan == "pro"
assert sub.status == "trialing"
assert sub.current_period_end is not None
@pytest.mark.asyncio
async def test_apply_subscription_event_is_idempotent(test_db):
payload = {
"data": {"object": {
"id": "evt_test_1",
"customer": "cus_xxx",
"subscription": "sub_xxx",
"status": "active",
}}
}
applied_first = await BillingService.apply_subscription_event(
test_db, "evt_test_1", "customer.subscription.updated", payload
)
applied_second = await BillingService.apply_subscription_event(
test_db, "evt_test_1", "customer.subscription.updated", payload
)
assert applied_first is True
assert applied_second is False # already-processed → ack without re-applying