%%%------------------------------------------------------------------- %%% @doc Тесты клиентского API для работы с конкретным отзывом. %%% %%% Покрывает эндпоинты: %%% GET /v1/reviews/:id %%% PUT /v1/reviews/:id %%% DELETE /v1/reviews/:id %%% %%% Проверяет: %%% - получение отзыва по ID %%% - обновление отзыва (автором) %%% - удаление отзыва (автором) %%% - ошибку 403 при попытке изменения чужим пользователем %%% - ошибку 404 для несуществующего отзыва %%% - ошибку 401 без токена %%% @end %%%------------------------------------------------------------------- -module(user_review_by_id_tests). -include_lib("eunit/include/eunit.hrl"). -export([test/0]). %%%=================================================================== %%% Главная тестовая функция %%%=================================================================== -spec test() -> ok. test() -> ct:pal("=== User Review By ID Tests ==="), OwnerToken = api_test_runner:get_user_token(), ParticipantEmail = api_test_runner:unique_email(<<"reviewer">>), ParticipantToken = api_test_runner:register_and_login(ParticipantEmail, <<"pass">>), StrangerEmail = api_test_runner:unique_email(<<"stranger">>), StrangerToken = api_test_runner:register_and_login(StrangerEmail, <<"pass">>), % Создаём календарь, событие, бронирование и отзыв CalId = api_test_runner:create_calendar(OwnerToken, #{title => <<"RevById">>}), #{<<"id">> := EventId} = api_test_runner:client_post( <<"/v1/calendars/", CalId/binary, "/events">>, OwnerToken, #{title => <<"Event for review">>, start_time => <<"2026-06-01T10:00:00Z">>, duration => 60}), #{<<"id">> := BookingId} = api_test_runner:client_post( <<"/v1/events/", EventId/binary, "/bookings">>, ParticipantToken, #{}), api_test_runner:client_put(<<"/v1/bookings/", BookingId/binary>>, OwnerToken, #{action => <<"confirm">>}), #{<<"id">> := ReviewId} = api_test_runner:client_post( <<"/v1/reviews">>, ParticipantToken, #{target_type => <<"event">>, target_id => EventId, rating => 5, comment => <<"Excellent!">>}), test_get_review(ParticipantToken, ReviewId), test_update_review(ParticipantToken, ReviewId), test_update_review_forbidden(StrangerToken, ReviewId), test_delete_review(ParticipantToken, ReviewId), test_get_review_not_found(ParticipantToken), test_get_review_unauthorized(ReviewId), ct:pal("=== All user review by id tests passed ==="), ok. %%%=================================================================== %%% Тестовые функции %%%=================================================================== %% @doc GET /v1/reviews/:id – получение отзыва. -spec test_get_review(binary(), binary()) -> ok. test_get_review(Token, ReviewId) -> ct:pal(" TEST: Get review by ID"), Path = <<"/v1/reviews/", ReviewId/binary>>, Review = api_test_runner:client_get(Path, Token), ?assertEqual(ReviewId, maps:get(<<"id">>, Review)), ?assertEqual(<<"Excellent!">>, maps:get(<<"comment">>, Review)), ct:pal(" OK: got review"). %% @doc PUT /v1/reviews/:id – обновление отзыва автором. -spec test_update_review(binary(), binary()) -> ok. test_update_review(Token, ReviewId) -> ct:pal(" TEST: Update review"), Path = <<"/v1/reviews/", ReviewId/binary>>, Updated = api_test_runner:client_put(Path, Token, #{comment => <<"Updated comment">>, rating => 4}), ?assertEqual(<<"Updated comment">>, maps:get(<<"comment">>, Updated)), ?assertEqual(4, maps:get(<<"rating">>, Updated)), ct:pal(" OK"). %% @doc PUT /v1/reviews/:id – попытка обновления чужим пользователем (403). -spec test_update_review_forbidden(binary(), binary()) -> ok. test_update_review_forbidden(StrangerToken, ReviewId) -> ct:pal(" TEST: Update review by non-author"), Path = <<"/v1/reviews/", ReviewId/binary>>, Resp = api_test_runner:client_request(put, Path, StrangerToken, jsx:encode(#{comment => <<"fail">>})), ?assertMatch({ok, 403, _, _}, Resp), ct:pal(" OK: got 403"). %% @doc DELETE /v1/reviews/:id – удаление отзыва автором. -spec test_delete_review(binary(), binary()) -> ok. test_delete_review(Token, ReviewId) -> ct:pal(" TEST: Delete review"), Path = <<"/v1/reviews/", ReviewId/binary>>, % Удаляем {ok, 200, _, _} = api_test_runner:client_request(delete, Path, Token), % Проверяем, что отзыв больше недоступен GetResp = api_test_runner:client_request(get, Path, Token), ?assertMatch({ok, 404, _, _}, GetResp), ct:pal(" OK: review deleted"). %% @doc GET /v1/reviews/:id – несуществующий отзыв (404). -spec test_get_review_not_found(binary()) -> ok. test_get_review_not_found(Token) -> ct:pal(" TEST: Get non-existent review"), Resp = api_test_runner:client_request(get, <<"/v1/reviews/fakeid">>, Token), ?assertMatch({ok, 404, _, _}, Resp), ct:pal(" OK: got 404"). %% @doc GET /v1/reviews/:id – без токена (401). -spec test_get_review_unauthorized(binary()) -> ok. test_get_review_unauthorized(ReviewId) -> ct:pal(" TEST: Get review without token"), Path = <<"/v1/reviews/", ReviewId/binary>>, Resp = api_test_runner:client_request(get, Path, <<>>), ?assertMatch({ok, 401, _, _}, Resp), ct:pal(" OK: got 401").