%%%------------------------------------------------------------------- %%% @doc Тесты клиентского API для работы с конкретным событием. %%% %%% Покрывает эндпоинты: %%% GET /v1/events/:id %%% PUT /v1/events/:id %%% DELETE /v1/events/:id %%% %%% Проверяет: %%% - получение события по ID %%% - обновление события (владельцем) %%% - мягкое удаление события (статус становится deleted) %%% - ошибку 403 при попытке изменения чужого события %%% - ошибку 404 для несуществующего события %%% - ошибку 401 без токена %%% @end %%%------------------------------------------------------------------- -module(user_event_by_id_tests). -include_lib("eunit/include/eunit.hrl"). -export([test/0]). %%%=================================================================== %%% Главная тестовая функция %%%=================================================================== -spec test() -> ok. test() -> ct:pal("=== User Event By ID Tests ==="), Token = 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(Token, #{title => <<"EvtById">>}), #{<<"id">> := EventId} = api_test_runner:client_post( <<"/v1/calendars/", CalId/binary, "/events">>, Token, #{title => <<"Test Event">>, start_time => <<"2026-06-01T10:00:00Z">>, duration => 60}), test_get_event(Token, EventId), test_update_event(Token, EventId), test_update_event_forbidden(OtherToken, EventId), test_delete_event(Token, EventId), test_get_event_not_found(Token), test_get_event_unauthorized(EventId), ct:pal("=== All user event by id tests passed ==="), ok. %%%=================================================================== %%% Тестовые функции %%%=================================================================== %% @doc GET /v1/events/:id – получение события. -spec test_get_event(binary(), binary()) -> ok. test_get_event(Token, EventId) -> ct:pal(" TEST: Get event by ID"), Path = <<"/v1/events/", EventId/binary>>, Event = api_test_runner:client_get(Path, Token), ?assertEqual(EventId, maps:get(<<"id">>, Event)), ?assertEqual(<<"Test Event">>, maps:get(<<"title">>, Event)), ct:pal(" OK: got event ~s", [EventId]). %% @doc PUT /v1/events/:id – обновление события. -spec test_update_event(binary(), binary()) -> ok. test_update_event(Token, EventId) -> ct:pal(" TEST: Update event"), Path = <<"/v1/events/", EventId/binary>>, Updated = api_test_runner:client_put(Path, Token, #{title => <<"Updated Event">>, description => <<"New desc">>}), ?assertEqual(<<"Updated Event">>, maps:get(<<"title">>, Updated)), ?assertEqual(<<"New desc">>, maps:get(<<"description">>, Updated)), ct:pal(" OK"). %% @doc PUT /v1/events/:id – попытка обновления чужим пользователем (403). -spec test_update_event_forbidden(binary(), binary()) -> ok. test_update_event_forbidden(OtherToken, EventId) -> ct:pal(" TEST: Update event by non-owner"), Path = <<"/v1/events/", EventId/binary>>, Resp = api_test_runner:client_request(put, Path, OtherToken, jsx:encode(#{title => <<"fail">>})), ?assertMatch({ok, 403, _, _}, Resp), ct:pal(" OK: got 403"). %% @doc DELETE /v1/events/:id – мягкое удаление события. -spec test_delete_event(binary(), binary()) -> ok. test_delete_event(Token, EventId) -> ct:pal(" TEST: Soft-delete event"), Path = <<"/v1/events/", EventId/binary>>, % Удаляем событие {ok, 200, _, _} = api_test_runner:client_request(delete, Path, Token), % Проверяем, что событие доступно, но его статус = deleted Event = api_test_runner:client_get(Path, Token), ?assertEqual(<<"deleted">>, maps:get(<<"status">>, Event)), ct:pal(" OK: event soft-deleted"). %% @doc GET /v1/events/:id – несуществующее событие (404). -spec test_get_event_not_found(binary()) -> ok. test_get_event_not_found(Token) -> ct:pal(" TEST: Get non-existent event"), Resp = api_test_runner:client_request(get, <<"/v1/events/fakeid">>, Token), ?assertMatch({ok, 404, _, _}, Resp), ct:pal(" OK: got 404"). %% @doc GET /v1/events/:id – без токена (401). -spec test_get_event_unauthorized(binary()) -> ok. test_get_event_unauthorized(EventId) -> ct:pal(" TEST: Get event without token"), Path = <<"/v1/events/", EventId/binary>>, Resp = api_test_runner:client_request(get, Path, <<>>), ?assertMatch({ok, 401, _, _}, Resp), ct:pal(" OK: got 401").