adobe-to-docusign-migrator/tests/test_api_auth.py

139 lines
4.9 KiB
Python

"""
tests/test_api_auth.py
----------------------
Tests for /api/auth/* endpoints.
All external OAuth calls are mocked with respx.
"""
import pytest
import respx
import httpx
from fastapi.testclient import TestClient
from web.app import app
from web.routers.auth import _ADOBE_TOKEN_URL
client = TestClient(app, raise_server_exceptions=True)
def test_status_unauthenticated():
"""Fresh session → both platforms disconnected."""
resp = client.get("/api/auth/status", cookies={})
assert resp.status_code == 200
data = resp.json()
assert data["adobe"] is False
assert data["docusign"] is False
def test_adobe_url_returns_auth_url():
"""GET /api/auth/adobe/url returns an Adobe Sign authorization URL."""
resp = client.get("/api/auth/adobe/url")
assert resp.status_code == 200
data = resp.json()
assert "url" in data
assert "adobesign.com" in data["url"]
assert "response_type=code" in data["url"]
# Must use the registered redirect URI
assert "localhost%3A8080" in data["url"] or "localhost:8080" in data["url"]
def test_adobe_connect_env_stores_token(monkeypatch):
"""GET /api/auth/adobe/connect uses .env refresh token → session connected."""
monkeypatch.setenv("ADOBE_ACCESS_TOKEN", "existing-token")
monkeypatch.setenv("ADOBE_REFRESH_TOKEN", "existing-refresh")
from unittest.mock import patch
with patch("adobe_api._refresh_access_token", return_value="refreshed-token"):
resp = client.get("/api/auth/adobe/connect")
assert resp.status_code == 200
assert resp.json()["connected"] is True
session_cookie = resp.cookies.get("migrator_session")
status_resp = client.get("/api/auth/status", cookies={"migrator_session": session_cookie})
assert status_resp.json()["adobe"] is True
def test_adobe_connect_env_fails_without_credentials(monkeypatch):
"""GET /api/auth/adobe/connect with no .env tokens → 400."""
monkeypatch.delenv("ADOBE_ACCESS_TOKEN", raising=False)
monkeypatch.delenv("ADOBE_REFRESH_TOKEN", raising=False)
resp = client.get("/api/auth/adobe/connect")
assert resp.status_code == 400
assert "No Adobe Sign credentials" in resp.json()["error"]
@respx.mock
def test_adobe_exchange_stores_token():
"""POST /api/auth/adobe/exchange with a valid redirect URL → session connected."""
respx.post(_ADOBE_TOKEN_URL).mock(
return_value=httpx.Response(200, json={
"access_token": "adobe-test-token",
"refresh_token": "adobe-refresh",
})
)
resp = client.post(
"/api/auth/adobe/exchange",
json={"redirect_url": "https://localhost:8080/callback?code=authcode123&api_access_point=https://api.eu2.adobesign.com/"},
)
assert resp.status_code == 200
assert resp.json()["connected"] is True
session_cookie = resp.cookies.get("migrator_session")
assert session_cookie is not None
status_resp = client.get("/api/auth/status", cookies={"migrator_session": session_cookie})
assert status_resp.json()["adobe"] is True
def test_adobe_exchange_rejects_missing_code():
"""POST /api/auth/adobe/exchange with no code in URL → 400."""
resp = client.post(
"/api/auth/adobe/exchange",
json={"redirect_url": "https://localhost:8080/callback?error=access_denied"},
)
assert resp.status_code == 400
def test_docusign_connect_stores_token():
"""GET /api/auth/docusign/connect uses JWT grant from .env → session connected."""
from unittest.mock import patch
import web.routers.auth as auth_module
with patch("docusign_auth.get_access_token", return_value="ds-jwt-token"):
resp = client.get("/api/auth/docusign/connect")
assert resp.status_code == 200
assert resp.json()["connected"] is True
session_cookie = resp.cookies.get("migrator_session")
assert session_cookie is not None
status_resp = client.get("/api/auth/status", cookies={"migrator_session": session_cookie})
assert status_resp.json()["docusign"] is True
@respx.mock
def test_disconnect_clears_token():
"""After disconnect, status shows platform as disconnected."""
respx.post(_ADOBE_TOKEN_URL).mock(
return_value=httpx.Response(200, json={"access_token": "tok", "refresh_token": "ref"})
)
# Connect Adobe via exchange
connect_resp = client.post(
"/api/auth/adobe/exchange",
json={"redirect_url": "https://localhost:8080/callback?code=abc"},
)
session_cookie = connect_resp.cookies["migrator_session"]
status_resp = client.get("/api/auth/status", cookies={"migrator_session": session_cookie})
assert status_resp.json()["adobe"] is True
disc_resp = client.get("/api/auth/adobe/disconnect", cookies={"migrator_session": session_cookie})
assert disc_resp.status_code == 200
new_cookie = disc_resp.cookies.get("migrator_session", session_cookie)
status_resp2 = client.get("/api/auth/status", cookies={"migrator_session": new_cookie})
assert status_resp2.json()["adobe"] is False