diff --git a/rebar.lock b/rebar.lock index 5d15125..33c4ee2 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,4 +1,4 @@ [{<<"damsel">>, {git,"https://github.com/valitydev/damsel.git", - {ref,"dac2cb599499cc0701e60856f4092c9ab283eedf"}}, + {ref,"38a420da68166d876153ea9d5e8701f636c11a0e"}}, 0}]. diff --git a/src/payproc_errors.erl b/src/payproc_errors.erl index 43a19e6..d87dc87 100644 --- a/src/payproc_errors.erl +++ b/src/payproc_errors.erl @@ -81,10 +81,10 @@ sub_error_to_static(Type, #domain_SubFailure{code = Code, sub = SDE}) -> to_static(Code, Type, SDE) -> StaticCode = code_to_static(Code), case type_by_field(StaticCode, Type) of - SubType when SubType =/= undefined -> - {StaticCode, sub_error_to_static(SubType, SDE)}; - undefined -> - {{unknown_error, Code}, #payproc_error_GeneralFailure{}} + SubType when SubType =:= undefined orelse SubType =:= unknown_error -> + {{unknown_error, Code}, sub_error_to_static(undefined, SDE)}; + SubType -> + {StaticCode, sub_error_to_static(SubType, SDE)} end. -spec code_to_static(dynamic_code()) -> static_code(). @@ -148,6 +148,10 @@ join(Code, Sub) -> [Code, $:, Sub]. %% -spec type_by_field(static_code(), type()) -> atom() | undefined. +type_by_field(_Code, undefined) -> + undefined; +type_by_field({unknown_error, _DynamicCode}, _Type) -> + unknown_error; type_by_field(Code, Type) -> case [Field || Field = {FCode, _} <- struct_info(Type), Code =:= FCode] of [{_, SubType}] -> SubType; diff --git a/test/payproc_errors_SUITE.erl b/test/payproc_errors_SUITE.erl index 0363305..99790c0 100644 --- a/test/payproc_errors_SUITE.erl +++ b/test/payproc_errors_SUITE.erl @@ -6,8 +6,9 @@ -export([all/0]). -export([known_error_test/1]). --export([unknown_error_test/1]). -export([unknown_error_atom_test/1]). +-export([unknown_error_nested_test/1]). +-export([unknown_error_nested_mixed_test/1]). -export([bad_static_type_test/1]). -export([formatting_test/1]). -export([from_notation_test/1]). @@ -23,8 +24,9 @@ all() -> [ known_error_test, - unknown_error_test, unknown_error_atom_test, + unknown_error_nested_test, + unknown_error_nested_mixed_test, bad_static_type_test, formatting_test, from_notation_test, @@ -62,16 +64,55 @@ unknown_error_atom_test(_C) -> DE = payproc_errors:construct('PaymentFailure', SE), ok = payproc_errors:match('PaymentFailure', DE, fun(E) when SE =:= E -> ok end). --spec unknown_error_test(config()) -> _. -unknown_error_test(_C) -> - UnknownCode = erlang:atom_to_binary(bad_error_code, utf8), +-define(NESTED_UNKNOWN_SUBCODES, + { + {unknown_error, <<"rejected_routes">>}, + {{unknown_error, <<"limit_hold_reject">>}, #payproc_error_GeneralFailure{}} + } +). + +-spec unknown_error_nested_test(config()) -> _. +unknown_error_nested_test(_C) -> + %% NOTE Ensure atoms exist + _ = rejected_routes, + _ = limit_hold_reject, + DE = #domain_Failure{ - code = UnknownCode + code = <<"forbidden">>, + sub = #domain_SubFailure{ + code = <<"rejected_routes">>, + sub = #domain_SubFailure{ + code = <<"limit_hold_reject">> + } + } }, - SE = {{unknown_error, UnknownCode}, #payproc_error_GeneralFailure{}}, + SE = {{unknown_error, <<"forbidden">>}, ?NESTED_UNKNOWN_SUBCODES}, DE = payproc_errors:construct('PaymentFailure', SE), ok = payproc_errors:match('PaymentFailure', DE, fun(E) when SE =:= E -> ok end). +-spec unknown_error_nested_mixed_test(config()) -> _. +unknown_error_nested_mixed_test(_C) -> + %% NOTE Ensure atoms exist + _ = rejected_routes, + _ = limit_hold_reject, + + DE = #domain_Failure{ + code = <<"no_route_found">>, + sub = #domain_SubFailure{ + code = <<"forbidden">>, + sub = #domain_SubFailure{ + code = <<"rejected_routes">>, + sub = #domain_SubFailure{ + code = <<"limit_hold_reject">> + } + } + } + }, + SE = {no_route_found, {{unknown_error, <<"forbidden">>}, ?NESTED_UNKNOWN_SUBCODES}}, + EquivalentSE = {no_route_found, {forbidden, ?NESTED_UNKNOWN_SUBCODES}}, + DE = payproc_errors:construct('PaymentFailure', SE), + ok = payproc_errors:match('PaymentFailure', DE, fun(E) when EquivalentSE =:= E -> ok end). + -spec bad_static_type_test(config()) -> _. bad_static_type_test(_C) -> Bad = {qwe, #payproc_error_GeneralFailure{}}, @@ -87,6 +128,8 @@ bad_static_type_test(_C) -> (catch payproc_errors:construct('RefundFailure', {preauthorization_failed, #payproc_error_GeneralFailure{}})), {'EXIT', {badarg, _}} = (catch payproc_errors:construct('RefundFailure', Bad)), + {'EXIT', {badarg, _}} = + (catch payproc_errors:construct('PaymentFailure', {{unknown_error, <<"forbidden">>}, Bad})), ok. -spec formatting_test(config()) -> _.