%%%------------------------------------------------------------------- %%% @doc Тесты административного API для управления отзывами. %%% Покрывает эндпоинты: %%% GET /v1/admin/reviews %%% PATCH /v1/admin/reviews %%% GET /v1/admin/reviews/:id %%% PUT /v1/admin/reviews/:id %%% @end %%%------------------------------------------------------------------- -module(admin_reviews_tests). -include_lib("eunit/include/eunit.hrl"). -export([test/0]). %%%=================================================================== %%% EUnit test generator %%%=================================================================== test() -> ct:pal("=== Admin Reviews Tests ==="), Token = api_test_runner:get_admin_token(), UserToken = api_test_runner:get_user_token(), %% Создаём тестовые данные: календарь, событие CalId = api_test_runner:create_calendar(UserToken, #{title => <<"ReviewsTestCal">>}), EventId = api_test_runner:create_event(UserToken, CalId, #{ title => <<"Event for review testing">>, start_time => api_test_runner:future_date(), duration => 60 }), %% Создаём двух пользователей для отзывов User1Email = api_test_runner:unique_email(<<"rev1">>), User1Token = api_test_runner:register_and_login(User1Email, <<"pass1">>), User2Email = api_test_runner:unique_email(<<"rev2">>), User2Token = api_test_runner:register_and_login(User2Email, <<"pass2">>), %% Записываем пользователей на событие и подтверждаем бронирования #{<<"id">> := Booking1Id} = api_test_runner:client_post( <<"/v1/events/", EventId/binary, "/bookings">>, User1Token, #{}), #{<<"id">> := Booking2Id} = api_test_runner:client_post( <<"/v1/events/", EventId/binary, "/bookings">>, User2Token, #{}), ct:pal(" Confirming bookings as calendar owner..."), api_test_runner:client_put(<<"/v1/bookings/", Booking1Id/binary>>, UserToken, #{action => <<"confirm">>}), api_test_runner:client_put(<<"/v1/bookings/", Booking2Id/binary>>, UserToken, #{action => <<"confirm">>}), %% Оставляем отзывы от имени участников #{<<"id">> := Review1Id} = api_test_runner:client_post(<<"/v1/reviews">>, User1Token, #{ target_type => <<"event">>, target_id => EventId, rating => 5, comment => <<"Great!">> }), #{<<"id">> := Review2Id} = api_test_runner:client_post(<<"/v1/reviews">>, User2Token, #{ target_type => <<"event">>, target_id => EventId, rating => 4, comment => <<"Good">> }), %% Запускаем тесты test_list_reviews(Token), test_filter_reviews(Token, EventId), test_bulk_update_status(Token, Review1Id, Review2Id), test_get_review(Token, Review1Id), test_update_review(Token, Review1Id), test_review_pagination(Token), ct:pal("=== All admin reviews tests passed ==="), ok. %%%=================================================================== %%% Тестовые функции %%%=================================================================== %% @doc GET /v1/admin/reviews – список отзывов. test_list_reviews(Token) -> ct:pal(" TEST: List all reviews"), Reviews = api_test_runner:admin_get(<<"/v1/admin/reviews">>, Token), ?assert(is_list(Reviews)), ?assert(length(Reviews) >= 2), ct:pal(" OK: ~p reviews", [length(Reviews)]). %% @doc GET /v1/admin/reviews?target_type=event&target_id=... – фильтрация по цели. test_filter_reviews(Token, EventId) -> ct:pal(" TEST: Filter reviews by target"), Path = <<"/v1/admin/reviews?target_type=event&target_id=", EventId/binary>>, Reviews = api_test_runner:admin_get(Path, Token), ?assert(is_list(Reviews)), ?assert(length(Reviews) >= 2), [?assertEqual(EventId, maps:get(<<"target_id">>, R)) || R <- Reviews], ct:pal(" OK: ~p reviews for event", [length(Reviews)]). %% @doc PATCH /v1/admin/reviews – массовое обновление статусов. test_bulk_update_status(Token, Review1Id, Review2Id) -> ct:pal(" TEST: Bulk update review statuses"), Body = [ #{<<"id">> => Review1Id, <<"status">> => <<"visible">>}, #{<<"id">> => Review2Id, <<"status">> => <<"hidden">>} ], #{<<"updated_count">> := Count} = api_test_runner:admin_patch(<<"/v1/admin/reviews">>, Token, Body), ?assertEqual(2, Count), ct:pal(" OK: updated ~p reviews", [Count]). %% @doc GET /v1/admin/reviews/:id – получение отзыва по ID. test_get_review(Token, ReviewId) -> ct:pal(" TEST: Get review by ID"), Path = <<"/v1/admin/reviews/", ReviewId/binary>>, Review = api_test_runner:admin_get(Path, Token), ?assertEqual(ReviewId, maps:get(<<"id">>, Review)), ?assertEqual(<<"visible">>, maps:get(<<"status">>, Review)), ct:pal(" OK: ~s", [maps:get(<<"comment">>, Review)]). %% @doc PUT /v1/admin/reviews/:id – обновление отзыва. test_update_review(Token, ReviewId) -> ct:pal(" TEST: Update review"), Path = <<"/v1/admin/reviews/", ReviewId/binary>>, Updates = #{<<"comment">> => <<"Updated by admin">>}, Updated = api_test_runner:admin_put(Path, Token, Updates), ?assertEqual(<<"Updated by admin">>, maps:get(<<"comment">>, Updated)), ct:pal(" OK"). %% @doc GET /v1/admin/reviews?limit=...&offset=... – пагинация. test_review_pagination(Token) -> ct:pal(" TEST: Review pagination"), Page1 = api_test_runner:admin_get(<<"/v1/admin/reviews?limit=1&offset=0">>, Token), ?assertEqual(1, length(Page1)), Page2 = api_test_runner:admin_get(<<"/v1/admin/reviews?limit=1&offset=1">>, Token), ?assert(length(Page2) >= 1), Id1 = maps:get(<<"id">>, hd(Page1)), Id2 = maps:get(<<"id">>, hd(Page2)), ?assertNotEqual(Id1, Id2), ct:pal(" OK").