From 5de9dbfae771c3f3f4e9a6f7ded96949bb12844c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hansmann?= Date: Mon, 2 Dec 2024 21:23:18 +0100 Subject: [PATCH] PB-974: separate test files for opentransapi and stationboard Originally there were separate test files for opentransapi and the stationboard. This is now again the case, also several test cases got lost, which were re-added again. --- tests/integration/test_opentransapi.py | 95 +++++++++++++ tests/integration/test_stationboard.py | 190 +++++++++++-------------- 2 files changed, 175 insertions(+), 110 deletions(-) create mode 100644 tests/integration/test_opentransapi.py diff --git a/tests/integration/test_opentransapi.py b/tests/integration/test_opentransapi.py new file mode 100644 index 0000000000..09e075124f --- /dev/null +++ b/tests/integration/test_opentransapi.py @@ -0,0 +1,95 @@ +from datetime import datetime +from unittest.mock import Mock +from unittest.mock import patch + +from pytz import timezone +from pyramid.httpexceptions import HTTPBadRequest +import requests_mock + +from chsdi.lib.opentransapi import opentransapi +from chsdi.lib.opentransapi.opentransapi import format_time +from chsdi.views.stationboard import TransportView +from tests.integration import TestsBase +from tests.integration.helpers import generate_mock_response + + +class TestOpenTransApi(TestsBase): + def setUp(self): + self.mock_api_key = "dummy_api_key" + self.mock_url = "https://dummy-url.com" + + @requests_mock.Mocker() + def test_stationboard(self, mock_requests): + now = datetime.now(timezone('Europe/Zurich')).isoformat(timespec="microseconds") + mock_departures = [ + { + "id": "ch:1:sloid:30813::1", + "label": "Hogwarts Express", + "currentDate": now, + "departureDate": "2024-11-19T08:52:00Z", + "estimatedDate": "2024-11-19T08:52:00Z", + "destinationName": "Hogwarts", + "destinationId": "ch:1:sloid:91178::3", + } + ] + mock_response = generate_mock_response(mock_departures, now) + + mock_requests.post( + self.mock_url, + text=mock_response, + status_code=200 + ) + + api = opentransapi.OpenTrans(self.mock_api_key, self.mock_url) + results = api.get_departures(8501120, number_results=1) + + self.assertEqual(len(results), 1) + self.assertEqual(results[0]["id"], "ch:1:sloid:30813::1") + self.assertEqual(results[0]["label"], "Hogwarts Express") + self.assertEqual(results[0]["currentDate"], format_time(now)) + self.assertEqual(results[0]["departureDate"], format_time("2024-11-19T08:52:00Z")) + self.assertEqual(results[0]["estimatedDate"], format_time("2024-11-19T08:52:00Z")) + self.assertEqual(results[0]["destinationName"], "Hogwarts") + self.assertEqual(results[0]["destinationId"], "ch:1:sloid:91178::3") + + @requests_mock.Mocker() + def test_stationboard_nonexisting_station(self, mock_requests): + now = datetime.now(timezone('Europe/Zurich')).isoformat(timespec="microseconds") + # empty response in order to trigger the OpenTransNoStationException + mock_response = generate_mock_response([], now) + mock_requests.post(self.mock_url, text=mock_response, status_code=200) + + api = opentransapi.OpenTrans(self.mock_api_key, self.mock_url) + with self.assertRaises(opentransapi.OpenTransNoStationException): + api.get_departures(999999) + + @requests_mock.Mocker() + def test_stationboard_invalid_id(self, mock_requests): + now = datetime.now(timezone('Europe/Zurich')).isoformat(timespec="microseconds") + mock_response = generate_mock_response([], now) + mock_requests.post(self.mock_url, text=mock_response, status_code=200) + + api = opentransapi.OpenTrans(self.mock_api_key, self.mock_url) + with self.assertRaises(opentransapi.OpenTransNoStationException): + api.get_departures("invalid_id") + + @patch('chsdi.views.stationboard.get_current_registry') + def test_invalid_limit_param(self, mock_get_current_registry): + + mock_request = Mock() + mock_request.matched_route.name = 'stationboard' + mock_request.params = {} + mock_request.matchdict = {'id': '8501120'} + + mock_registry = Mock() + mock_registry.settings = { + 'opentrans_api_key': 'dummy_api_key', + 'opentrans_url': 'https://dummy-url.com', + } + mock_get_current_registry.return_value = mock_registry + + mock_request.params['limit'] = 'lalala' + + # Expect an HTTPBadRequest exception + with self.assertRaises(HTTPBadRequest): + TransportView(mock_request) diff --git a/tests/integration/test_stationboard.py b/tests/integration/test_stationboard.py index 0328c19487..aa31c0bdf1 100644 --- a/tests/integration/test_stationboard.py +++ b/tests/integration/test_stationboard.py @@ -4,139 +4,109 @@ from pytz import timezone from pyramid.httpexceptions import HTTPBadRequest +from pyramid.httpexceptions import HTTPNotFound + import requests_mock -from chsdi.lib.opentransapi import opentransapi from chsdi.lib.opentransapi.opentransapi import format_time from chsdi.views.stationboard import TransportView from tests.integration import TestsBase - - -def generate_mock_response(departures, now): - """Generate a dynamic mock OJP response with correct structure.""" - departure_events = "".join( - f""" - - - - - {dep['id']} - - {dep['label']} - - - {dep['departureDate']} - {dep.get('estimatedDate', dep['departureDate'])} - - - - - - {dep['label']} - - - {dep['destinationName']} - - {dep['destinationId']} - - - - """ - for dep in departures - ) - - mock_response = f""" - - - - {now} - - {now} - {departure_events} - - - - """ - - return mock_response +from tests.integration.helpers import generate_mock_response class TestStationboard(TestsBase): def setUp(self): - self.mock_api_key = "dummy_api_key" - self.mock_url = "https://dummy-url.com" + self.mock_request = Mock() + self.mock_request.matched_route.name = 'stationboard' + self.mock_request.params = {} + self.mock_request.matchdict = {} - @requests_mock.Mocker() - def test_stationboard(self, mock_requests): - now = datetime.now(timezone('Europe/Zurich')).isoformat(timespec="microseconds") + self.mock_registry = Mock() + self.mock_registry.settings = { + 'opentrans_api_key': 'dummy_api_key', + 'opentrans_url': 'https://dummy-url.com', + } + + @patch('chsdi.views.stationboard.get_current_registry') + def test_stationboard(self, mock_get_current_registry): + mock_get_current_registry.return_value = self.mock_registry + now = datetime.now(timezone('UTC')).strftime('%Y-%m-%dT%H:%M:%S.%f%z') mock_departures = [ { "id": "ch:1:sloid:30813::1", "label": "Hogwarts Express", - "currentDate": now, - "departureDate": "2024-11-19T08:52:00Z", - "estimatedDate": "2024-11-19T08:52:00Z", + "departureDate": now, + "estimatedDate": now, "destinationName": "Hogwarts", "destinationId": "ch:1:sloid:91178::3", } ] mock_response = generate_mock_response(mock_departures, now) - mock_requests.post( - self.mock_url, - text=mock_response, - status_code=200 - ) - - api = opentransapi.OpenTrans(self.mock_api_key, self.mock_url) - results = api.get_departures(8501120, number_results=1) - - self.assertEqual(len(results), 1) - self.assertEqual(results[0]["id"], "ch:1:sloid:30813::1") - self.assertEqual(results[0]["label"], "Hogwarts Express") - self.assertEqual(results[0]["currentDate"], format_time(now)) - self.assertEqual(results[0]["departureDate"], format_time("2024-11-19T08:52:00Z")) - self.assertEqual(results[0]["estimatedDate"], format_time("2024-11-19T08:52:00Z")) - self.assertEqual(results[0]["destinationName"], "Hogwarts") - self.assertEqual(results[0]["destinationId"], "ch:1:sloid:91178::3") - - @requests_mock.Mocker() - def test_stationboard_missing_station(self, mock_requests): - now = datetime.now(timezone('Europe/Zurich')).isoformat(timespec="microseconds") - mock_response = generate_mock_response([], now) - mock_requests.post(self.mock_url, text=mock_response, status_code=200) - - api = opentransapi.OpenTrans(self.mock_api_key, self.mock_url) - with self.assertRaises(opentransapi.OpenTransNoStationException): - api.get_departures(999999) - - @requests_mock.Mocker() - def test_stationboard_invalid_id(self, mock_requests): - now = datetime.now(timezone('Europe/Zurich')).isoformat(timespec="microseconds") - mock_response = generate_mock_response([], now) - mock_requests.post(self.mock_url, text=mock_response, status_code=200) - - api = opentransapi.OpenTrans(self.mock_api_key, self.mock_url) - with self.assertRaises(opentransapi.OpenTransNoStationException): - api.get_departures("invalid_id") + with requests_mock.Mocker() as m: + m.post(self.mock_registry.settings['opentrans_url'], text=mock_response) + + self.mock_request.matchdict = {"id": "99999"} + view = TransportView(self.mock_request) + resp = view.get_departures() + + self.assertEqual(len(resp), 1) + self.assertEqual(resp[0]["id"], "ch:1:sloid:30813::1") + self.assertEqual(resp[0]["label"], "Hogwarts Express") + self.assertEqual(resp[0]["departureDate"], format_time(now)) + self.assertEqual(resp[0]["estimatedDate"], format_time(now)) + self.assertEqual(resp[0]["destinationName"], "Hogwarts") + self.assertEqual(resp[0]["destinationId"], "ch:1:sloid:91178::3") @patch('chsdi.views.stationboard.get_current_registry') - def test_invalid_limit_param(self, mock_get_current_registry): + def test_stationboard_nonexisting_id(self, mock_get_current_registry): + mock_get_current_registry.return_value = self.mock_registry + now = datetime.now(timezone('UTC')).strftime('%Y-%m-%dT%H:%M:%S.%f%z') + nonexisting_id = "99999" + + # This will simulate the response of the OJP 2.0 API, when no station is found + mock_response = f""" + + + + {now} + + {now} + + + + + """ + + with requests_mock.Mocker() as m: + m.post(self.mock_registry.settings['opentrans_url'], text=mock_response) + self.mock_request.matchdict = {"id": nonexisting_id} + view = TransportView(self.mock_request) + + with self.assertRaises(HTTPNotFound) as e: + view.get_departures() + self.assertEqual(str(e.exception), f"No data available for the station {nonexisting_id}.") - mock_request = Mock() - mock_request.matched_route.name = 'stationboard' - mock_request.params = {} - mock_request.matchdict = {'id': '8501120'} + @patch('chsdi.views.stationboard.get_current_registry') + def test_stationboard_wrong_id(self, mock_get_current_registry): + mock_get_current_registry.return_value = self.mock_registry + wrong_id = "lalala" + self.mock_request.matchdict = {"id": wrong_id} - mock_registry = Mock() - mock_registry.settings = { - 'opentrans_api_key': 'dummy_api_key', - 'opentrans_url': 'https://dummy-url.com', - } - mock_get_current_registry.return_value = mock_registry + with self.assertRaises(HTTPBadRequest) as e: + _ = TransportView(self.mock_request) + self.assertEqual(str(e.exception), "The id must be an integer.") - mock_request.params['limit'] = 'lalala' + @patch('chsdi.views.stationboard.get_current_registry') + def test_stationboard_wrong_limit(self, mock_get_current_registry): + mock_get_current_registry.return_value = self.mock_registry + self.mock_request.params["limit"] = "lalala" + self.mock_request.matchdict = {"id": "123"} - # Expect an HTTPBadRequest exception - with self.assertRaises(HTTPBadRequest): - TransportView(mock_request) + with self.assertRaises(HTTPBadRequest) as e: + _ = TransportView(self.mock_request) + self.assertEqual(str(e.exception), "The limit parameter must be an integer.") + + @patch('chsdi.views.stationboard.get_current_registry') + def test_stationboard_with_cb(self, mock_get_current_registry): + pass