From 07042f56005c8d7011e12101301833abb85bc870 Mon Sep 17 00:00:00 2001 From: David Barrat Date: Sun, 5 Jan 2025 03:45:54 +0100 Subject: [PATCH] adding tests realtime python --- python/.gitignore | 4 +- python/examples/realtime.py | 0 .../realtime_events.py} | 5 +- python/test/test_dummy.py | 6 - python/test/test_realtime.py | 107 ++++++++++++++++++ 5 files changed, 114 insertions(+), 8 deletions(-) delete mode 100644 python/examples/realtime.py rename python/{__init__.py => examples/realtime_events.py} (80%) delete mode 100644 python/test/test_dummy.py create mode 100644 python/test/test_realtime.py diff --git a/python/.gitignore b/python/.gitignore index b07af7d..262ddb2 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -40,4 +40,6 @@ profile.json .env -__pycache__/ \ No newline at end of file +__pycache__/ +*.pyc +.pytest_cache/ \ No newline at end of file diff --git a/python/examples/realtime.py b/python/examples/realtime.py deleted file mode 100644 index e69de29..0000000 diff --git a/python/__init__.py b/python/examples/realtime_events.py similarity index 80% rename from python/__init__.py rename to python/examples/realtime_events.py index 915e059..06caecb 100644 --- a/python/__init__.py +++ b/python/examples/realtime_events.py @@ -1,5 +1,8 @@ +import os, sys +mypath = os.path.join(os.path.dirname(__file__), "..") +sys.path.append(mypath) + from modules.core import Kadoa -import os def process_event(event): print(f"Received event: {event['id']}, type: {event['type']}") diff --git a/python/test/test_dummy.py b/python/test/test_dummy.py deleted file mode 100644 index 87ff9b4..0000000 --- a/python/test/test_dummy.py +++ /dev/null @@ -1,6 +0,0 @@ -def inc(x): - return x + 1 - - -def test_answer(): - assert inc(4) == 5 \ No newline at end of file diff --git a/python/test/test_realtime.py b/python/test/test_realtime.py new file mode 100644 index 0000000..a82ba9a --- /dev/null +++ b/python/test/test_realtime.py @@ -0,0 +1,107 @@ +import os, sys +mypath = os.path.join(os.path.dirname(__file__), "..") +sys.path.append(mypath) + +import pytest +import json +import time +import threading +from unittest.mock import MagicMock, patch +from modules.realtime import Realtime + +@pytest.fixture +def mock_requests_post(): + with patch("requests.post") as mock_post: + mock_response = MagicMock() + mock_response.json.return_value = { + "access_token": "mock_access_token", + "team_id": "mock_team_id" + } + mock_post.return_value = mock_response + yield mock_post + +@pytest.fixture +def mock_websocket(): + with patch("websocket.WebSocketApp") as mock_ws: + yield mock_ws + +@pytest.fixture +def realtime_instance(mock_requests_post, mock_websocket): + instance = Realtime(team_api_key="mock_api_key") + instance.socket = MagicMock() # Ensure socket is mocked properly + return instance + +def test_init_missing_api_key(): + with pytest.raises(ValueError, match="teamApiKey is required for Realtime connection"): + Realtime(team_api_key=None) + +def test_connect_success(realtime_instance, mock_requests_post, mock_websocket): + realtime_instance.connect() + + assert realtime_instance.is_connecting is True + mock_requests_post.assert_called_once() + mock_websocket.assert_called_once() + +def test_connect_failure(mock_requests_post): + mock_requests_post.side_effect = Exception("Connection failed") + realtime = Realtime(team_api_key="mock_api_key") + + with patch("threading.Timer.start") as mock_timer: + realtime.connect() + mock_timer.assert_called_once() + +def test_on_open(realtime_instance): + ws_mock = MagicMock() + realtime_instance.team_id = "mock_team_id" # Explicitly set team_id + realtime_instance.socket = ws_mock # Ensure socket is assigned before testing + realtime_instance.on_open(ws_mock) + + assert realtime_instance.is_connecting is False + assert realtime_instance.last_heartbeat <= time.time() + ws_mock.send.assert_called_once_with(json.dumps({"action": "subscribe", "channel": "mock_team_id"})) + +def test_on_message_handle_heartbeat(realtime_instance): + ws_mock = MagicMock() + message = json.dumps({"type": "heartbeat"}) + realtime_instance.on_message(ws_mock, message) + + assert realtime_instance.last_heartbeat <= time.time() + +def test_on_message_handle_event(realtime_instance): + ws_mock = MagicMock() + event_data = {"type": "event", "data": "test"} + message = json.dumps(event_data) + + mock_callback = MagicMock() + realtime_instance.listen(mock_callback) + realtime_instance.on_message(ws_mock, message) + + mock_callback.assert_called_once_with(event_data) + +def test_on_close(realtime_instance): + ws_mock = MagicMock() + with patch("threading.Timer.start") as mock_timer: + realtime_instance.on_close(ws_mock, 1000, "Closed") + mock_timer.assert_called_once() + +def test_on_error(realtime_instance): + ws_mock = MagicMock() + error = "Test error" + realtime_instance.on_error(ws_mock, error) + + assert realtime_instance.is_connecting is False + +# def test_heartbeat_monitor(realtime_instance): +# realtime_instance.last_heartbeat = time.time() - 31 +# realtime_instance.socket = MagicMock() + +# with patch("time.sleep", side_effect=InterruptedError): +# with pytest.raises(InterruptedError): +# threading.Thread(target=realtime_instance.start_heartbeat_check).start() + +# realtime_instance.socket.close.assert_called_once() + +def test_listen(realtime_instance): + callback = MagicMock() + realtime_instance.listen(callback) + assert realtime_instance.handle_event == callback