Files
fastapi-users/tests/test_router_verify.py
François Voron 72aa68c462 Native model and generic ID (#971)
* Use a generic Protocol model for User instead of Pydantic

* Remove UserDB Pydantic schema

* Harmonize schema variable naming to avoid confusions

* Revamp OAuth account model management

* Revamp AccessToken DB strategy to adopt generic model approach

* Make ID a generic instead of forcing UUIDs

* Improve generic typing

* Improve Strategy typing

* Tweak base DB typing

* Don't set Pydantic schemas on FastAPIUsers class: pass it directly on router creation

* Add IntegerIdMixin and export related classes

* Start to revamp doc for V10

* Revamp OAuth documentation

* Fix code highlights

* Write the 9.x.x ➡️ 10.x.x migration doc

* Fix pyproject.toml
2022-05-05 14:51:19 +02:00

192 lines
6.5 KiB
Python

from typing import Any, AsyncGenerator, Dict, cast
import httpx
import pytest
from fastapi import FastAPI, status
from fastapi_users.manager import (
InvalidVerifyToken,
UserAlreadyVerified,
UserInactive,
UserNotExists,
)
from fastapi_users.router import ErrorCode, get_verify_router
from tests.conftest import AsyncMethodMocker, User, UserManagerMock, UserModel
@pytest.fixture
@pytest.mark.asyncio
async def test_app_client(
get_user_manager,
get_test_client,
) -> AsyncGenerator[httpx.AsyncClient, None]:
verify_router = get_verify_router(get_user_manager, User)
app = FastAPI()
app.include_router(verify_router)
async for client in get_test_client(app):
yield client
@pytest.mark.router
@pytest.mark.asyncio
class TestVerifyTokenRequest:
async def test_empty_body(
self,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
):
response = await test_app_client.post("/request-verify-token", json={})
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
assert user_manager.request_verify.called is False
async def test_wrong_email(
self,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
):
json = {"email": "king.arthur"}
response = await test_app_client.post("/request-verify-token", json=json)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
assert user_manager.request_verify.called is False
async def test_user_not_exists(
self,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
):
user_manager.get_by_email.side_effect = UserNotExists()
json = {"email": "user@example.com"}
response = await test_app_client.post("/request-verify-token", json=json)
assert response.status_code == status.HTTP_202_ACCEPTED
assert user_manager.request_verify.called is False
async def test_user_inactive(
self,
async_method_mocker: AsyncMethodMocker,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
user: UserModel,
):
async_method_mocker(user_manager, "get_by_email", return_value=user)
user_manager.request_verify.side_effect = UserInactive()
json = {"email": "user@example.com"}
response = await test_app_client.post("/request-verify-token", json=json)
assert response.status_code == status.HTTP_202_ACCEPTED
async def test_user_already_verified(
self,
async_method_mocker: AsyncMethodMocker,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
user: UserModel,
):
async_method_mocker(user_manager, "get_by_email", return_value=user)
user_manager.request_verify.side_effect = UserAlreadyVerified()
json = {"email": "user@example.com"}
response = await test_app_client.post("/request-verify-token", json=json)
assert response.status_code == status.HTTP_202_ACCEPTED
async def test_user_not_verified(
self,
async_method_mocker: AsyncMethodMocker,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
user: UserModel,
):
async_method_mocker(user_manager, "get_by_email", return_value=user)
async_method_mocker(user_manager, "request_verify", return_value=None)
json = {"email": "user@example.com"}
response = await test_app_client.post("/request-verify-token", json=json)
assert response.status_code == status.HTTP_202_ACCEPTED
async def test_token_namespace(
self,
get_user_manager,
):
verify_router = get_verify_router(
get_user_manager,
User,
)
app = FastAPI()
app.include_router(verify_router)
assert app.url_path_for("verify:request-token") == "/request-verify-token"
@pytest.mark.router
@pytest.mark.asyncio
class TestVerify:
async def test_empty_body(
self,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
):
response = await test_app_client.post("/verify", json={})
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
assert user_manager.verify.called is False
async def test_invalid_verify_token(
self,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
):
user_manager.verify.side_effect = InvalidVerifyToken()
response = await test_app_client.post("/verify", json={"token": "foo"})
assert response.status_code == status.HTTP_400_BAD_REQUEST
data = cast(Dict[str, Any], response.json())
assert data["detail"] == ErrorCode.VERIFY_USER_BAD_TOKEN
async def test_user_not_exists(
self,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
):
user_manager.verify.side_effect = UserNotExists()
response = await test_app_client.post("/verify", json={"token": "foo"})
assert response.status_code == status.HTTP_400_BAD_REQUEST
data = cast(Dict[str, Any], response.json())
assert data["detail"] == ErrorCode.VERIFY_USER_BAD_TOKEN
async def test_user_already_verified(
self,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
):
user_manager.verify.side_effect = UserAlreadyVerified()
response = await test_app_client.post("/verify", json={"token": "foo"})
assert response.status_code == status.HTTP_400_BAD_REQUEST
data = cast(Dict[str, Any], response.json())
assert data["detail"] == ErrorCode.VERIFY_USER_ALREADY_VERIFIED
async def test_success(
self,
async_method_mocker: AsyncMethodMocker,
test_app_client: httpx.AsyncClient,
user_manager: UserManagerMock,
user: UserModel,
):
async_method_mocker(user_manager, "verify", return_value=user)
response = await test_app_client.post("/verify", json={"token": "foo"})
assert response.status_code == status.HTTP_200_OK
data = cast(Dict[str, Any], response.json())
assert data["id"] == str(user.id)
async def test_verify_namespace(
self,
get_user_manager,
):
verify_router = get_verify_router(
get_user_manager,
User,
)
app = FastAPI()
app.include_router(verify_router)
assert app.url_path_for("verify:verify") == "/verify"