Files
EventHubBack/test/api/users/user_review_vote_tests.erl
T
aleksey 5b638de450
CI / test (push) Failing after 45m52s
CI / deploy-ift (push) Has been skipped
CI / e2e-ift (push) Has been skipped
CI / deploy-stage (push) Has been skipped
CI / e2e-stage (push) Has been skipped
feat: user API голосования за отзывы (like/dislike). Refs EventHub/EventHubBack#47
2026-07-19 21:31:29 +03:00

158 lines
6.1 KiB
Erlang

%%%-------------------------------------------------------------------
%%% @doc Тесты голосования за отзывы (like/dislike).
%%%
%%% PUT /v1/reviews/:id/vote
%%% DELETE /v1/reviews/:id/vote
%%% GET /v1/reviews/:id (my_vote)
%%% @end
%%%-------------------------------------------------------------------
-module(user_review_vote_tests).
-include_lib("eunit/include/eunit.hrl").
-export([test/0]).
-spec test() -> ok.
test() ->
ct:pal("=== User Review Vote Tests ==="),
OwnerToken = api_test_runner:get_user_token(),
AuthorEmail = api_test_runner:unique_email(<<"rvauthor">>),
AuthorToken = api_test_runner:register_and_login(AuthorEmail, <<"pass">>),
VoterEmail = api_test_runner:unique_email(<<"rvvoter">>),
VoterToken = api_test_runner:register_and_login(VoterEmail, <<"pass">>),
OtherEmail = api_test_runner:unique_email(<<"rvother">>),
OtherToken = api_test_runner:register_and_login(OtherEmail, <<"pass">>),
CalId = api_test_runner:create_calendar(OwnerToken, #{title => <<"VoteCal">>}),
#{<<"id">> := EventId} = api_test_runner:client_post(
<<"/v1/calendars/", CalId/binary, "/events">>, OwnerToken,
#{title => <<"Event for votes">>,
start_time => api_test_runner:future_date_iso8601(),
duration => 60}),
#{<<"id">> := BookingId} = api_test_runner:client_post(
<<"/v1/events/", EventId/binary, "/bookings">>, AuthorToken, #{}),
api_test_runner:client_put(<<"/v1/bookings/", BookingId/binary>>, OwnerToken,
#{action => <<"confirm">>}),
#{<<"id">> := ReviewId} = api_test_runner:client_post(
<<"/v1/reviews">>, AuthorToken,
#{target_type => <<"event">>,
target_id => EventId,
rating => 5,
comment => <<"Nice event">>}),
VotePath = <<"/v1/reviews/", ReviewId/binary, "/vote">>,
test_put_like(VoterToken, VotePath),
test_put_like_idempotent(VoterToken, VotePath),
test_switch_to_dislike(VoterToken, VotePath),
test_my_vote_on_get(VoterToken, ReviewId),
test_my_vote_on_list(VoterToken, EventId, ReviewId),
test_delete_vote(VoterToken, VotePath),
test_delete_idempotent(VoterToken, VotePath),
test_own_review_forbidden(AuthorToken, VotePath),
test_unauthorized(VotePath),
test_not_found(VoterToken),
test_invalid_body(VoterToken, VotePath),
test_second_voter(OtherToken, VotePath),
ct:pal("=== All user review vote tests passed ==="),
ok.
%%%===================================================================
%%% Cases
%%%===================================================================
test_put_like(Token, Path) ->
ct:pal(" TEST: PUT like"),
Resp = api_test_runner:client_put(Path, Token, #{value => <<"like">>}),
?assertEqual(<<"like">>, maps:get(<<"my_vote">>, Resp)),
?assertEqual(1, maps:get(<<"likes">>, Resp)),
?assertEqual(0, maps:get(<<"dislikes">>, Resp)),
ct:pal(" OK").
test_put_like_idempotent(Token, Path) ->
ct:pal(" TEST: PUT like idempotent"),
Resp = api_test_runner:client_put(Path, Token, #{value => <<"like">>}),
?assertEqual(<<"like">>, maps:get(<<"my_vote">>, Resp)),
?assertEqual(1, maps:get(<<"likes">>, Resp)),
?assertEqual(0, maps:get(<<"dislikes">>, Resp)),
ct:pal(" OK").
test_switch_to_dislike(Token, Path) ->
ct:pal(" TEST: switch like -> dislike"),
Resp = api_test_runner:client_put(Path, Token, #{value => <<"dislike">>}),
?assertEqual(<<"dislike">>, maps:get(<<"my_vote">>, Resp)),
?assertEqual(0, maps:get(<<"likes">>, Resp)),
?assertEqual(1, maps:get(<<"dislikes">>, Resp)),
ct:pal(" OK").
test_my_vote_on_get(Token, ReviewId) ->
ct:pal(" TEST: GET review includes my_vote"),
Review = api_test_runner:client_get(<<"/v1/reviews/", ReviewId/binary>>, Token),
?assertEqual(<<"dislike">>, maps:get(<<"my_vote">>, Review)),
?assertEqual(1, maps:get(<<"dislikes">>, Review)),
ct:pal(" OK").
test_my_vote_on_list(Token, EventId, ReviewId) ->
ct:pal(" TEST: GET reviews list includes my_vote"),
Path = <<"/v1/reviews?target_type=event&target_id=", EventId/binary>>,
List = api_test_runner:client_get(Path, Token),
?assert(is_list(List)),
Match = [R || R <- List, maps:get(<<"id">>, R) =:= ReviewId],
?assertMatch([_], Match),
[R] = Match,
?assertEqual(<<"dislike">>, maps:get(<<"my_vote">>, R)),
ct:pal(" OK").
test_delete_vote(Token, Path) ->
ct:pal(" TEST: DELETE vote"),
Resp = api_test_runner:client_delete(Path, Token),
?assertEqual(null, maps:get(<<"my_vote">>, Resp)),
?assertEqual(0, maps:get(<<"likes">>, Resp)),
?assertEqual(0, maps:get(<<"dislikes">>, Resp)),
ct:pal(" OK").
test_delete_idempotent(Token, Path) ->
ct:pal(" TEST: DELETE vote idempotent"),
Resp = api_test_runner:client_delete(Path, Token),
?assertEqual(null, maps:get(<<"my_vote">>, Resp)),
?assertEqual(0, maps:get(<<"likes">>, Resp)),
?assertEqual(0, maps:get(<<"dislikes">>, Resp)),
ct:pal(" OK").
test_own_review_forbidden(Token, Path) ->
ct:pal(" TEST: vote on own review -> 403"),
Body = jsx:encode(#{value => <<"like">>}),
Resp = api_test_runner:client_request(put, Path, Token, Body),
?assertMatch({ok, 403, _, _}, Resp),
ct:pal(" OK").
test_unauthorized(Path) ->
ct:pal(" TEST: unauthorized -> 401"),
Body = jsx:encode(#{value => <<"like">>}),
Resp = api_test_runner:client_request(put, Path, <<>>, Body),
?assertMatch({ok, 401, _, _}, Resp),
ct:pal(" OK").
test_not_found(Token) ->
ct:pal(" TEST: vote missing review -> 404"),
Path = <<"/v1/reviews/missing-review-id/vote">>,
Body = jsx:encode(#{value => <<"like">>}),
Resp = api_test_runner:client_request(put, Path, Token, Body),
?assertMatch({ok, 404, _, _}, Resp),
ct:pal(" OK").
test_invalid_body(Token, Path) ->
ct:pal(" TEST: invalid value -> 400"),
Body = jsx:encode(#{value => <<"love">>}),
Resp = api_test_runner:client_request(put, Path, Token, Body),
?assertMatch({ok, 400, _, _}, Resp),
ct:pal(" OK").
test_second_voter(Token, Path) ->
ct:pal(" TEST: second voter like"),
Resp = api_test_runner:client_put(Path, Token, #{value => <<"like">>}),
?assertEqual(<<"like">>, maps:get(<<"my_vote">>, Resp)),
?assertEqual(1, maps:get(<<"likes">>, Resp)),
?assertEqual(0, maps:get(<<"dislikes">>, Resp)),
ct:pal(" OK").