-module(validator_test). -compile(no_auto_import). -export([invalid_test/0, valid_test/0, error_type_test/0, custom_test/0, and_test/0, and_with_transformation_test/0, all_test/0, compose_and_all_test/0, whole_test/0, int_min_test/0, int_max_test/0, list_is_not_empty_test/0, list_min_length_test/0, list_max_length_test/0, list_all_test/0, option_is_some_test/0, option_optional_test/0, string_not_empty_test/0, string_is_int_test/0, string_is_float_test/0, string_is_email_test/0, string_min_length_test/0, string_max_length_test/0]). user_validator(User) -> validator:keep( validator:validate( validator:validate( validator:build3(fun(A, B, C) -> {valid_user, A, B, C} end), erlang:element(2, User), validator@option:is_some(<<"Please provide a name"/utf8>>) ), erlang:element(3, User), validator@option:is_some(<<"Please provide an email"/utf8>>) ), erlang:element(4, User) ). invalid_test() -> Invalid = {input_user, none, none, 0}, Expected = {error, {<<"Please provide a name"/utf8>>, [<<"Please provide a name"/utf8>>, <<"Please provide an email"/utf8>>]}}, gleam@should:equal(user_validator(Invalid), Expected). valid_test() -> ValidInput = {input_user, {some, <<"Sam"/utf8>>}, {some, <<"sam@sample.com"/utf8>>}, 11}, Valid = {valid_user, <<"Sam"/utf8>>, <<"sam@sample.com"/utf8>>, 11}, gleam@should:equal(user_validator(ValidInput), {ok, Valid}). error_type_test() -> Validator = fun(Thing) -> validator:validate( validator:build1(fun(A) -> {thing, A} end), erlang:element(2, Thing), validator@string:is_not_empty(error_empty) ) end, Thing@1 = {thing, <<""/utf8>>}, Expected = {error, {error_empty, [error_empty]}}, gleam@should:equal(Validator(Thing@1), Expected). custom_test() -> MustBeOne = fun(Name) -> case Name =:= <<"One"/utf8>> of true -> {some, Name}; false -> none end end, Custom = validator:custom(<<"Must be One"/utf8>>, MustBeOne), Validator = fun(Thing) -> validator:validate( validator:build1(fun(A) -> {thing, A} end), erlang:element(2, Thing), Custom ) end, ThingOne = {thing, <<"One"/utf8>>}, gleam@should:equal(Validator(ThingOne), {ok, {thing, <<"One"/utf8>>}}), ThingTwo = {thing, <<"Two"/utf8>>}, ExpectedError = {error, {<<"Must be One"/utf8>>, [<<"Must be One"/utf8>>]}}, gleam@should:equal(Validator(ThingTwo), ExpectedError). and_test() -> NameValidator = validator:'and'( validator:'and'( validator@string:is_not_empty(<<"Empty"/utf8>>), validator@string:min_length(<<"More"/utf8>>, 6) ), validator@string:max_length(<<"Less"/utf8>>, 2) ), Validator = fun(Thing) -> validator:validate( validator:build1(fun(A) -> {thing, A} end), erlang:element(2, Thing), NameValidator ) end, Thing@1 = {thing, <<"One"/utf8>>}, ExpectedError = {error, {<<"More"/utf8>>, [<<"More"/utf8>>]}}, gleam@should:equal(Validator(Thing@1), ExpectedError). and_with_transformation_test() -> NameValidator = validator:'and'( validator:'and'( validator:'and'( validator@option:is_some(<<"Is null"/utf8>>), validator@string:is_not_empty(<<"Empty"/utf8>>) ), validator@string:min_length(<<"More"/utf8>>, 3) ), validator@string:max_length(<<"Less"/utf8>>, 8) ), Validator = fun(Thing) -> validator:validate( validator:build1(fun(A) -> {thing, A} end), erlang:element(2, Thing), NameValidator ) end, Thing@1 = {input_thing, {some, <<"One Thing"/utf8>>}}, ExpectedError = {error, {<<"Less"/utf8>>, [<<"Less"/utf8>>]}}, gleam@should:equal(Validator(Thing@1), ExpectedError). all_test() -> NameValidator = validator:all( [validator@string:is_not_empty(<<"Empty"/utf8>>), validator@string:min_length(<<">=3"/utf8>>, 3), validator@string:min_length(<<">=4"/utf8>>, 4), validator@string:min_length(<<">=5"/utf8>>, 5), validator@string:max_length(<<"<=10"/utf8>>, 10)] ), Validator = fun(Thing) -> validator:validate( validator:build1(fun(A) -> {thing, A} end), erlang:element(2, Thing), NameValidator ) end, Thing@1 = {thing, <<"1"/utf8>>}, ExpectedError = {error, {<<">=3"/utf8>>, [<<">=3"/utf8>>, <<">=4"/utf8>>, <<">=5"/utf8>>]}}, gleam@should:equal(Validator(Thing@1), ExpectedError). compose_and_all_test() -> NameValidator = validator:'and'( validator@option:is_some(<<"Is null"/utf8>>), validator:all( [validator@string:is_not_empty(<<"Empty"/utf8>>), validator@string:min_length(<<">=3"/utf8>>, 3), validator@string:max_length(<<"<=10"/utf8>>, 10)] ) ), Validator = fun(Thing) -> validator:validate( validator:build1(fun(A) -> {thing, A} end), erlang:element(2, Thing), NameValidator ) end, Thing@1 = {input_thing, {some, <<"One Thing after the other"/utf8>>}}, ExpectedError = {error, {<<"<=10"/utf8>>, [<<"<=10"/utf8>>]}}, gleam@should:equal(Validator(Thing@1), ExpectedError). whole_test() -> Error = <<"Strength cannot be less than level"/utf8>>, WholeValidator = fun(C) -> case erlang:element(2, C) > erlang:element(3, C) of true -> {error, Error}; false -> {ok, C} end end, Validator = fun(C@1) -> (validator:whole(WholeValidator))( validator:validate( validator:validate( validator:build2(fun(A, B) -> {character, A, B} end), erlang:element(2, C@1), validator@int:min( <<"Level must be more that zero"/utf8>>, 1 ) ), erlang:element(3, C@1), validator@int:min(<<"Strength must be more that zero"/utf8>>, 1) ) ) end, Char = {character, 1, 1}, gleam@should:equal(Validator(Char), {ok, Char}), Char2 = {character, 2, 1}, gleam@should:equal(Validator(Char2), {error, {Error, [Error]}}). int_min_test() -> Validator = validator@int:min(<<">=5"/utf8>>, 5), gleam@should:equal(Validator(5), {ok, 5}), ExpectedError = {error, {<<">=5"/utf8>>, [<<">=5"/utf8>>]}}, gleam@should:equal(Validator(4), ExpectedError). int_max_test() -> Validator = validator@int:max(<<"<=5"/utf8>>, 5), gleam@should:equal(Validator(5), {ok, 5}), ExpectedError = {error, {<<"<=5"/utf8>>, [<<"<=5"/utf8>>]}}, gleam@should:equal(Validator(6), ExpectedError). list_is_not_empty_test() -> Validator = validator@list:is_not_empty(<<"Empty"/utf8>>), gleam@should:equal(Validator([1]), {ok, [1]}), ExpectedError = {error, {<<"Empty"/utf8>>, [<<"Empty"/utf8>>]}}, gleam@should:equal(Validator([]), ExpectedError). list_min_length_test() -> Validator = validator@list:min_length(<<"Short"/utf8>>, 3), gleam@should:equal(Validator([1, 2, 3]), {ok, [1, 2, 3]}), ExpectedError = {error, {<<"Short"/utf8>>, [<<"Short"/utf8>>]}}, gleam@should:equal(Validator([1, 2]), ExpectedError). list_max_length_test() -> Validator = validator@list:max_length(<<"Long"/utf8>>, 4), gleam@should:equal(Validator([1, 2, 3]), {ok, [1, 2, 3]}), ExpectedError = {error, {<<"Long"/utf8>>, [<<"Long"/utf8>>]}}, gleam@should:equal(Validator([1, 2, 3, 4, 5]), ExpectedError). list_all_test() -> ListValidator = validator@list:every( validator@string:min_length(<<"Short"/utf8>>, 3) ), Validator = fun(Thing) -> validator:validate( validator:build1(fun(A) -> {thing_with_list, A} end), erlang:element(2, Thing), ListValidator ) end, Thing@1 = {thing_with_list, [<<"One"/utf8>>, <<"Two"/utf8>>]}, gleam@should:equal(Validator(Thing@1), {ok, Thing@1}), Thing2 = {thing_with_list, [<<"One"/utf8>>, <<"T"/utf8>>, <<"A"/utf8>>]}, ExpectedError = {error, {<<"Short"/utf8>>, [<<"Short"/utf8>>, <<"Short"/utf8>>]}}, gleam@should:equal(Validator(Thing2), ExpectedError). option_is_some_test() -> Validator = validator@option:is_some(<<"Null"/utf8>>), gleam@should:equal( Validator({some, <<"Hola"/utf8>>}), {ok, <<"Hola"/utf8>>} ), ExpectedError = {error, {<<"Null"/utf8>>, [<<"Null"/utf8>>]}}, gleam@should:equal(Validator(none), ExpectedError). option_optional_test() -> Validator = validator@option:optional( validator@string:min_length(<<"Short"/utf8>>, 3) ), gleam@should:equal(Validator(none), {ok, none}), gleam@should:equal( Validator({some, <<"abc"/utf8>>}), {ok, {some, <<"abc"/utf8>>}} ), ExpectedError = {error, {<<"Short"/utf8>>, [<<"Short"/utf8>>]}}, gleam@should:equal(Validator({some, <<"a"/utf8>>}), ExpectedError). string_not_empty_test() -> Validator = validator@string:is_not_empty(<<"Empty"/utf8>>), gleam@should:equal(Validator(<<"One"/utf8>>), {ok, <<"One"/utf8>>}), ExpectedError = {error, {<<"Empty"/utf8>>, [<<"Empty"/utf8>>]}}, gleam@should:equal(Validator(<<""/utf8>>), ExpectedError). string_is_int_test() -> Validator = validator@string:is_int(<<"NaN"/utf8>>), gleam@should:equal(Validator(<<"1"/utf8>>), {ok, 1}), ExpectedError = {error, {<<"NaN"/utf8>>, [<<"NaN"/utf8>>]}}, gleam@should:equal(Validator(<<"A"/utf8>>), ExpectedError). string_is_float_test() -> Validator = validator@string:is_float(<<"NaN"/utf8>>), gleam@should:equal(Validator(<<"1.1"/utf8>>), {ok, 1.1}), ExpectedError = {error, {<<"NaN"/utf8>>, [<<"NaN"/utf8>>]}}, gleam@should:equal(Validator(<<"A"/utf8>>), ExpectedError). string_is_email_test() -> Validator = validator@string:is_email(<<"Not email"/utf8>>), gleam@list:map( [<<"a@b"/utf8>>, <<"a1@b"/utf8>>, <<"a1@b.com"/utf8>>, <<"a1@b.com.au"/utf8>>], fun(Email) -> gleam@should:equal(Validator(Email), {ok, Email}) end ), ExpectedError = {error, {<<"Not email"/utf8>>, [<<"Not email"/utf8>>]}}, gleam@list:map( [<<""/utf8>>, <<"a"/utf8>>, <<"a@"/utf8>>, <<"@b"/utf8>>], fun(Email@1) -> gleam@should:equal(Validator(Email@1), ExpectedError) end ). string_min_length_test() -> Validator = validator@string:min_length(<<"Less than 3"/utf8>>, 3), gleam@should:equal(Validator(<<"One"/utf8>>), {ok, <<"One"/utf8>>}), ExpectedError = {error, {<<"Less than 3"/utf8>>, [<<"Less than 3"/utf8>>]}}, gleam@should:equal(Validator(<<"Tw"/utf8>>), ExpectedError). string_max_length_test() -> Validator = validator@string:max_length(<<"More than 5"/utf8>>, 5), gleam@should:equal(Validator(<<"Hello"/utf8>>), {ok, <<"Hello"/utf8>>}), ExpectedError = {error, {<<"More than 5"/utf8>>, [<<"More than 5"/utf8>>]}}, gleam@should:equal(Validator(<<"More than five"/utf8>>), ExpectedError).