Coverage for tests/test_documents.py: 100%
110 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-05 11:17 +0200
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-05 11:17 +0200
1"""Tests du sous-client documents (synchrone et asynchrone)."""
3from __future__ import annotations
5from typing import Any
7from unittest.mock import AsyncMock, MagicMock
9import pytest # type: ignore[import]
11from henrri_connect.connect import (
12 AsyncHenrriClient, SyncHenrriClient, # type: ignore[import]
13)
14from henrri_connect.models import Document, ValidateDocumentRequest, DocumentQuery
15from henrri_connect.models.base import DocumentKind, DocumentState
16from tests.conftest import DOCUMENT_JSON, PAGED_META, make_response
19def _paged(elements: list[Any]) -> dict[str, Any]:
20 return {"elements": elements, "meta": PAGED_META}
23class TestSyncDocuments:
24 """Tests du sous-client documents (synchrone)."""
25 def test_list_retourne_documents(
26 self, sync_client: SyncHenrriClient, mock_http: MagicMock
27 ) -> None:
28 """Test de la méthode list_documents()."""
29 mock_http.request.return_value = make_response(_paged([DOCUMENT_JSON]))
31 result = sync_client.documents.list_documents(request=DocumentQuery())
33 assert result.elements is not None
34 assert len(result.elements) == 1
35 assert result.elements[0].id == 100
37 def test_list_passe_les_filtres(
38 self, sync_client: SyncHenrriClient, mock_http: MagicMock
39 ) -> None:
40 """Test de la méthode list_documents()."""
41 mock_http.request.return_value = make_response(_paged([]))
43 sync_client.documents.list_documents(
44 request=DocumentQuery(
45 document_types=[DocumentKind.INVOICE], state=DocumentState.PENDING
46 ),
47 )
49 _, kwargs = mock_http.request.call_args
50 params = kwargs["params"]
51 # ``DocumentQuery`` serializes ``document_types`` as ``documentTypes`` and ``state`` as string
52 assert params.get("documentTypes") is not None
53 assert params["documentTypes"][0] == DocumentKind.INVOICE
54 assert params["state"] == "Pending"
56 def test_add_cree_document(
57 self, sync_client: SyncHenrriClient, mock_http: MagicMock
58 ) -> None:
59 """Test de la méthode add_document()."""
60 mock_http.request.return_value = make_response({**DOCUMENT_JSON, "id": 200})
61 doc = Document(document_type_id=1, customer_id=1) # type: ignore[call-arg]
63 result = sync_client.documents.add(doc)
65 assert result.id == 200
66 assert mock_http.request.call_args.args[0] == "POST"
68 def test_get_retourne_document(
69 self, sync_client: SyncHenrriClient, mock_http: MagicMock
70 ) -> None:
71 """Test de la méthode get_document()."""
72 mock_http.request.return_value = make_response(DOCUMENT_JSON)
74 result = sync_client.documents.get(100)
76 assert result.id == 100
77 assert "/v1/documents/100" in mock_http.request.call_args.args[1]
79 def test_modify_met_a_jour(
80 self, sync_client: SyncHenrriClient, mock_http: MagicMock
81 ) -> None:
82 """Test de la méthode modify_document()."""
83 updated: dict[str, Any] = {**DOCUMENT_JSON, "title": "Facture modifiée"}
84 mock_http.request.return_value = make_response(updated)
86 result = sync_client.documents.modify(
87 100, Document(document_type_id=1, customer_id=1) # type: ignore[call-arg]
88 )
90 assert result.title == "Facture modifiée"
91 assert mock_http.request.call_args.args[0] == "PUT"
93 def test_delete(
94 self, sync_client: SyncHenrriClient, mock_http: MagicMock
95 ) -> None:
96 """Test de la méthode delete_document()."""
97 mock_http.request.return_value = make_response({})
99 sync_client.documents.delete(100)
101 assert mock_http.request.call_args.args[0] == "DELETE"
103 def test_get_tax_details(
104 self, sync_client: SyncHenrriClient, mock_http: MagicMock
105 ) -> None:
106 """Test de la méthode get_tax_details()."""
107 mock_http.request.return_value = make_response(
108 {
109 "taxDetailArray": [
110 {
111 "rate": 20.0,
112 "priceBeforeTax": 100.0,
113 "taxAmount": 20.0,
114 "priceAfterTax": 120.0
115 }
116 ]
117 }
118 )
120 result = sync_client.documents.get_tax_details(100)
122 assert result.tax_detail_array is not None
123 assert len(result.tax_detail_array) == 1
124 assert result.tax_detail_array[0].rate == pytest.approx(20.0) # type: ignore[misc]
126 def test_validate_document(
127 self, sync_client: SyncHenrriClient, mock_http: MagicMock
128 ) -> None:
129 """Test de la méthode validate_document()."""
130 mock_http.request.return_value = make_response({**DOCUMENT_JSON, "validated": True})
131 req = ValidateDocumentRequest(
132 email="sign@example.com",
133 first_name="Jean",
134 last_name="Dupont",
135 validation_date="2025-01-01",
136 time_offset=60,
137 ip="127.0.0.1",
138 )
140 result = sync_client.documents.validate(100, req)
142 assert result.validated is True
143 assert mock_http.request.call_args.args[0] == "POST"
144 assert "/v1/documents/100/validate" in mock_http.request.call_args.args[1]
146 def test_get_pdf_url(
147 self, sync_client: SyncHenrriClient, mock_http: MagicMock
148 ) -> None:
149 """Test de la méthode get_pdf_url()."""
150 mock_http.request.return_value = make_response(
151 {
152 "downloadUrl": "https://cdn.example.com/facture.pdf",
153 "fileName": "facture.pdf"
154 }
155 )
157 result = sync_client.documents.get_pdf_url(100)
159 assert result.download_url == "https://cdn.example.com/facture.pdf"
161 def test_get_pdf_bytes(
162 self, sync_client: SyncHenrriClient, mock_http: MagicMock
163 ) -> None:
164 """Test de la méthode get_pdf_bytes()."""
165 pdf_bytes = b"%PDF-1.4 test"
166 mock_http.request.return_value = make_response({}, content=pdf_bytes)
168 result = sync_client.documents.get_pdf_bytes(100)
170 assert result == pdf_bytes
172 def test_finalize(
173 self, sync_client: SyncHenrriClient, mock_http: MagicMock
174 ) -> None:
175 """Test de la méthode finalize()."""
176 mock_http.request.return_value = make_response({**DOCUMENT_JSON, "finalized": True})
178 result = sync_client.documents.finalize(100)
180 assert result.finalized is True
181 assert "/v1/documents/100/finalize" in mock_http.request.call_args.args[1]
183 def test_transform_to_invoice(
184 self, sync_client: SyncHenrriClient, mock_http: MagicMock
185 ) -> None:
186 """Test de la méthode transform_to_invoice()."""
187 mock_http.request.return_value = make_response({**DOCUMENT_JSON, "id": 101})
189 result = sync_client.documents.transform_to_invoice(100)
191 assert result.id == 101
192 assert "/transform-to-invoice" in mock_http.request.call_args.args[1]
194 def test_get_payment_milestones(
195 self, sync_client: SyncHenrriClient, mock_http: MagicMock
196 ) -> None:
197 """Test de la méthode get_payment_milestones()."""
198 milestone: dict[str, Any] = {
199 "id": 1,
200 "dueDate": "2025-06-30T00:00:00",
201 "isPaid": False,
202 "documentId": 100,
203 }
204 mock_http.request.return_value = make_response({"elements": [milestone]})
206 result = sync_client.documents.get_payment_milestones(100)
208 assert result.elements is not None
209 assert len(result.elements) == 1
210 assert result.elements[0].document_id == 100
212 def test_get_with_all(
213 self, sync_client: SyncHenrriClient, mock_http: MagicMock
214 ) -> None:
215 """Test de la méthode get_with_all()."""
216 mock_http.request.return_value = make_response(DOCUMENT_JSON)
218 result = sync_client.documents.get_with_all(100)
220 assert result.id == 100
221 assert "/with-all" in mock_http.request.call_args.args[1]
224class TestAsyncDocuments:
225 """Test de la classe AsyncDocuments."""
226 async def test_list_retourne_documents(
227 self, async_client: AsyncHenrriClient, mock_async_http: AsyncMock
228 ) -> None:
229 """Test de la méthode list_documents()."""
230 mock_async_http.request.return_value = make_response(_paged([DOCUMENT_JSON]))
232 result = await async_client.documents.list_documents(request=DocumentQuery())
234 assert result.elements is not None
235 assert len(result.elements) == 1
236 assert result.elements[0].id == 100
238 async def test_get_retourne_document(
239 self, async_client: AsyncHenrriClient, mock_async_http: AsyncMock
240 ) -> None:
241 """Test de la méthode get_document()."""
242 mock_async_http.request.return_value = make_response(DOCUMENT_JSON)
244 result = await async_client.documents.get(100)
246 assert result.id == 100
248 async def test_finalize(
249 self, async_client: AsyncHenrriClient, mock_async_http: AsyncMock
250 ) -> None:
251 """Test de la méthode finalize()."""
252 mock_async_http.request.return_value = make_response({**DOCUMENT_JSON, "finalized": True})
254 result = await async_client.documents.finalize(100)
256 assert result.finalized is True
258 async def test_get_pdf_bytes(
259 self, async_client: AsyncHenrriClient, mock_async_http: AsyncMock
260 ) -> None:
261 """Test de la méthode get_pdf_bytes()."""
262 pdf_bytes = b"%PDF-1.4 async"
263 mock_async_http.request.return_value = make_response({}, content=pdf_bytes)
265 result = await async_client.documents.get_pdf_bytes(100)
267 assert result == pdf_bytes