165 lines
6.0 KiB
Python
165 lines
6.0 KiB
Python
|
|
import pytest
|
||
|
|
from httpx import AsyncClient
|
||
|
|
|
||
|
|
from tests.conftest import make_business, make_user
|
||
|
|
|
||
|
|
REGISTER_PAYLOAD = {
|
||
|
|
"business_name": "Restaurante Nuevo",
|
||
|
|
"business_type": "restaurant",
|
||
|
|
"timezone": "America/Bogota",
|
||
|
|
"email": "nuevo@negocio.com",
|
||
|
|
"password": "segura123",
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Registration
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
async def test_register_creates_business_user_and_returns_token(client: AsyncClient):
|
||
|
|
response = await client.post("/auth/register", json=REGISTER_PAYLOAD)
|
||
|
|
assert response.status_code == 201
|
||
|
|
data = response.json()
|
||
|
|
assert "access_token" in data
|
||
|
|
assert data["token_type"] == "bearer"
|
||
|
|
assert isinstance(data["business_id"], int)
|
||
|
|
assert isinstance(data["user_id"], int)
|
||
|
|
|
||
|
|
|
||
|
|
async def test_register_token_grants_access_to_own_business(client: AsyncClient):
|
||
|
|
response = await client.post("/auth/register", json=REGISTER_PAYLOAD | {"email": "owner2@test.com"})
|
||
|
|
token = response.json()["access_token"]
|
||
|
|
business_id = response.json()["business_id"]
|
||
|
|
|
||
|
|
me = await client.get("/business/me", headers={"Authorization": f"Bearer {token}"})
|
||
|
|
assert me.status_code == 200
|
||
|
|
assert me.json()["id"] == business_id
|
||
|
|
assert me.json()["name"] == REGISTER_PAYLOAD["business_name"]
|
||
|
|
|
||
|
|
|
||
|
|
async def test_register_duplicate_email_returns_409(client: AsyncClient):
|
||
|
|
payload = REGISTER_PAYLOAD | {"email": "dup@test.com"}
|
||
|
|
first = await client.post("/auth/register", json=payload)
|
||
|
|
assert first.status_code == 201
|
||
|
|
|
||
|
|
second = await client.post("/auth/register", json=payload)
|
||
|
|
assert second.status_code == 409
|
||
|
|
|
||
|
|
|
||
|
|
async def test_register_password_too_short_returns_422(client: AsyncClient):
|
||
|
|
response = await client.post("/auth/register", json=REGISTER_PAYLOAD | {"email": "short@test.com", "password": "abc"})
|
||
|
|
assert response.status_code == 422
|
||
|
|
|
||
|
|
|
||
|
|
async def test_register_empty_business_name_returns_422(client: AsyncClient):
|
||
|
|
response = await client.post("/auth/register", json=REGISTER_PAYLOAD | {"email": "empty@test.com", "business_name": " "})
|
||
|
|
assert response.status_code == 422
|
||
|
|
|
||
|
|
|
||
|
|
async def test_register_creates_default_business_config(client: AsyncClient):
|
||
|
|
response = await client.post("/auth/register", json=REGISTER_PAYLOAD | {"email": "config@test.com"})
|
||
|
|
token = response.json()["access_token"]
|
||
|
|
|
||
|
|
config = await client.get("/business/me/config", headers={"Authorization": f"Bearer {token}"})
|
||
|
|
assert config.status_code == 200
|
||
|
|
data = config.json()
|
||
|
|
assert data["open_days"] == [0, 1, 2, 3, 4]
|
||
|
|
assert data["slot_duration"] == 60
|
||
|
|
assert data["assistant_name"] == "Hermes"
|
||
|
|
|
||
|
|
|
||
|
|
async def test_two_businesses_cannot_see_each_other_reservations(client: AsyncClient):
|
||
|
|
r1 = await client.post("/auth/register", json=REGISTER_PAYLOAD | {"email": "biz1@test.com"})
|
||
|
|
r2 = await client.post("/auth/register", json=REGISTER_PAYLOAD | {"email": "biz2@test.com"})
|
||
|
|
token1 = r1.json()["access_token"]
|
||
|
|
token2 = r2.json()["access_token"]
|
||
|
|
|
||
|
|
res1 = await client.get("/reservations/", headers={"Authorization": f"Bearer {token1}"})
|
||
|
|
res2 = await client.get("/reservations/", headers={"Authorization": f"Bearer {token2}"})
|
||
|
|
assert res1.status_code == 200
|
||
|
|
assert res2.status_code == 200
|
||
|
|
# Each business sees only their own empty list
|
||
|
|
assert res1.json() == []
|
||
|
|
assert res2.json() == []
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Login
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
async def test_login_success(client: AsyncClient, db):
|
||
|
|
business = await make_business(db, name="Auth Test")
|
||
|
|
await make_user(db, business.id, email="test@example.com", password="mypassword")
|
||
|
|
|
||
|
|
response = await client.post("/auth/login", json={
|
||
|
|
"email": "test@example.com",
|
||
|
|
"password": "mypassword",
|
||
|
|
})
|
||
|
|
assert response.status_code == 200
|
||
|
|
data = response.json()
|
||
|
|
assert "access_token" in data
|
||
|
|
assert data["token_type"] == "bearer"
|
||
|
|
|
||
|
|
|
||
|
|
async def test_login_wrong_password(client: AsyncClient, db):
|
||
|
|
business = await make_business(db, name="Wrong Pass Test")
|
||
|
|
await make_user(db, business.id, email="wrong@example.com", password="correct")
|
||
|
|
|
||
|
|
response = await client.post("/auth/login", json={
|
||
|
|
"email": "wrong@example.com",
|
||
|
|
"password": "incorrect",
|
||
|
|
})
|
||
|
|
assert response.status_code == 401
|
||
|
|
|
||
|
|
|
||
|
|
async def test_login_unknown_email(client: AsyncClient, db):
|
||
|
|
response = await client.post("/auth/login", json={
|
||
|
|
"email": "noexiste@example.com",
|
||
|
|
"password": "cualquiera",
|
||
|
|
})
|
||
|
|
assert response.status_code == 401
|
||
|
|
|
||
|
|
|
||
|
|
async def test_protected_endpoint_without_token(client: AsyncClient):
|
||
|
|
response = await client.get("/business/me")
|
||
|
|
assert response.status_code == 403
|
||
|
|
|
||
|
|
|
||
|
|
async def test_protected_endpoint_with_token(client: AsyncClient, db):
|
||
|
|
business = await make_business(db, name="Protected Test")
|
||
|
|
await make_user(db, business.id, email="protected@example.com", password="pass123")
|
||
|
|
|
||
|
|
login = await client.post("/auth/login", json={
|
||
|
|
"email": "protected@example.com",
|
||
|
|
"password": "pass123",
|
||
|
|
})
|
||
|
|
token = login.json()["access_token"]
|
||
|
|
|
||
|
|
response = await client.get("/business/me", headers={"Authorization": f"Bearer {token}"})
|
||
|
|
assert response.status_code == 200
|
||
|
|
data = response.json()
|
||
|
|
assert data["id"] == business.id
|
||
|
|
assert data["name"] == "Protected Test"
|
||
|
|
|
||
|
|
|
||
|
|
async def test_logout_returns_204(client: AsyncClient):
|
||
|
|
response = await client.post("/auth/logout")
|
||
|
|
assert response.status_code == 204
|
||
|
|
|
||
|
|
|
||
|
|
async def test_refresh_token(client: AsyncClient, db):
|
||
|
|
business = await make_business(db, name="Refresh Test")
|
||
|
|
await make_user(db, business.id, email="refresh@example.com", password="pass")
|
||
|
|
|
||
|
|
login = await client.post("/auth/login", json={
|
||
|
|
"email": "refresh@example.com",
|
||
|
|
"password": "pass",
|
||
|
|
})
|
||
|
|
token = login.json()["access_token"]
|
||
|
|
|
||
|
|
response = await client.post("/auth/refresh", json={"access_token": token})
|
||
|
|
assert response.status_code == 200
|
||
|
|
assert "access_token" in response.json()
|