fix(ct): adapt API tests to sole Default personal
Default create_calendar to commercial; reuse existing personal on 409; assert verify title Default; cover personal_exists / default_calendar. Refs EventHub/EventHubBack#64
This commit is contained in:
@@ -67,21 +67,16 @@ setup() ->
|
|||||||
Email = api_test_runner:unique_email(<<"caladmin">>),
|
Email = api_test_runner:unique_email(<<"caladmin">>),
|
||||||
Password = <<"testpass">>,
|
Password = <<"testpass">>,
|
||||||
UserToken = api_test_runner:register_and_login(Email, Password),
|
UserToken = api_test_runner:register_and_login(Email, Password),
|
||||||
CalId1 = create_calendar(UserToken, <<"Personal Active">>, <<"Desc1">>),
|
%% Sole personal Default already exists after verify
|
||||||
CalId2 = create_calendar(UserToken, <<"Commercial">>, <<"Desc2">>),
|
CalId1 = api_test_runner:existing_personal_calendar_id(UserToken),
|
||||||
CalId3 = create_calendar(UserToken, <<"Frozen">>, <<"Desc3">>),
|
CalId2 = api_test_runner:create_calendar(UserToken,
|
||||||
update_calendar_admin(AdminToken, CalId2, #{<<"type">> => <<"commercial">>}),
|
#{title => <<"Commercial">>, description => <<"Desc2">>, type => <<"commercial">>}),
|
||||||
|
CalId3 = api_test_runner:create_calendar(UserToken,
|
||||||
|
#{title => <<"Frozen">>, description => <<"Desc3">>, type => <<"commercial">>}),
|
||||||
update_calendar_admin(AdminToken, CalId3, #{<<"status">> => <<"frozen">>}),
|
update_calendar_admin(AdminToken, CalId3, #{<<"status">> => <<"frozen">>}),
|
||||||
ct:pal(" Created calendars: ~p", [[CalId1, CalId2, CalId3]]),
|
ct:pal(" Created calendars: ~p", [[CalId1, CalId2, CalId3]]),
|
||||||
{AdminToken, UserToken, [CalId1, CalId2, CalId3]}.
|
{AdminToken, UserToken, [CalId1, CalId2, CalId3]}.
|
||||||
|
|
||||||
-spec create_calendar(binary(), binary(), binary()) -> binary().
|
|
||||||
create_calendar(UserToken, Title, Description) ->
|
|
||||||
Body = jsx:encode(#{title => Title, description => Description}),
|
|
||||||
{ok, 201, _, Resp} = api_test_runner:client_request(post, <<"/v1/calendars">>, UserToken, Body),
|
|
||||||
#{<<"id">> := Id} = jsx:decode(list_to_binary(Resp), [return_maps]),
|
|
||||||
Id.
|
|
||||||
|
|
||||||
-spec update_calendar_admin(binary(), binary(), map()) -> ok.
|
-spec update_calendar_admin(binary(), binary(), map()) -> ok.
|
||||||
update_calendar_admin(AdminToken, CalId, Updates) ->
|
update_calendar_admin(AdminToken, CalId, Updates) ->
|
||||||
{ok, 200, _, RespBody} = api_test_runner:admin_request(get, <<"/v1/admin/calendars/", CalId/binary>>, AdminToken, <<"">>),
|
{ok, 200, _, RespBody} = api_test_runner:admin_request(get, <<"/v1/admin/calendars/", CalId/binary>>, AdminToken, <<"">>),
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
future_date/0,
|
future_date/0,
|
||||||
register_and_login/2,
|
register_and_login/2,
|
||||||
create_calendar/2,
|
create_calendar/2,
|
||||||
create_event/3
|
create_event/3,
|
||||||
|
ensure_commercial_subscription/1,
|
||||||
|
existing_personal_calendar_id/1
|
||||||
, get_admin_refresh_token/0
|
, get_admin_refresh_token/0
|
||||||
, admin_super_email/0
|
, admin_super_email/0
|
||||||
, admin_super_password/0]).
|
, admin_super_password/0]).
|
||||||
@@ -409,14 +411,39 @@ register_and_login(Email, Password) ->
|
|||||||
|
|
||||||
-spec create_calendar(binary(), map()) -> binary().
|
-spec create_calendar(binary(), map()) -> binary().
|
||||||
create_calendar(Token, Params) ->
|
create_calendar(Token, Params) ->
|
||||||
Type = maps:get(type, Params, maps:get(<<"type">>, Params, <<"personal">>)),
|
%% Default commercial: user already has sole personal Default after verify.
|
||||||
|
Type = maps:get(type, Params, maps:get(<<"type">>, Params, <<"commercial">>)),
|
||||||
|
Params1 =
|
||||||
|
case maps:is_key(type, Params) orelse maps:is_key(<<"type">>, Params) of
|
||||||
|
true -> Params;
|
||||||
|
false -> Params#{type => Type}
|
||||||
|
end,
|
||||||
case Type of
|
case Type of
|
||||||
<<"commercial">> -> ensure_commercial_subscription(Token);
|
<<"commercial">> -> ensure_commercial_subscription(Token);
|
||||||
commercial -> ensure_commercial_subscription(Token);
|
commercial -> ensure_commercial_subscription(Token);
|
||||||
_ -> ok
|
<<"personal">> -> ok;
|
||||||
|
personal -> ok;
|
||||||
|
_ -> ensure_commercial_subscription(Token)
|
||||||
end,
|
end,
|
||||||
#{<<"id">> := CalId} = client_post(<<"/v1/calendars">>, Token, Params),
|
Body = jsx:encode(Params1),
|
||||||
CalId.
|
case client_request(post, <<"/v1/calendars">>, Token, Body) of
|
||||||
|
{ok, 201, _, RespBody} ->
|
||||||
|
#{<<"id">> := CalId} = jsx:decode(list_to_binary(RespBody), [return_maps]),
|
||||||
|
CalId;
|
||||||
|
{ok, 409, _, _} when Type =:= <<"personal">>; Type =:= personal ->
|
||||||
|
%% Sole Default personal already exists — reuse it.
|
||||||
|
existing_personal_calendar_id(Token);
|
||||||
|
Other ->
|
||||||
|
error({create_calendar_failed, Other})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec existing_personal_calendar_id(binary()) -> binary().
|
||||||
|
existing_personal_calendar_id(Token) ->
|
||||||
|
Cals = client_get(<<"/v1/calendars">>, Token),
|
||||||
|
case [Id || #{<<"id">> := Id, <<"type">> := <<"personal">>} <- Cals] of
|
||||||
|
[Id | _] -> Id;
|
||||||
|
[] -> error(no_personal_calendar)
|
||||||
|
end.
|
||||||
|
|
||||||
-spec ensure_commercial_subscription(binary()) -> ok.
|
-spec ensure_commercial_subscription(binary()) -> ok.
|
||||||
ensure_commercial_subscription(Token) ->
|
ensure_commercial_subscription(Token) ->
|
||||||
|
|||||||
@@ -15,9 +15,8 @@ test() ->
|
|||||||
OtherToken = api_test_runner:register_and_login(
|
OtherToken = api_test_runner:register_and_login(
|
||||||
api_test_runner:unique_email(<<"other">>), <<"pass">>),
|
api_test_runner:unique_email(<<"other">>), <<"pass">>),
|
||||||
|
|
||||||
% Создаём календарь для тестов
|
%% Studio calendar (sole personal Default cannot be deleted)
|
||||||
#{<<"id">> := CalId} = api_test_runner:client_post(<<"/v1/calendars">>, Token,
|
CalId = api_test_runner:create_calendar(Token, #{title => <<"TestCal">>}),
|
||||||
#{title => <<"TestCal">>, type => <<"personal">>}),
|
|
||||||
|
|
||||||
test_get_calendar(Token, CalId),
|
test_get_calendar(Token, CalId),
|
||||||
test_get_calendar_unauthorized(CalId),
|
test_get_calendar_unauthorized(CalId),
|
||||||
@@ -26,6 +25,7 @@ test() ->
|
|||||||
test_update_calendar_settings(Token, CalId),
|
test_update_calendar_settings(Token, CalId),
|
||||||
test_update_calendar_forbidden(OtherToken, CalId),
|
test_update_calendar_forbidden(OtherToken, CalId),
|
||||||
test_delete_calendar(Token, CalId),
|
test_delete_calendar(Token, CalId),
|
||||||
|
test_delete_default_personal_forbidden(Token),
|
||||||
test_delete_calendar_forbidden(OtherToken, CalId),
|
test_delete_calendar_forbidden(OtherToken, CalId),
|
||||||
|
|
||||||
ct:pal("=== All user calendar by id tests passed ==="),
|
ct:pal("=== All user calendar by id tests passed ==="),
|
||||||
@@ -104,18 +104,24 @@ test_update_calendar_forbidden(OtherToken, CalId) ->
|
|||||||
ct:pal(" OK: got 403").
|
ct:pal(" OK: got 403").
|
||||||
|
|
||||||
test_delete_calendar(Token, CalId) ->
|
test_delete_calendar(Token, CalId) ->
|
||||||
ct:pal(" TEST: Delete calendar (soft-delete)"),
|
ct:pal(" TEST: Delete studio calendar (soft-delete)"),
|
||||||
Path = <<"/v1/calendars/", CalId/binary>>,
|
Path = <<"/v1/calendars/", CalId/binary>>,
|
||||||
Resp = api_test_runner:client_request(delete, Path, Token),
|
Resp = api_test_runner:client_request(delete, Path, Token),
|
||||||
?assertMatch({ok, 200, _, _}, Resp),
|
?assertMatch({ok, 200, _, _}, Resp),
|
||||||
ct:pal(" OK: deleted").
|
ct:pal(" OK: deleted").
|
||||||
|
|
||||||
test_delete_calendar_forbidden(OtherToken, CalId) ->
|
test_delete_default_personal_forbidden(Token) ->
|
||||||
% Первый раз мы уже удалили, но проверим на другом календаре
|
ct:pal(" TEST: Delete sole personal calendar (403 default_calendar)"),
|
||||||
|
PersonalId = api_test_runner:existing_personal_calendar_id(Token),
|
||||||
|
Path = <<"/v1/calendars/", PersonalId/binary>>,
|
||||||
|
Resp = api_test_runner:client_request(delete, Path, Token),
|
||||||
|
?assertMatch({ok, 403, _, _}, Resp),
|
||||||
|
ct:pal(" OK: got 403 default_calendar").
|
||||||
|
|
||||||
|
test_delete_calendar_forbidden(OtherToken, _DeletedCalId) ->
|
||||||
ct:pal(" TEST: Delete calendar by non-owner (403)"),
|
ct:pal(" TEST: Delete calendar by non-owner (403)"),
|
||||||
% Создадим новый календарь владельцем Token, попробуем удалить OtherToken
|
OwnerToken = api_test_runner:get_user_token(),
|
||||||
#{<<"id">> := NewCalId} = api_test_runner:client_post(<<"/v1/calendars">>, api_test_runner:get_user_token(),
|
NewCalId = api_test_runner:create_calendar(OwnerToken, #{title => <<"ForbiddenDel">>}),
|
||||||
#{title => <<"ForbiddenDel">>, type => <<"personal">>}),
|
|
||||||
Path = <<"/v1/calendars/", NewCalId/binary>>,
|
Path = <<"/v1/calendars/", NewCalId/binary>>,
|
||||||
Resp = api_test_runner:client_request(delete, Path, OtherToken),
|
Resp = api_test_runner:client_request(delete, Path, OtherToken),
|
||||||
?assertMatch({ok, 403, _, _}, Resp),
|
?assertMatch({ok, 403, _, _}, Resp),
|
||||||
|
|||||||
@@ -13,11 +13,10 @@ test() ->
|
|||||||
ct:pal("=== User Calendars Tests ==="),
|
ct:pal("=== User Calendars Tests ==="),
|
||||||
Token = api_test_runner:get_user_token(),
|
Token = api_test_runner:get_user_token(),
|
||||||
|
|
||||||
% Создаём один календарь для тестов
|
_CalId = api_test_runner:create_calendar(Token, #{title => <<"TestCal">>}),
|
||||||
#{<<"id">> := CalId} = api_test_runner:client_post(<<"/v1/calendars">>, Token,
|
|
||||||
#{title => <<"TestCal">>, type => <<"personal">>}),
|
|
||||||
|
|
||||||
test_create_calendar(Token),
|
test_create_calendar(Token),
|
||||||
|
test_second_personal_rejected(Token),
|
||||||
test_list_calendars(Token),
|
test_list_calendars(Token),
|
||||||
test_list_calendars_unauthorized(),
|
test_list_calendars_unauthorized(),
|
||||||
|
|
||||||
@@ -25,15 +24,23 @@ test() ->
|
|||||||
ok.
|
ok.
|
||||||
|
|
||||||
test_create_calendar(Token) ->
|
test_create_calendar(Token) ->
|
||||||
ct:pal(" TEST: Create a new calendar"),
|
ct:pal(" TEST: Create a new studio calendar"),
|
||||||
|
api_test_runner:ensure_commercial_subscription(Token),
|
||||||
Resp = api_test_runner:client_request(post, <<"/v1/calendars">>, Token,
|
Resp = api_test_runner:client_request(post, <<"/v1/calendars">>, Token,
|
||||||
jsx:encode(#{title => <<"NewCal">>, type => <<"personal">>})),
|
jsx:encode(#{title => <<"NewCal">>, type => <<"commercial">>})),
|
||||||
{ok, 201, _, Body} = Resp,
|
{ok, 201, _, Body} = Resp,
|
||||||
#{<<"id">> := Id, <<"title">> := Title} = jsx:decode(list_to_binary(Body), [return_maps]),
|
#{<<"id">> := Id, <<"title">> := Title} = jsx:decode(list_to_binary(Body), [return_maps]),
|
||||||
?assert(is_binary(Id)),
|
?assert(is_binary(Id)),
|
||||||
?assertEqual(<<"NewCal">>, Title),
|
?assertEqual(<<"NewCal">>, Title),
|
||||||
ct:pal(" OK: created calendar ~s", [Id]).
|
ct:pal(" OK: created calendar ~s", [Id]).
|
||||||
|
|
||||||
|
test_second_personal_rejected(Token) ->
|
||||||
|
ct:pal(" TEST: Second personal calendar rejected (409)"),
|
||||||
|
Resp = api_test_runner:client_request(post, <<"/v1/calendars">>, Token,
|
||||||
|
jsx:encode(#{title => <<"AnotherPersonal">>, type => <<"personal">>})),
|
||||||
|
?assertMatch({ok, 409, _, _}, Resp),
|
||||||
|
ct:pal(" OK: got 409 personal_exists").
|
||||||
|
|
||||||
test_list_calendars(Token) ->
|
test_list_calendars(Token) ->
|
||||||
ct:pal(" TEST: List user calendars"),
|
ct:pal(" TEST: List user calendars"),
|
||||||
Calendars = api_test_runner:client_get(<<"/v1/calendars">>, Token),
|
Calendars = api_test_runner:client_get(<<"/v1/calendars">>, Token),
|
||||||
|
|||||||
@@ -47,17 +47,13 @@ test() ->
|
|||||||
#{<<"token">> := AuthToken} = jsx:decode(list_to_binary(LoginBody), [return_maps]),
|
#{<<"token">> := AuthToken} = jsx:decode(list_to_binary(LoginBody), [return_maps]),
|
||||||
?assert(is_binary(AuthToken)),
|
?assert(is_binary(AuthToken)),
|
||||||
|
|
||||||
% 6. После активации — дефолтный приватный personal-календарь
|
% 6. После активации — единственный personal с title Default
|
||||||
Calendars = api_test_runner:client_get(<<"/v1/calendars">>, AuthToken),
|
Calendars = api_test_runner:client_get(<<"/v1/calendars">>, AuthToken),
|
||||||
?assertEqual(1, length(Calendars)),
|
?assertEqual(1, length(Calendars)),
|
||||||
[DefaultCal] = Calendars,
|
[DefaultCal] = Calendars,
|
||||||
?assertEqual(<<"personal">>, maps:get(<<"type">>, DefaultCal)),
|
?assertEqual(<<"personal">>, maps:get(<<"type">>, DefaultCal)),
|
||||||
?assertEqual(<<>>, maps:get(<<"short_name">>, DefaultCal)),
|
?assertEqual(<<>>, maps:get(<<"short_name">>, DefaultCal)),
|
||||||
ExpectedTitle = case string:split(Email, <<"@">>) of
|
?assertEqual(<<"Default">>, maps:get(<<"title">>, DefaultCal)),
|
||||||
[Local, _] when byte_size(Local) > 0 -> Local;
|
|
||||||
_ -> <<"Мой календарь">>
|
|
||||||
end,
|
|
||||||
?assertEqual(ExpectedTitle, maps:get(<<"title">>, DefaultCal)),
|
|
||||||
|
|
||||||
% 7. Повторное использование того же токена – ошибка 404
|
% 7. Повторное использование того же токена – ошибка 404
|
||||||
{ok, 404, _, _} = api_test_runner:client_request(post, <<"/v1/verify">>, <<>>,
|
{ok, 404, _, _} = api_test_runner:client_request(post, <<"/v1/verify">>, <<>>,
|
||||||
|
|||||||
Reference in New Issue
Block a user