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

158 lines
5.2 KiB
Python

"""
tests/test_api_templates.py
----------------------------
Tests for /api/templates/* endpoints.
All external API calls are mocked with respx.
"""
import pytest
import respx
import httpx
from fastapi.testclient import TestClient
from web.app import app
from web.session import _serializer, _COOKIE_NAME
client = TestClient(app, raise_server_exceptions=True)
def _make_session_cookie(data: dict) -> str:
"""Build a valid signed session cookie for testing."""
return _serializer.dumps(data)
def _adobe_session():
return _make_session_cookie({"adobe_access_token": "adobe-tok", "docusign_access_token": "ds-tok"})
def _ds_only_session():
return _make_session_cookie({"docusign_access_token": "ds-tok"})
def _adobe_only_session():
return _make_session_cookie({"adobe_access_token": "adobe-tok"})
ADOBE_BASE = "https://api.eu2.adobesign.com/api/rest/v6"
DS_BASE = "https://demo.docusign.net/restapi"
DS_ACCOUNT = "test-account-id"
@pytest.fixture(autouse=True)
def patch_account_id(monkeypatch):
import web.config as cfg
monkeypatch.setattr(cfg.settings, "docusign_account_id", DS_ACCOUNT)
monkeypatch.setattr(cfg.settings, "docusign_base_url", DS_BASE)
monkeypatch.setattr(cfg.settings, "adobe_sign_base_url", ADOBE_BASE)
def test_adobe_list_requires_auth():
"""No session → 401."""
resp = client.get("/api/templates/adobe", cookies={})
assert resp.status_code == 401
def test_docusign_list_requires_auth():
"""No session → 401."""
resp = client.get("/api/templates/docusign", cookies={})
assert resp.status_code == 401
@respx.mock
def test_adobe_list_returns_templates():
"""Authenticated → list of templates returned."""
respx.get(f"{ADOBE_BASE}/libraryDocuments").mock(
return_value=httpx.Response(200, json={
"libraryDocumentList": [
{"id": "abc1", "name": "NDA", "modifiedDate": "2026-04-10", "sharingMode": "USER"},
{"id": "abc2", "name": "Sales Agmt", "modifiedDate": "2026-04-12", "sharingMode": "USER"},
]
})
)
resp = client.get("/api/templates/adobe", cookies={_COOKIE_NAME: _adobe_only_session()})
assert resp.status_code == 200
data = resp.json()
assert len(data["templates"]) == 2
assert data["templates"][0]["name"] == "NDA"
@respx.mock
def test_docusign_list_returns_templates():
"""Authenticated → list of DocuSign templates returned."""
respx.get(f"{DS_BASE}/v2.1/accounts/{DS_ACCOUNT}/templates").mock(
return_value=httpx.Response(200, json={
"envelopeTemplates": [
{"templateId": "ds1", "name": "NDA", "lastModified": "2026-04-11"},
]
})
)
resp = client.get("/api/templates/docusign", cookies={_COOKIE_NAME: _ds_only_session()})
assert resp.status_code == 200
data = resp.json()
assert data["templates"][0]["id"] == "ds1"
@respx.mock
def test_status_not_migrated():
"""Adobe template with no matching DS name → not_migrated."""
respx.get(f"{ADOBE_BASE}/libraryDocuments").mock(
return_value=httpx.Response(200, json={
"libraryDocumentList": [
{"id": "adobe1", "name": "Onboarding", "modifiedDate": "2026-04-10"},
]
})
)
respx.get(f"{DS_BASE}/v2.1/accounts/{DS_ACCOUNT}/templates").mock(
return_value=httpx.Response(200, json={"envelopeTemplates": []})
)
resp = client.get("/api/templates/status", cookies={_COOKIE_NAME: _adobe_session()})
assert resp.status_code == 200
t = resp.json()["templates"][0]
assert t["status"] == "not_migrated"
assert t["docusign_id"] is None
@respx.mock
def test_status_migrated():
"""Adobe template with same name in DS and DS is newer → migrated."""
respx.get(f"{ADOBE_BASE}/libraryDocuments").mock(
return_value=httpx.Response(200, json={
"libraryDocumentList": [
{"id": "adobe1", "name": "NDA", "modifiedDate": "2026-04-10T00:00:00Z"},
]
})
)
respx.get(f"{DS_BASE}/v2.1/accounts/{DS_ACCOUNT}/templates").mock(
return_value=httpx.Response(200, json={
"envelopeTemplates": [
{"templateId": "ds1", "name": "NDA", "lastModified": "2026-04-11T00:00:00Z"},
]
})
)
resp = client.get("/api/templates/status", cookies={_COOKIE_NAME: _adobe_session()})
t = resp.json()["templates"][0]
assert t["status"] == "migrated"
assert t["docusign_id"] == "ds1"
@respx.mock
def test_status_needs_update():
"""Adobe template modified after the DS template → needs_update."""
respx.get(f"{ADOBE_BASE}/libraryDocuments").mock(
return_value=httpx.Response(200, json={
"libraryDocumentList": [
{"id": "adobe1", "name": "NDA", "modifiedDate": "2026-04-15T00:00:00Z"},
]
})
)
respx.get(f"{DS_BASE}/v2.1/accounts/{DS_ACCOUNT}/templates").mock(
return_value=httpx.Response(200, json={
"envelopeTemplates": [
{"templateId": "ds1", "name": "NDA", "lastModified": "2026-04-10T00:00:00Z"},
]
})
)
resp = client.get("/api/templates/status", cookies={_COOKIE_NAME: _adobe_session()})
t = resp.json()["templates"][0]
assert t["status"] == "needs_update"