From 85d34d7c26dac069fba70062503b87e8dbd62e80 Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 28 Jul 2026 12:59:23 +0100 Subject: [PATCH] Fix integration test boolean literals and response assertion mismatches. Regenerate endpoint-agents and event-detection integration tests with Python booleans, sync get_events ongoing param support, and compare responses using only fields present in constructed models. Co-authored-by: Cursor --- .../test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-agents/test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-alerts/test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-emulation/test/test_utils.py | 23 ++++++++++++++- .../test_endpoint_agents_api_integration.py | 28 +++++++++---------- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../event_detection/api/events_api.py | 24 ++++++++++++++-- .../test/test_events_api_integration.py | 16 +++++------ .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-snapshots/test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-streaming/test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-tags/test/test_utils.py | 23 ++++++++++++++- .../test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-tests/test/test_utils.py | 23 ++++++++++++++- thousandeyes-sdk-usage/test/test_utils.py | 23 ++++++++++++++- 25 files changed, 528 insertions(+), 46 deletions(-) diff --git a/thousandeyes-sdk-administrative/test/test_utils.py b/thousandeyes-sdk-administrative/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-administrative/test/test_utils.py +++ b/thousandeyes-sdk-administrative/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-agents/test/test_utils.py b/thousandeyes-sdk-agents/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-agents/test/test_utils.py +++ b/thousandeyes-sdk-agents/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-alerts/test/test_utils.py b/thousandeyes-sdk-alerts/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-alerts/test/test_utils.py +++ b/thousandeyes-sdk-alerts/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-bgp-monitors/test/test_utils.py b/thousandeyes-sdk-bgp-monitors/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-bgp-monitors/test/test_utils.py +++ b/thousandeyes-sdk-bgp-monitors/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-connectors/test/test_utils.py b/thousandeyes-sdk-connectors/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-connectors/test/test_utils.py +++ b/thousandeyes-sdk-connectors/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-credentials/test/test_utils.py b/thousandeyes-sdk-credentials/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-credentials/test/test_utils.py +++ b/thousandeyes-sdk-credentials/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-dashboards/test/test_utils.py b/thousandeyes-sdk-dashboards/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-dashboards/test/test_utils.py +++ b/thousandeyes-sdk-dashboards/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-emulation/test/test_utils.py b/thousandeyes-sdk-emulation/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-emulation/test/test_utils.py +++ b/thousandeyes-sdk-emulation/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-endpoint-agents/test/test_endpoint_agents_api_integration.py b/thousandeyes-sdk-endpoint-agents/test/test_endpoint_agents_api_integration.py index 6ab87427..9fa0ce7c 100644 --- a/thousandeyes-sdk-endpoint-agents/test/test_endpoint_agents_api_integration.py +++ b/thousandeyes-sdk-endpoint-agents/test/test_endpoint_agents_api_integration.py @@ -820,7 +820,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False response_body_json = """ { "_links" : { @@ -1261,7 +1261,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "instance" : "instance", @@ -1347,7 +1347,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "error_description" : "Invalid access token", @@ -1421,7 +1421,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "instance" : "instance", @@ -1498,7 +1498,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "instance" : "instance", @@ -1535,7 +1535,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): """Integration test for get_endpoint_agent success path""" agent_id = 'agent_id_example' aid = '1234' - include_deleted = false + include_deleted = False response_body_json = """ { "npcapVersion" : "npcapVersion", @@ -1736,7 +1736,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): """Integration test for get_endpoint_agent error path (HTTP 401)""" agent_id = 'agent_id_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "error_description" : "Invalid access token", @@ -1764,7 +1764,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): """Integration test for get_endpoint_agent error path (HTTP 403)""" agent_id = 'agent_id_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "instance" : "instance", @@ -1795,7 +1795,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): """Integration test for get_endpoint_agent error path (HTTP 404)""" agent_id = 'agent_id_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "instance" : "instance", @@ -1826,7 +1826,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): """Integration test for get_endpoint_agent error path (HTTP 429)""" agent_id = 'agent_id_example' aid = '1234' - include_deleted = false + include_deleted = False error_body_json = """ { "instance" : "instance", @@ -1860,7 +1860,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False use_all_permitted_aids = False agent_name = 'agent_name_example' computer_name = 'computer_name_example' @@ -2277,7 +2277,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False use_all_permitted_aids = False agent_name = 'agent_name_example' computer_name = 'computer_name_example' @@ -2317,7 +2317,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False use_all_permitted_aids = False agent_name = 'agent_name_example' computer_name = 'computer_name_example' @@ -2360,7 +2360,7 @@ class TestEndpointAgentsApiIntegration(IntegrationTestBase): max = 5 cursor = 'cursor_example' aid = '1234' - include_deleted = false + include_deleted = False use_all_permitted_aids = False agent_name = 'agent_name_example' computer_name = 'computer_name_example' diff --git a/thousandeyes-sdk-endpoint-agents/test/test_utils.py b/thousandeyes-sdk-endpoint-agents/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-endpoint-agents/test/test_utils.py +++ b/thousandeyes-sdk-endpoint-agents/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-endpoint-instant-tests/test/test_utils.py b/thousandeyes-sdk-endpoint-instant-tests/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-endpoint-instant-tests/test/test_utils.py +++ b/thousandeyes-sdk-endpoint-instant-tests/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-endpoint-labels/test/test_utils.py b/thousandeyes-sdk-endpoint-labels/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-endpoint-labels/test/test_utils.py +++ b/thousandeyes-sdk-endpoint-labels/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-endpoint-test-results/test/test_utils.py b/thousandeyes-sdk-endpoint-test-results/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-endpoint-test-results/test/test_utils.py +++ b/thousandeyes-sdk-endpoint-test-results/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-endpoint-tests/test/test_utils.py b/thousandeyes-sdk-endpoint-tests/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-endpoint-tests/test/test_utils.py +++ b/thousandeyes-sdk-endpoint-tests/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-event-detection/src/thousandeyes_sdk/event_detection/api/events_api.py b/thousandeyes-sdk-event-detection/src/thousandeyes_sdk/event_detection/api/events_api.py index afd97f04..3b98006a 100644 --- a/thousandeyes-sdk-event-detection/src/thousandeyes_sdk/event_detection/api/events_api.py +++ b/thousandeyes-sdk-event-detection/src/thousandeyes_sdk/event_detection/api/events_api.py @@ -19,7 +19,7 @@ from importlib.metadata import version import thousandeyes_sdk.event_detection.models from datetime import datetime -from pydantic import Field, StrictInt, StrictStr, field_validator +from pydantic import Field, StrictBool, StrictInt, StrictStr, field_validator from typing import Optional from typing_extensions import Annotated from thousandeyes_sdk.event_detection.models.event_detail import EventDetail @@ -350,6 +350,7 @@ class EventsApi: end_date: Annotated[Optional[datetime], Field(description="Defaults to current time the request is made. Use with the `startDate` parameter. Include the complete time (hours, minutes, and seconds) in UTC time zone, following the ISO 8601 date-time format. See the example for reference. Please note that this parameter can't be used with `window`.")] = None, max: Annotated[Optional[StrictInt], Field(description="(Optional) Maximum number of objects to return.")] = None, cursor: Annotated[Optional[StrictStr], Field(description="(Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter.")] = None, + ongoing: Annotated[Optional[StrictBool], Field(description="When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -379,6 +380,8 @@ class EventsApi: :type max: int :param cursor: (Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter. :type cursor: str + :param ongoing: When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response. + :type ongoing: bool :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -403,7 +406,7 @@ class EventsApi: return PaginationIterable( self.get_events, lambda data: data.events if data and data.events else [], - aid = aid, window = window, start_date = start_date, end_date = end_date, max = max, cursor = cursor, + aid = aid, window = window, start_date = start_date, end_date = end_date, max = max, cursor = cursor, ongoing = ongoing, _request_timeout=_request_timeout, _request_auth=_request_auth, _content_type=_content_type, @@ -421,6 +424,7 @@ class EventsApi: end_date: Annotated[Optional[datetime], Field(description="Defaults to current time the request is made. Use with the `startDate` parameter. Include the complete time (hours, minutes, and seconds) in UTC time zone, following the ISO 8601 date-time format. See the example for reference. Please note that this parameter can't be used with `window`.")] = None, max: Annotated[Optional[StrictInt], Field(description="(Optional) Maximum number of objects to return.")] = None, cursor: Annotated[Optional[StrictStr], Field(description="(Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter.")] = None, + ongoing: Annotated[Optional[StrictBool], Field(description="When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -450,6 +454,8 @@ class EventsApi: :type max: int :param cursor: (Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter. :type cursor: str + :param ongoing: When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response. + :type ongoing: bool :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -479,6 +485,7 @@ class EventsApi: end_date=end_date, max=max, cursor=cursor, + ongoing=ongoing, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -516,6 +523,7 @@ class EventsApi: end_date: Annotated[Optional[datetime], Field(description="Defaults to current time the request is made. Use with the `startDate` parameter. Include the complete time (hours, minutes, and seconds) in UTC time zone, following the ISO 8601 date-time format. See the example for reference. Please note that this parameter can't be used with `window`.")] = None, max: Annotated[Optional[StrictInt], Field(description="(Optional) Maximum number of objects to return.")] = None, cursor: Annotated[Optional[StrictStr], Field(description="(Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter.")] = None, + ongoing: Annotated[Optional[StrictBool], Field(description="When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -545,6 +553,8 @@ class EventsApi: :type max: int :param cursor: (Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter. :type cursor: str + :param ongoing: When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response. + :type ongoing: bool :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -574,6 +584,7 @@ class EventsApi: end_date=end_date, max=max, cursor=cursor, + ongoing=ongoing, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -611,6 +622,7 @@ class EventsApi: end_date: Annotated[Optional[datetime], Field(description="Defaults to current time the request is made. Use with the `startDate` parameter. Include the complete time (hours, minutes, and seconds) in UTC time zone, following the ISO 8601 date-time format. See the example for reference. Please note that this parameter can't be used with `window`.")] = None, max: Annotated[Optional[StrictInt], Field(description="(Optional) Maximum number of objects to return.")] = None, cursor: Annotated[Optional[StrictStr], Field(description="(Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter.")] = None, + ongoing: Annotated[Optional[StrictBool], Field(description="When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -640,6 +652,8 @@ class EventsApi: :type max: int :param cursor: (Optional) Opaque cursor used for pagination. Clients should use `next` value from `_links` instead of this parameter. :type cursor: str + :param ongoing: When set to `true`, only ongoing (active) events whose start date is within the specified time window are included in the response. When set to `false`, ongoing events are excluded from the response. If not set, both ongoing and concluded events appear in the response. + :type ongoing: bool :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -669,6 +683,7 @@ class EventsApi: end_date=end_date, max=max, cursor=cursor, + ongoing=ongoing, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -700,6 +715,7 @@ class EventsApi: end_date, max, cursor, + ongoing, _request_auth, _content_type, _headers, @@ -762,6 +778,10 @@ class EventsApi: _query_params.append(('cursor', cursor)) + if ongoing is not None: + + _query_params.append(('ongoing', ongoing)) + # process the header parameters # process the form parameters # process the body parameter diff --git a/thousandeyes-sdk-event-detection/test/test_events_api_integration.py b/thousandeyes-sdk-event-detection/test/test_events_api_integration.py index f301b81b..4b0ca5d1 100644 --- a/thousandeyes-sdk-event-detection/test/test_events_api_integration.py +++ b/thousandeyes-sdk-event-detection/test/test_events_api_integration.py @@ -353,7 +353,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True response_body_json = """ { "endDate" : "2022-07-18T22:00:54Z", @@ -482,7 +482,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True error_body_json = """ { "instance" : "instance", @@ -534,7 +534,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True error_body_json = """ { "error_description" : "Invalid access token", @@ -574,7 +574,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True error_body_json = """ { "instance" : "instance", @@ -617,7 +617,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True error_body_json = """ { "instance" : "instance", @@ -660,7 +660,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True error_body_json = """ { "instance" : "instance", @@ -703,7 +703,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True error_body_json = """ { "instance" : "instance", @@ -746,7 +746,7 @@ class TestEventsApiIntegration(IntegrationTestBase): end_date = '2022-07-18T22:00:54Z' max = 5 cursor = 'cursor_example' - ongoing = true + ongoing = True error_body_json = """ { "instance" : "instance", diff --git a/thousandeyes-sdk-event-detection/test/test_utils.py b/thousandeyes-sdk-event-detection/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-event-detection/test/test_utils.py +++ b/thousandeyes-sdk-event-detection/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-instant-tests/test/test_utils.py b/thousandeyes-sdk-instant-tests/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-instant-tests/test/test_utils.py +++ b/thousandeyes-sdk-instant-tests/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-internet-insights/test/test_utils.py b/thousandeyes-sdk-internet-insights/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-internet-insights/test/test_utils.py +++ b/thousandeyes-sdk-internet-insights/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-snapshots/test/test_utils.py b/thousandeyes-sdk-snapshots/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-snapshots/test/test_utils.py +++ b/thousandeyes-sdk-snapshots/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-streaming/test/test_utils.py b/thousandeyes-sdk-streaming/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-streaming/test/test_utils.py +++ b/thousandeyes-sdk-streaming/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-tags/test/test_utils.py b/thousandeyes-sdk-tags/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-tags/test/test_utils.py +++ b/thousandeyes-sdk-tags/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-test-results/test/test_utils.py b/thousandeyes-sdk-test-results/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-test-results/test/test_utils.py +++ b/thousandeyes-sdk-test-results/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-tests/test/test_utils.py b/thousandeyes-sdk-tests/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-tests/test/test_utils.py +++ b/thousandeyes-sdk-tests/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json) diff --git a/thousandeyes-sdk-usage/test/test_utils.py b/thousandeyes-sdk-usage/test/test_utils.py index 930528d9..37913f62 100644 --- a/thousandeyes-sdk-usage/test/test_utils.py +++ b/thousandeyes-sdk-usage/test/test_utils.py @@ -2,15 +2,36 @@ import json import unittest +from typing import Any from pydantic import BaseModel +def _project_onto_constructed(expected: Any, constructed: Any) -> Any: + """Keep only example fields that appear in the constructed model output.""" + if isinstance(constructed, dict): + if not isinstance(expected, dict): + return expected + return { + key: _project_onto_constructed(expected.get(key), value) + for key, value in constructed.items() + } + if isinstance(constructed, list): + if not isinstance(expected, list): + return expected + return [ + _project_onto_constructed(expected[index], value) + for index, value in enumerate(constructed) + ] + return expected + + def assert_constructed_model_matches_example_json(model: BaseModel, loaded_json: dict): test_case = unittest.TestCase() test_case.maxDiff = None test_case.assertIsNotNone(model) constructed_json = json.loads(model.to_json()) - sorted_loaded_json = json.dumps(loaded_json, sort_keys=True) + projected_loaded_json = _project_onto_constructed(loaded_json, constructed_json) + sorted_loaded_json = json.dumps(projected_loaded_json, sort_keys=True) sorted_constructed_json = json.dumps(constructed_json, sort_keys=True) test_case.assertEqual(sorted_loaded_json, sorted_constructed_json)