2026-09-24 08:12:42 +00:00
|
|
|
import asyncio
|
|
|
|
|
|
2026-01-22 10:37:35 +00:00
|
|
|
import pytest
|
|
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
from signing_service.application.errors import (
|
|
|
|
|
InvalidPdfError,
|
|
|
|
|
SecretProviderError,
|
|
|
|
|
ServiceError,
|
2026-01-22 10:37:35 +00:00
|
|
|
)
|
2026-09-24 08:12:42 +00:00
|
|
|
from signing_service.application.use_cases.sign_document import SignDocumentUseCase
|
|
|
|
|
from signing_service.application.use_cases.sign_document_dto import SignDocumentCommand
|
2026-01-22 10:37:35 +00:00
|
|
|
from signing_service.infrastructure.pdf.fake_pdf_signer import FakePDFSigner
|
2026-09-24 08:12:42 +00:00
|
|
|
from signing_service.infrastructure.pdf.pdf_validator_error import PDFValidationError
|
|
|
|
|
from signing_service.infrastructure.secrets.fake_secret_manager import FakeSecretManager
|
|
|
|
|
|
|
|
|
|
CERT_NAME = "configured-cert"
|
|
|
|
|
PASSWORD_NAME = "configured-password"
|
2026-01-22 10:37:35 +00:00
|
|
|
|
|
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
def command() -> SignDocumentCommand:
|
|
|
|
|
return SignDocumentCommand(
|
|
|
|
|
pdf_bytes=b"%PDF-1.4 fake pdf content",
|
|
|
|
|
certificate_secret_name="legacy-cert-name",
|
|
|
|
|
certificate_password_secret_name="legacy-password-name",
|
|
|
|
|
company_slug="legacy-company",
|
|
|
|
|
)
|
|
|
|
|
|
2026-01-22 10:37:35 +00:00
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
def test_sign_document_success() -> None:
|
2026-01-22 10:37:35 +00:00
|
|
|
use_case = SignDocumentUseCase(
|
2026-09-24 08:12:42 +00:00
|
|
|
secret_manager=FakeSecretManager(
|
|
|
|
|
{CERT_NAME: "certificate", PASSWORD_NAME: "password"}
|
|
|
|
|
),
|
|
|
|
|
pdf_signer=FakePDFSigner(),
|
|
|
|
|
cert_secret_name=CERT_NAME,
|
|
|
|
|
cert_password_secret_name=PASSWORD_NAME,
|
2026-01-22 10:37:35 +00:00
|
|
|
)
|
|
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
result = asyncio.run(use_case.execute(command()))
|
|
|
|
|
|
|
|
|
|
assert result.signed_pdf_bytes.startswith(command().pdf_bytes)
|
|
|
|
|
assert result.signed_pdf_bytes.endswith(b"-- Signed by fake signer")
|
|
|
|
|
assert b"certificate" not in result.signed_pdf_bytes
|
|
|
|
|
assert b"password" not in result.signed_pdf_bytes
|
|
|
|
|
|
2026-01-22 10:37:35 +00:00
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
def test_sign_document_maps_secret_manager_errors() -> None:
|
|
|
|
|
use_case = SignDocumentUseCase(
|
|
|
|
|
secret_manager=FakeSecretManager({}),
|
|
|
|
|
pdf_signer=FakePDFSigner(),
|
|
|
|
|
cert_secret_name=CERT_NAME,
|
|
|
|
|
cert_password_secret_name=PASSWORD_NAME,
|
2026-01-22 10:37:35 +00:00
|
|
|
)
|
|
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
with pytest.raises(SecretProviderError):
|
|
|
|
|
asyncio.run(use_case.execute(command()))
|
|
|
|
|
|
2026-01-22 10:37:35 +00:00
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
class FailingSigner:
|
|
|
|
|
async def sign(self, **kwargs: object) -> bytes:
|
|
|
|
|
raise RuntimeError("PFX password was rejected")
|
2026-01-22 10:37:35 +00:00
|
|
|
|
|
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
class InvalidPdfSigner:
|
|
|
|
|
async def sign(self, **kwargs: object) -> bytes:
|
|
|
|
|
raise PDFValidationError("internal parsing detail")
|
2026-01-22 10:37:35 +00:00
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
|
|
|
|
|
def test_sign_document_maps_signer_errors() -> None:
|
2026-01-22 10:37:35 +00:00
|
|
|
use_case = SignDocumentUseCase(
|
2026-09-24 08:12:42 +00:00
|
|
|
secret_manager=FakeSecretManager(
|
|
|
|
|
{CERT_NAME: "certificate", PASSWORD_NAME: "password"}
|
|
|
|
|
),
|
|
|
|
|
pdf_signer=FailingSigner(), # type: ignore[arg-type]
|
|
|
|
|
cert_secret_name=CERT_NAME,
|
|
|
|
|
cert_password_secret_name=PASSWORD_NAME,
|
2026-01-22 10:37:35 +00:00
|
|
|
)
|
|
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
with pytest.raises(ServiceError) as caught:
|
|
|
|
|
asyncio.run(use_case.execute(command()))
|
|
|
|
|
|
|
|
|
|
assert caught.value.code == "SIGNING_FAILED"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_sign_document_maps_invalid_pdf_errors() -> None:
|
|
|
|
|
use_case = SignDocumentUseCase(
|
|
|
|
|
secret_manager=FakeSecretManager(
|
|
|
|
|
{CERT_NAME: "certificate", PASSWORD_NAME: "password"}
|
|
|
|
|
),
|
|
|
|
|
pdf_signer=InvalidPdfSigner(), # type: ignore[arg-type]
|
|
|
|
|
cert_secret_name=CERT_NAME,
|
|
|
|
|
cert_password_secret_name=PASSWORD_NAME,
|
2026-01-22 10:37:35 +00:00
|
|
|
)
|
|
|
|
|
|
2026-09-24 08:12:42 +00:00
|
|
|
with pytest.raises(InvalidPdfError):
|
|
|
|
|
asyncio.run(use_case.execute(command()))
|