%%%------------------------------------------------------------------- %%% @doc Тесты клиентского API для регистрации пользователей. %%% %%% Покрывает эндпоинты: %%% POST /v1/register %%% %%% Проверяет: %%% - успешную регистрацию нового пользователя (статус pending) %%% - ошибку при повторной регистрации с тем же email %%% - ошибку при отсутствии обязательных полей %%% - что логин до подтверждения возвращает 403 %%% @end %%%------------------------------------------------------------------- -module(user_register_tests). -include_lib("eunit/include/eunit.hrl"). -export([test/0]). %%%=================================================================== %%% Главная тестовая функция %%%=================================================================== -spec test() -> ok. test() -> ct:pal("=== Client Register Tests ==="), Email = api_test_runner:unique_email(<<"register">>), Password = <<"StrongPass1!">>, test_successful_register(Email, Password), test_duplicate_register(Email, Password), test_missing_fields(), test_login_before_verification(Email, Password), ct:pal("=== All client register tests passed ==="), ok. %%%=================================================================== %%% Тестовые функции %%%=================================================================== %% @doc Успешная регистрация: 201 Created, возвращает пользователя со статусом pending. -spec test_successful_register(binary(), binary()) -> ok. test_successful_register(Email, Password) -> ct:pal(" TEST: Successful registration"), Resp = api_test_runner:client_request(post, <<"/v1/register">>, <<>>, jsx:encode(#{email => Email, password => Password})), {ok, 201, _, Body} = Resp, #{<<"user">> := User} = jsx:decode(list_to_binary(Body), [return_maps]), ?assert(maps:is_key(<<"id">>, User)), ?assertEqual(Email, maps:get(<<"email">>, User)), ?assertEqual(<<"pending">>, maps:get(<<"status">>, User)), ct:pal(" OK: user ~s created with status pending", [maps:get(<<"id">>, User)]). %% @doc Повторная регистрация с тем же email: 409 Conflict. -spec test_duplicate_register(binary(), binary()) -> ok. test_duplicate_register(Email, Password) -> ct:pal(" TEST: Duplicate registration"), Resp = api_test_runner:client_request(post, <<"/v1/register">>, <<>>, jsx:encode(#{email => Email, password => Password})), {ok, 409, _, Body} = Resp, #{<<"error">> := ErrorMsg} = jsx:decode(list_to_binary(Body), [return_maps]), ?assertEqual(<<"Email already exists">>, ErrorMsg), ct:pal(" OK: got 409 conflict"). %% @doc Отсутствие обязательных полей: 400 Bad Request. -spec test_missing_fields() -> ok. test_missing_fields() -> ct:pal(" TEST: Missing required fields"), Resp1 = api_test_runner:client_request(post, <<"/v1/register">>, <<>>, jsx:encode(#{email => <<"missing@test.local">>})), ?assertMatch({ok, 400, _, _}, Resp1), Resp2 = api_test_runner:client_request(post, <<"/v1/register">>, <<>>, jsx:encode(#{password => <<"NoEmail1">>})), ?assertMatch({ok, 400, _, _}, Resp2), ct:pal(" OK: 400 on missing fields"). %% @doc Попытка входа до подтверждения email: 403 Forbidden. -spec test_login_before_verification(binary(), binary()) -> ok. test_login_before_verification(Email, Password) -> ct:pal(" TEST: Login before email verification (403)"), Resp = api_test_runner:client_request(post, <<"/v1/login">>, <<>>, jsx:encode(#{email => Email, password => Password})), {ok, 403, _, Body} = Resp, #{<<"error">> := ErrorMsg} = jsx:decode(list_to_binary(Body), [return_maps]), ?assertEqual(<<"Account not verified">>, ErrorMsg), ct:pal(" OK: got 403").