From 0ae5f2bda55128261e22725815ffa67aa5b924fa Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 19 Jul 2026 14:13:35 -0500 Subject: [PATCH] feat: update API contract tests with new export request helper and update JSON formatting for route fixtures --- meshchatx.rsm | Bin 158741 -> 158741 bytes tests/backend/fixtures/http_api_routes.json | 78 +++++++++++++++---- tests/backend/http_api_contract_helpers.py | 2 +- tests/backend/test_messages_export.py | 13 +++- tests/backend/test_messages_export_bundle.py | 9 ++- tests/backend/test_telephone_audio_ws.py | 7 +- 6 files changed, 90 insertions(+), 19 deletions(-) diff --git a/meshchatx.rsm b/meshchatx.rsm index 53531b3e2635401881ca76be2eb3c08fc09c1eeb..e3194aba8fb3ad4246b81a5ed0d198a46a5eb6d8 100644 GIT binary patch delta 486 zcmWlVJ#5ZV7{zmiQV9)BQ_`WeAQEx!b3dNv4)~J}601cTk>`FqHrfzrRO2f}nBL*- zJ6I(ooq4U^bRuk`Z$e_wL2VK-Sp02gIp_S&>28d6H%6PgTg}enug^btzu8$DzUZ!` z@1Iuok9=Hq&!66@tEXo+|EwKdpSr#K=EC;%lb0q(ejI#L&h7Yn;^kL5d>w!7?KB5w z_T89x_-O3dZ13!c&u6agx;VdZ`PtN!;b85;q50qM=Dyrpe6^^Cx0;%QttDFoV>1z2 za-M}987PsB7+VZ_C(e_N4AqhmTN#}e1~0nbSyE3_6Sbxy1<1LOi!10*Z0nT-Db}h( zL5vuDkc_6HXTnz1wy>IPBK7B%)wS8CMF1$CLj-3E+m^1{3Oa&VAV5!8GIDi6CzCl; z(cqzq_cdXTzW4UAn&?dr)cC1(7r3koqZpT}K;kT>IHX{5#NwvxydU7ubMZj%|ktLa%*kx zVteTD=*+px zgG+?gfy^cat0HldK7zI$7y_tRG-X#$#-y3R$KK)%F)v!s36w@3W2}`?4Ax=JO6LN_ zOVF5-DH4HgR)I_Qrluf0V95}vcj2bEcDe;qjATq4vyWD~N^^9T2KLg05>-^37-KTd z21Q5(Q7M&7blGR!`?WLE6J2d||xREnuE1aC1UDq4}NzhtLD1EDq$ zoQrh_Dr0wQRvi3q+TVMyA@+@TfJhh8K0B!qJtT@QX&KntzzVQR9FVbD8gHs2tCXyj XITf&6RCj&3`r0pIPp|nbMrQs2??j?x diff --git a/tests/backend/fixtures/http_api_routes.json b/tests/backend/fixtures/http_api_routes.json index 9c9ea6ba..be57e21e 100644 --- a/tests/backend/fixtures/http_api_routes.json +++ b/tests/backend/fixtures/http_api_routes.json @@ -300,6 +300,58 @@ "method": "POST", "path": "/api/v1/favourites/{destination_hash}/rename" }, + { + "method": "GET", + "path": "/api/v1/filesync/acl" + }, + { + "method": "POST", + "path": "/api/v1/filesync/acl" + }, + { + "method": "POST", + "path": "/api/v1/filesync/announce" + }, + { + "method": "POST", + "path": "/api/v1/filesync/browse" + }, + { + "method": "POST", + "path": "/api/v1/filesync/connect" + }, + { + "method": "POST", + "path": "/api/v1/filesync/disconnect" + }, + { + "method": "POST", + "path": "/api/v1/filesync/download" + }, + { + "method": "GET", + "path": "/api/v1/filesync/files" + }, + { + "method": "GET", + "path": "/api/v1/filesync/peers" + }, + { + "method": "PATCH", + "path": "/api/v1/filesync/settings" + }, + { + "method": "POST", + "path": "/api/v1/filesync/start" + }, + { + "method": "GET", + "path": "/api/v1/filesync/status" + }, + { + "method": "POST", + "path": "/api/v1/filesync/stop" + }, { "method": "GET", "path": "/api/v1/gifs" @@ -536,21 +588,17 @@ "method": "DELETE", "path": "/api/v1/maintenance/messages" }, - { - "method": "GET", - "path": "/api/v1/maintenance/messages/export" - }, - { - "method": "GET", - "path": "/api/v1/maintenance/messages/duplicates" - }, { "method": "DELETE", "path": "/api/v1/maintenance/messages/duplicates" }, { "method": "GET", - "path": "/api/v1/maintenance/messages/purge-preview" + "path": "/api/v1/maintenance/messages/duplicates" + }, + { + "method": "GET", + "path": "/api/v1/maintenance/messages/export" }, { "method": "POST", @@ -560,6 +608,10 @@ "method": "POST", "path": "/api/v1/maintenance/messages/import-file" }, + { + "method": "GET", + "path": "/api/v1/maintenance/messages/purge-preview" + }, { "method": "DELETE", "path": "/api/v1/maintenance/path-table" @@ -1112,6 +1164,10 @@ "method": "POST", "path": "/api/v1/rnx/sessions/{session_id}/stop" }, + { + "method": "POST", + "path": "/api/v1/rrc/active/clear" + }, { "method": "GET", "path": "/api/v1/rrc/hubs" @@ -1172,10 +1228,6 @@ "method": "POST", "path": "/api/v1/rrc/hubs/{hub_hash}/rooms/{room}/read" }, - { - "method": "POST", - "path": "/api/v1/rrc/active/clear" - }, { "method": "GET", "path": "/api/v1/rrc/servers" diff --git a/tests/backend/http_api_contract_helpers.py b/tests/backend/http_api_contract_helpers.py index 2ba77fd1..dbeebfa9 100644 --- a/tests/backend/http_api_contract_helpers.py +++ b/tests/backend/http_api_contract_helpers.py @@ -67,6 +67,6 @@ def load_route_fixture(fixture_path: Path) -> list[dict[str, str]]: def write_route_fixture(fixture_path: Path, routes: list[dict[str, str]]) -> None: fixture_path.parent.mkdir(parents=True, exist_ok=True) fixture_path.write_text( - json.dumps({"routes": routes}, indent=2) + "\n", + json.dumps({"routes": routes}, indent=4) + "\n", encoding="utf-8", ) diff --git a/tests/backend/test_messages_export.py b/tests/backend/test_messages_export.py index 75226011..86eed8ce 100644 --- a/tests/backend/test_messages_export.py +++ b/tests/backend/test_messages_export.py @@ -21,6 +21,13 @@ def _make_json_request(body): return request +def _make_export_request(**query): + """GET export reads request.query. Bare MagicMock makes .get() truthy junk.""" + request = MagicMock() + request.query = dict(query) + return request + + def _make_multipart_file_request(body: bytes): class _MultipartField: name = "file" @@ -165,7 +172,7 @@ async def test_messages_export_with_icons(mock_rns_minimal, temp_dir): break assert handler is not None - request = MagicMock() + request = _make_export_request() response = await handler(request) data = json.loads(response.body) assert "messages" in data @@ -227,7 +234,7 @@ async def test_messages_export_without_icons(mock_rns_minimal, temp_dir): break assert handler is not None - request = MagicMock() + request = _make_export_request() response = await handler(request) data = json.loads(response.body) assert len(data["messages"]) == 1 @@ -283,7 +290,7 @@ async def test_messages_import_export_roundtrip(mock_rns_minimal, temp_dir): assert export_handler is not None assert import_handler is not None - export_response = await export_handler(MagicMock()) + export_response = await export_handler(_make_export_request()) export_data = json.loads(export_response.body) assert len(export_data["messages"]) == 1 assert "lxmf_icon" not in export_data["messages"][0] diff --git a/tests/backend/test_messages_export_bundle.py b/tests/backend/test_messages_export_bundle.py index 92bad668..62a02c04 100644 --- a/tests/backend/test_messages_export_bundle.py +++ b/tests/backend/test_messages_export_bundle.py @@ -26,6 +26,13 @@ def _make_json_request(body): return request +def _make_export_request(**query): + """GET export reads request.query. Bare MagicMock makes .get() truthy junk.""" + request = MagicMock() + request.query = dict(query) + return request + + @pytest.fixture def temp_dir(): dir_path = tempfile.mkdtemp() @@ -111,7 +118,7 @@ async def test_messages_export_includes_contacts_names_and_read_state( handler = route.handler break assert handler is not None - response = await handler(MagicMock()) + response = await handler(_make_export_request()) data = json.loads(response.body) assert data["format"] == MESSAGE_EXPORT_FORMAT diff --git a/tests/backend/test_telephone_audio_ws.py b/tests/backend/test_telephone_audio_ws.py index 3444939d..54d2f5ab 100644 --- a/tests/backend/test_telephone_audio_ws.py +++ b/tests/backend/test_telephone_audio_ws.py @@ -27,7 +27,12 @@ def web_audio_app(mock_app): @pytest.mark.asyncio -async def test_telephone_audio_ws_disabled_config_returns_error(web_audio_app): +async def test_telephone_audio_ws_disabled_config_returns_error( + web_audio_app, + monkeypatch, +): + monkeypatch.setattr(web_audio_app, "web_audio_required", lambda: False) + bridge = MagicMock() bridge.config_enabled.return_value = False bridge.send_status = AsyncMock()