99 lines
4.7 KiB
Erlang
99 lines
4.7 KiB
Erlang
%%%-------------------------------------------------------------------
|
||
%%% @doc Тесты клиентского API для отмены вхождения повторяющегося события.
|
||
%%%
|
||
%%% Покрывает эндпоинты:
|
||
%%% DELETE /v1/events/:id/occurrences/:start_time
|
||
%%%
|
||
%%% Проверяет:
|
||
%%% - успешную отмену конкретного вхождения
|
||
%%% - ошибку 400 для не-recurring события
|
||
%%% - ошибку 403 при попытке отмены чужим пользователем
|
||
%%% - ошибку 401 без токена
|
||
%%% @end
|
||
%%%-------------------------------------------------------------------
|
||
-module(user_occurrence_cancel_tests).
|
||
-include_lib("eunit/include/eunit.hrl").
|
||
|
||
-export([test/0]).
|
||
|
||
%%%===================================================================
|
||
%%% Главная тестовая функция
|
||
%%%===================================================================
|
||
|
||
-spec test() -> ok.
|
||
test() ->
|
||
ct:pal("=== User Occurrence Cancel Tests ==="),
|
||
OwnerToken = api_test_runner:get_user_token(),
|
||
OtherToken = api_test_runner:register_and_login(
|
||
api_test_runner:unique_email(<<"other">>), <<"pass">>),
|
||
|
||
% Создаём календарь и повторяющееся событие
|
||
CalId = api_test_runner:create_calendar(OwnerToken, #{title => <<"OccCancel">>}),
|
||
#{<<"id">> := RecurringId} = api_test_runner:client_post(
|
||
<<"/v1/calendars/", CalId/binary, "/events">>, OwnerToken,
|
||
#{title => <<"Weekly Standup">>,
|
||
start_time => <<"2026-06-01T10:00:00Z">>,
|
||
duration => 30,
|
||
recurrence => #{freq => <<"WEEKLY">>, interval => 1}}),
|
||
|
||
% Получаем вхождения (ответ – список карт)
|
||
OccPath = <<"/v1/events/", RecurringId/binary, "/occurrences?from=2026-06-01T00:00:00Z&to=2026-06-30T00:00:00Z">>,
|
||
Occurrences = api_test_runner:client_get(OccPath, OwnerToken),
|
||
?assert(is_list(Occurrences)),
|
||
?assert(length(Occurrences) >= 1),
|
||
#{<<"start_time">> := FirstStart} = hd(Occurrences),
|
||
|
||
test_cancel_occurrence(OwnerToken, RecurringId, FirstStart),
|
||
test_cancel_occurrence_on_single_event(OwnerToken, CalId),
|
||
test_cancel_occurrence_forbidden(OtherToken, RecurringId, FirstStart),
|
||
test_cancel_occurrence_unauthorized(RecurringId, FirstStart),
|
||
|
||
ct:pal("=== All user occurrence cancel tests passed ==="),
|
||
ok.
|
||
|
||
%%%===================================================================
|
||
%%% Тестовые функции
|
||
%%%===================================================================
|
||
|
||
%% @doc Успешная отмена вхождения: 200 OK.
|
||
-spec test_cancel_occurrence(binary(), binary(), binary()) -> ok.
|
||
test_cancel_occurrence(Token, EventId, StartTime) ->
|
||
ct:pal(" TEST: Cancel occurrence"),
|
||
Path = <<"/v1/events/", EventId/binary, "/occurrences/", StartTime/binary>>,
|
||
Resp = api_test_runner:client_request(delete, Path, Token),
|
||
{ok, 200, _, Body} = Resp,
|
||
#{<<"status">> := Status} = jsx:decode(list_to_binary(Body), [return_maps]),
|
||
?assertEqual(<<"cancelled">>, Status),
|
||
ct:pal(" OK: occurrence cancelled").
|
||
|
||
%% @doc Попытка отменить вхождение для одиночного события: 400.
|
||
-spec test_cancel_occurrence_on_single_event(binary(), binary()) -> ok.
|
||
test_cancel_occurrence_on_single_event(Token, CalId) ->
|
||
ct:pal(" TEST: Cancel occurrence on non-recurring event"),
|
||
#{<<"id">> := SingleId} = api_test_runner:client_post(
|
||
<<"/v1/calendars/", CalId/binary, "/events">>, Token,
|
||
#{title => <<"Single">>,
|
||
start_time => <<"2026-06-02T10:00:00Z">>,
|
||
duration => 30}),
|
||
Path = <<"/v1/events/", SingleId/binary, "/occurrences/2026-06-02T10:00:00Z">>,
|
||
Resp = api_test_runner:client_request(delete, Path, Token),
|
||
?assertMatch({ok, 400, _, _}, Resp),
|
||
ct:pal(" OK: got 400").
|
||
|
||
%% @doc Попытка отмены чужим пользователем: 403.
|
||
-spec test_cancel_occurrence_forbidden(binary(), binary(), binary()) -> ok.
|
||
test_cancel_occurrence_forbidden(OtherToken, EventId, StartTime) ->
|
||
ct:pal(" TEST: Cancel occurrence by non-owner"),
|
||
Path = <<"/v1/events/", EventId/binary, "/occurrences/", StartTime/binary>>,
|
||
Resp = api_test_runner:client_request(delete, Path, OtherToken),
|
||
?assertMatch({ok, 403, _, _}, Resp),
|
||
ct:pal(" OK: got 403").
|
||
|
||
%% @doc Запрос без токена: 401.
|
||
-spec test_cancel_occurrence_unauthorized(binary(), binary()) -> ok.
|
||
test_cancel_occurrence_unauthorized(EventId, StartTime) ->
|
||
ct:pal(" TEST: Cancel occurrence without token"),
|
||
Path = <<"/v1/events/", EventId/binary, "/occurrences/", StartTime/binary>>,
|
||
Resp = api_test_runner:client_request(delete, Path, <<>>),
|
||
?assertMatch({ok, 401, _, _}, Resp),
|
||
ct:pal(" OK: got 401"). |