test_task_crm/tests/api/v1/test_deals.py

113 lines
3.5 KiB
Python

"""API tests for deal endpoints."""
from __future__ import annotations
from decimal import Decimal
import pytest
from app.models.activity import Activity, ActivityType
from app.models.deal import Deal, DealStage, DealStatus
from httpx import AsyncClient
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
from tests.api.v1.task_activity_shared import auth_headers, make_token, prepare_scenario
@pytest.mark.asyncio
async def test_create_deal_endpoint_uses_context_owner(
session_factory: async_sessionmaker[AsyncSession],
client: AsyncClient,
) -> None:
scenario = await prepare_scenario(session_factory)
token = make_token(scenario.user_id, scenario.user_email)
response = await client.post(
"/api/v1/deals/",
json={
"contact_id": scenario.contact_id,
"title": "Upsell Subscription",
"amount": 2500.0,
"currency": "USD",
},
headers=auth_headers(token, scenario),
)
assert response.status_code == 201
payload = response.json()
assert payload["owner_id"] == scenario.user_id
assert payload["organization_id"] == scenario.organization_id
assert payload["title"] == "Upsell Subscription"
@pytest.mark.asyncio
async def test_list_deals_endpoint_filters_by_status(
session_factory: async_sessionmaker[AsyncSession],
client: AsyncClient,
) -> None:
scenario = await prepare_scenario(session_factory)
token = make_token(scenario.user_id, scenario.user_email)
async with session_factory() as session:
base_deal = await session.get(Deal, scenario.deal_id)
assert base_deal is not None
base_deal.status = DealStatus.NEW
won_deal = Deal(
organization_id=scenario.organization_id,
contact_id=scenario.contact_id,
owner_id=scenario.user_id,
title="Enterprise Upgrade",
amount=Decimal("8000"),
currency="USD",
status=DealStatus.WON,
stage=DealStage.CLOSED,
)
session.add(won_deal)
await session.commit()
response = await client.get(
"/api/v1/deals/?status=won",
headers=auth_headers(token, scenario),
)
assert response.status_code == 200
data = response.json()
assert len(data) == 1
assert data[0]["title"] == "Enterprise Upgrade"
assert data[0]["status"] == DealStatus.WON.value
@pytest.mark.asyncio
async def test_update_deal_endpoint_updates_stage_and_logs_activity(
session_factory: async_sessionmaker[AsyncSession],
client: AsyncClient,
) -> None:
scenario = await prepare_scenario(session_factory)
token = make_token(scenario.user_id, scenario.user_email)
response = await client.patch(
f"/api/v1/deals/{scenario.deal_id}",
json={
"stage": DealStage.PROPOSAL.value,
"status": DealStatus.WON.value,
"amount": 5000.0,
"currency": "USD",
},
headers=auth_headers(token, scenario),
)
assert response.status_code == 200
body = response.json()
assert body["stage"] == DealStage.PROPOSAL.value
assert body["status"] == DealStatus.WON.value
assert Decimal(body["amount"]) == Decimal("5000")
async with session_factory() as session:
activity_types = await session.scalars(
select(Activity.type).where(Activity.deal_id == scenario.deal_id),
)
collected = set(activity_types.all())
assert ActivityType.STAGE_CHANGED in collected
assert ActivityType.STATUS_CHANGED in collected