From 42deaca0e25f5dbb6c5133dc969366b93526960f Mon Sep 17 00:00:00 2001 From: Karel Hovorka Date: Mon, 13 May 2024 13:22:18 +0700 Subject: [PATCH] Made WebsocketCommunicator assertions more informative. (#2098) --- channels/testing/websocket.py | 14 ++++++++++---- tests/test_testing.py | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/channels/testing/websocket.py b/channels/testing/websocket.py index dd48686d9..57ea4a653 100644 --- a/channels/testing/websocket.py +++ b/channels/testing/websocket.py @@ -78,19 +78,23 @@ async def receive_from(self, timeout=1): """ response = await self.receive_output(timeout) # Make sure this is a send message - assert response["type"] == "websocket.send" + assert ( + response["type"] == "websocket.send" + ), f"Expected type 'websocket.send', but was '{response['type']}'" # Make sure there's exactly one key in the response assert ("text" in response) != ( "bytes" in response ), "The response needs exactly one of 'text' or 'bytes'" # Pull out the right key and typecheck it for our users if "text" in response: - assert isinstance(response["text"], str), "Text frame payload is not str" + assert isinstance( + response["text"], str + ), f"Text frame payload is not str, it is {type(response['text'])}" return response["text"] else: assert isinstance( response["bytes"], bytes - ), "Binary frame payload is not bytes" + ), f"Binary frame payload is not bytes, it is {type(response['bytes'])}" return response["bytes"] async def receive_json_from(self, timeout=1): @@ -98,7 +102,9 @@ async def receive_json_from(self, timeout=1): Receives a JSON text frame payload and decodes it """ payload = await self.receive_from(timeout) - assert isinstance(payload, str), "JSON data is not a text frame" + assert isinstance( + payload, str + ), f"JSON data is not a text frame, it is {type(payload)}" return json.loads(payload) async def disconnect(self, code=1000, timeout=1): diff --git a/tests/test_testing.py b/tests/test_testing.py index 12164b9af..6beae7d5b 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -47,6 +47,13 @@ def receive(self, text_data=None, bytes_data=None): self.send(text_data=text_data, bytes_data=bytes_data) +class AcceptCloseWebsocketApp(WebsocketConsumer): + def connect(self): + assert self.scope["path"] == "/testws/" + self.accept() + self.close() + + class ErrorWebsocketApp(WebsocketConsumer): """ Barebones WebSocket ASGI app for error testing. @@ -93,6 +100,25 @@ async def test_websocket_communicator(): await communicator.disconnect() +@pytest.mark.django_db +@pytest.mark.asyncio +async def test_websocket_incorrect_read_json(): + """ + When using an invalid communicator method, an assertion error will be raised with + informative message. + In this test, the server accepts and then immediately closes the connection so + the server is not in a valid state to handle "receive_from". + """ + communicator = WebsocketCommunicator(AcceptCloseWebsocketApp(), "/testws/") + await communicator.connect() + with pytest.raises(AssertionError) as exception_info: + await communicator.receive_from() + assert ( + str(exception_info.value) + == "Expected type 'websocket.send', but was 'websocket.close'" + ) + + @pytest.mark.django_db @pytest.mark.asyncio async def test_websocket_application():