feat: sync latest ARR implementation

This commit is contained in:
Wyndham ARR
2026-07-31 15:11:42 +08:00
parent d6f8a747fa
commit bf7939dd1a
185 changed files with 17527 additions and 2260 deletions

View File

@@ -0,0 +1,151 @@
from __future__ import annotations
import http.client
import json
import threading
import unittest
from contextlib import contextmanager
from http.server import ThreadingHTTPServer
from typing import Any, Iterator, Mapping
from arr_web.contracts import MAX_UPLOAD_BYTES, Response, success
from arr_web.server import handler_for
class RecordingApplication:
def __init__(self) -> None:
self.calls: list[dict[str, Any]] = []
def handle(
self,
method: str,
path: str,
headers: Mapping[str, str],
body: bytes,
*,
client_id: str,
) -> Response:
self.calls.append(
{
"method": method,
"path": path,
"headers": dict(headers),
"body": body,
"client_id": client_id,
}
)
return Response.json(200, success({"method": method}))
@contextmanager
def running_server(
application: RecordingApplication,
) -> Iterator[tuple[str, int]]:
server = ThreadingHTTPServer(("127.0.0.1", 0), handler_for(application))
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
host, port = server.server_address
yield str(host), int(port)
finally:
server.shutdown()
server.server_close()
thread.join(timeout=5)
class PortalHttpAdapterTests(unittest.TestCase):
def test_patch_and_delete_forward_json_bodies_to_application(self) -> None:
application = RecordingApplication()
with running_server(application) as (host, port):
connection = http.client.HTTPConnection(host, port, timeout=5)
try:
patch_body = json.dumps(
{"draft_id": "bookingdraft-test", "room_type": "U-TWN", "quantity": 2}
).encode("utf-8")
connection.request(
"PATCH",
"/api/company-reports/source/draft/items/7",
body=patch_body,
headers={"Content-Type": "application/json"},
)
patch_response = connection.getresponse()
self.assertEqual(patch_response.status, 200)
self.assertEqual(patch_response.getheader("X-Content-Type-Options"), "nosniff")
patch_response.read()
delete_body = b'{"draft_id":"bookingdraft-test"}'
connection.request(
"DELETE",
"/api/company-reports/source/draft/items/7",
body=delete_body,
headers={"Content-Type": "application/json"},
)
delete_response = connection.getresponse()
self.assertEqual(delete_response.status, 200)
delete_response.read()
batch_delete_body = b'{"draft_id":"bookingdraft-test","item_ids":[7,8]}'
connection.request(
"DELETE",
"/api/company-reports/source/draft/items",
body=batch_delete_body,
headers={"Content-Type": "application/json"},
)
batch_delete_response = connection.getresponse()
self.assertEqual(batch_delete_response.status, 200)
batch_delete_response.read()
finally:
connection.close()
self.assertEqual(
[(call["method"], call["body"]) for call in application.calls],
[
("PATCH", patch_body),
("DELETE", delete_body),
("DELETE", batch_delete_body),
],
)
self.assertEqual(
[call["path"] for call in application.calls],
[
"/api/company-reports/source/draft/items/7",
"/api/company-reports/source/draft/items/7",
"/api/company-reports/source/draft/items",
],
)
def test_mutation_methods_reject_missing_or_oversized_content_length(self) -> None:
application = RecordingApplication()
with running_server(application) as (host, port):
missing = http.client.HTTPConnection(host, port, timeout=5)
try:
missing.putrequest("PATCH", "/api/company-reports/source/draft/items/7")
missing.endheaders()
missing_response = missing.getresponse()
self.assertEqual(missing_response.status, 411)
self.assertEqual(
json.loads(missing_response.read())["error"]["code"],
"CONTENT_LENGTH_REQUIRED",
)
finally:
missing.close()
oversized = http.client.HTTPConnection(host, port, timeout=5)
try:
oversized.putrequest("DELETE", "/api/company-reports/source/draft")
oversized.putheader("Content-Length", str(MAX_UPLOAD_BYTES + 1))
oversized.endheaders()
oversized_response = oversized.getresponse()
self.assertEqual(oversized_response.status, 413)
self.assertEqual(
json.loads(oversized_response.read())["error"]["code"],
"REQUEST_TOO_LARGE",
)
finally:
oversized.close()
self.assertEqual(application.calls, [])
if __name__ == "__main__":
unittest.main()