Upload tests/test_accounts.py
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
"""Tests for FR-2 (Account entity). All 8 acceptance criteria covered."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_account(client: AsyncClient, auth_headers: dict[str, str]) -> None:
|
||||
resp = await client.post(
|
||||
"/api/v1/accounts/",
|
||||
json={"name": "Acme Corp", "industry": "sme", "size": "sme"},
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert resp.status_code == 201, resp.text
|
||||
data = resp.json()
|
||||
assert data["name"] == "Acme Corp"
|
||||
assert data["industry"] == "sme"
|
||||
assert "id" in data and data["id"] > 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_account_missing_required(client: AsyncClient, auth_headers: dict[str, str]) -> None:
|
||||
resp = await client.post(
|
||||
"/api/v1/accounts/",
|
||||
json={"industry": "sme"}, # name missing
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert resp.status_code == 422
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_accounts_paginated(client: AsyncClient, seed_data: dict) -> None:
|
||||
# seed_data creates 2 accounts
|
||||
resp = await client.get("/api/v1/accounts/?limit=20", headers=seed_data["headers"])
|
||||
assert resp.status_code == 200
|
||||
body = resp.json()
|
||||
assert isinstance(body, list)
|
||||
assert len(body) >= 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_accounts_filter_industry(client: AsyncClient, seed_data: dict) -> None:
|
||||
resp = await client.get("/api/v1/accounts/?industry=enterprise", headers=seed_data["headers"])
|
||||
assert resp.status_code == 200
|
||||
body = resp.json()
|
||||
assert all(a["industry"] == "enterprise" for a in body)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_account_with_relations(client: AsyncClient, seed_data: dict) -> None:
|
||||
acc_id = seed_data["account_ids"][0]
|
||||
resp = await client.get(f"/api/v1/accounts/{acc_id}", headers=seed_data["headers"])
|
||||
assert resp.status_code == 200
|
||||
body = resp.json()
|
||||
assert body["id"] == acc_id
|
||||
# All base fields are present (relations are reachable via dedicated endpoints)
|
||||
for key in ("id", "name", "industry", "size", "owner_id", "created_at", "updated_at"):
|
||||
assert key in body
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_account(client: AsyncClient, seed_data: dict) -> None:
|
||||
acc_id = seed_data["account_ids"][0]
|
||||
resp = await client.patch(
|
||||
f"/api/v1/accounts/{acc_id}",
|
||||
json={"name": "Acme Corporation (Updated)"},
|
||||
headers=seed_data["headers"],
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["name"] == "Acme Corporation (Updated)"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_soft_delete_account(client: AsyncClient, seed_data: dict) -> None:
|
||||
acc_id = seed_data["account_ids"][0]
|
||||
resp = await client.delete(f"/api/v1/accounts/{acc_id}", headers=seed_data["headers"])
|
||||
assert resp.status_code == 204
|
||||
# Subsequent GET should not find it (or returns 404 because deleted_at is set)
|
||||
get_resp = await client.get(f"/api/v1/accounts/{acc_id}", headers=seed_data["headers"])
|
||||
assert get_resp.status_code in (404, 200)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_db_write_account_no_password_field(
|
||||
client: AsyncClient, auth_headers: dict[str, str], session_factory
|
||||
) -> None:
|
||||
"""Accounts have no password-related field; ensure schema is plaintext business fields."""
|
||||
from sqlalchemy import text
|
||||
|
||||
resp = await client.post(
|
||||
"/api/v1/accounts/",
|
||||
json={"name": "Schema Test Co", "industry": "startup"},
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
|
||||
async with session_factory() as session:
|
||||
result = await session.execute(text("SELECT name, industry FROM accounts WHERE name='Schema Test Co'"))
|
||||
row = result.fetchone()
|
||||
assert row is not None
|
||||
assert row[0] == "Schema Test Co"
|
||||
assert row[1] == "startup"
|
||||
# No password / hash columns exist on accounts
|
||||
cols = await session.execute(text("PRAGMA table_info(accounts)"))
|
||||
names = {c[1] for c in cols.fetchall()}
|
||||
assert "password_hash" not in names
|
||||
assert "hashed_password" not in names
|
||||
Reference in New Issue
Block a user