diff --git a/changelog.d/+ignore_new_keys_in_tests.infrastructure.md b/changelog.d/+ignore_new_keys_in_tests.infrastructure.md new file mode 100644 index 00000000..90e3cc85 --- /dev/null +++ b/changelog.d/+ignore_new_keys_in_tests.infrastructure.md @@ -0,0 +1 @@ +Fix event notification tests when introducing new keys in API outputs. \ No newline at end of file diff --git a/test/helpers.py b/test/helpers.py index ba9c6e53..1b6a48a0 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -32,3 +32,22 @@ def b2_uri_args_v4(bucket_name, path=_MISSING): if path is _MISSING: path = '' return [f'b2://{bucket_name}/{path}'] + + +def deep_cast_dict(actual, expected): + """ + For composite objects `actual` and `expected`, return a copy of `actual` (with all dicts and lists deeply copied) + with all keys of dicts not appearing in `expected` (comparing dicts on any level) removed. Useful for assertions + in tests ignoring extra keys. + """ + if isinstance(expected, dict) and isinstance(actual, dict): + return {k: deep_cast_dict(actual[k], expected[k]) for k in expected if k in actual} + + elif isinstance(expected, list) and isinstance(actual, list): + return [deep_cast_dict(a, e) for a, e in zip(actual, expected)] + + return actual + + +def assert_dict_equal_ignore_extra(actual, expected): + assert deep_cast_dict(actual, expected) == expected diff --git a/test/integration/test_b2_command_line.py b/test/integration/test_b2_command_line.py index 51812d4f..dac9aec8 100755 --- a/test/integration/test_b2_command_line.py +++ b/test/integration/test_b2_command_line.py @@ -46,7 +46,7 @@ ) from b2._internal.console_tool import current_time_millis -from ..helpers import skip_on_windows +from ..helpers import assert_dict_equal_ignore_extra, skip_on_windows from .helpers import ( ONE_DAY_MILLIS, ONE_HOUR_MILLIS, @@ -3465,7 +3465,7 @@ def test_notification_rules(b2_tool, bucket_name): expected_stderr_pattern=private_preview_pattern ) expected_rules = [{**notification_rule, "isSuspended": False, "suspensionReason": ""}] - assert created_rule == expected_rules[0] + assert_dict_equal_ignore_extra(created_rule, expected_rules[0]) # modify rule secret = "0testSecret000000000000000000032" @@ -3485,13 +3485,16 @@ def test_notification_rules(b2_tool, bucket_name): ) expected_rules[0].update({"objectNamePrefix": "prefix", "isEnabled": False}) expected_rules[0]["targetConfiguration"]["hmacSha256SigningSecret"] = secret - assert modified_rule == expected_rules[0] + assert_dict_equal_ignore_extra(modified_rule, expected_rules[0]) # read updated rules - assert b2_tool.should_succeed_json( - ["bucket", "notification-rule", "list", f"b2://{bucket_name}", "--json"], - expected_stderr_pattern=private_preview_pattern - ) == expected_rules + modified_rule( + b2_tool.should_succeed_json( + ["bucket", "notification-rule", "list", f"b2://{bucket_name}", "--json"], + expected_stderr_pattern=private_preview_pattern + ), + expected_rules, + ) # delete rule by name assert b2_tool.should_succeed(