diff --git a/thousandeyes-sdk-core/test/sdk_test_support/mock_server.py b/thousandeyes-sdk-core/test/sdk_test_support/mock_server.py index 8479728d..33e9d38b 100644 --- a/thousandeyes-sdk-core/test/sdk_test_support/mock_server.py +++ b/thousandeyes-sdk-core/test/sdk_test_support/mock_server.py @@ -50,8 +50,17 @@ def _normalize_json(value: Any) -> Any: def _json_body_matches(expected: Any, actual: Any) -> bool: if isinstance(expected, dict) and isinstance(actual, dict): - filtered_expected = {key: expected[key] for key in actual if key in expected} - return _normalize_json(filtered_expected) == _normalize_json(actual) + for key in actual: + if key not in expected: + return False + if not _json_body_matches(expected[key], actual[key]): + return False + return True + if isinstance(expected, list) and isinstance(actual, list): + if len(expected) != len(actual): + return False + return all(_json_body_matches(expected_item, actual_item) + for expected_item, actual_item in zip(expected, actual)) return _normalize_json(expected) == _normalize_json(actual) diff --git a/thousandeyes-sdk-core/test/test_mock_server.py b/thousandeyes-sdk-core/test/test_mock_server.py index 940c05ba..a34a7580 100644 --- a/thousandeyes-sdk-core/test/test_mock_server.py +++ b/thousandeyes-sdk-core/test/test_mock_server.py @@ -214,3 +214,38 @@ def test_mock_server_accepts_equivalent_iso8601_datetime_formats(manifest): ) assert status == 201 assert json.loads(body.decode("utf-8")) == {"ruleId": "1"} + + +def test_mock_server_ignores_readonly_fields_in_nested_request_objects(manifest): + nested_manifest = { + **manifest, + "createAlertRule": OperationExpectation( + operation_id="createAlertRule", + method="POST", + path="/alerts/rules", + request_body_example={ + "ruleName": "Example", + "widgets": [ + { + "title": "Widget Title", + "id": "read-only-id", + "embedUrl": "https://example.com/embed", + } + ], + }, + success_status=201, + success_body={"ruleId": "1"}, + ), + } + with MockApiServer(nested_manifest) as server: + status, body = _request( + server, + method="POST", + path="/alerts/rules", + body={ + "ruleName": "Example", + "widgets": [{"title": "Widget Title"}], + }, + ) + assert status == 201 + assert json.loads(body.decode("utf-8")) == {"ruleId": "1"} diff --git a/thousandeyes-sdk-dashboards/test/test_dashboards_api_integration.py b/thousandeyes-sdk-dashboards/test/test_dashboards_api_integration.py index 52cd5593..c2ff1ea4 100644 --- a/thousandeyes-sdk-dashboards/test/test_dashboards_api_integration.py +++ b/thousandeyes-sdk-dashboards/test/test_dashboards_api_integration.py @@ -2916,7 +2916,10 @@ class TestDashboardsApiIntegration(IntegrationTestBase): _headers=self.te_headers("get_dashboards"), ) - assert_constructed_model_matches_example_json(response, expected_response) + self.assertIsInstance(response, list) + self.assertEqual(len(response), len(expected_response)) + for index, element in enumerate(response): + assert_constructed_model_matches_example_json(element, expected_response[index]) def test_get_dashboards_error_400(self) -> None: diff --git a/thousandeyes-sdk-streaming/test/test_streaming_api_integration.py b/thousandeyes-sdk-streaming/test/test_streaming_api_integration.py index d196589f..01fff3ef 100644 --- a/thousandeyes-sdk-streaming/test/test_streaming_api_integration.py +++ b/thousandeyes-sdk-streaming/test/test_streaming_api_integration.py @@ -907,7 +907,10 @@ class TestStreamingApiIntegration(IntegrationTestBase): _headers=self.te_headers("get_streams"), ) - assert_constructed_model_matches_example_json(response, expected_response) + self.assertIsInstance(response, list) + self.assertEqual(len(response), len(expected_response)) + for index, element in enumerate(response): + assert_constructed_model_matches_example_json(element, expected_response[index]) def test_get_streams_error_400(self) -> None: