Добавить автомодерацию: политики, порог жалоб, settings/hits API и тесты.
Refs EventHub/EventHubBack#37 Refs EventHub/EventHubBack#38 Refs EventHub/EventHubBack#39 Refs EventHub/EventHubBack#40
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @doc API-тесты автомодерации (admin settings + hits queue).
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(admin_automod_tests).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-export([test/0]).
|
||||
|
||||
-spec test() -> ok.
|
||||
test() ->
|
||||
ct:pal("=== Admin Automod Tests ==="),
|
||||
Admin = api_test_runner:get_admin_token(),
|
||||
Moder = api_test_runner:get_moderator_token(),
|
||||
|
||||
test_get_settings(Admin),
|
||||
test_put_settings(Admin),
|
||||
test_put_settings_forbidden_moderator(Moder),
|
||||
Unique = integer_to_binary(erlang:system_time()),
|
||||
BadWord = <<"am_spam_", Unique/binary>>,
|
||||
test_seed_banned_word(Admin, BadWord),
|
||||
test_flag_creates_hit(Admin, BadWord),
|
||||
test_list_hits_filter(Admin),
|
||||
test_approve_restores(Admin, Moder, BadWord),
|
||||
test_reject_keeps_frozen(Admin, BadWord),
|
||||
test_restore_defaults(Admin),
|
||||
|
||||
ct:pal("=== All admin automod tests passed ==="),
|
||||
ok.
|
||||
|
||||
test_get_settings(Token) ->
|
||||
ct:pal(" TEST: GET automod settings"),
|
||||
S = api_test_runner:admin_get(<<"/v1/admin/automod/settings">>, Token),
|
||||
?assert(maps:is_key(<<"keyword_action">>, S)),
|
||||
?assert(maps:is_key(<<"match_mode">>, S)),
|
||||
?assert(maps:is_key(<<"report_threshold">>, S)),
|
||||
ct:pal(" OK").
|
||||
|
||||
test_put_settings(Token) ->
|
||||
ct:pal(" TEST: PUT automod settings"),
|
||||
S = api_test_runner:admin_put(<<"/v1/admin/automod/settings">>, Token, #{
|
||||
<<"keyword_action">> => <<"flag">>,
|
||||
<<"match_mode">> => <<"word_boundary">>,
|
||||
<<"report_threshold">> => 3
|
||||
}),
|
||||
?assertEqual(<<"flag">>, maps:get(<<"keyword_action">>, S)),
|
||||
?assertEqual(3, maps:get(<<"report_threshold">>, S)),
|
||||
ct:pal(" OK").
|
||||
|
||||
test_put_settings_forbidden_moderator(Token) ->
|
||||
ct:pal(" TEST: moderator cannot PUT settings"),
|
||||
{ok, Status, _, _} = api_test_runner:admin_request(put,
|
||||
<<"/v1/admin/automod/settings">>, Token,
|
||||
jsx:encode(#{<<"report_threshold">> => 9})),
|
||||
?assertEqual(403, Status),
|
||||
ct:pal(" OK").
|
||||
|
||||
test_seed_banned_word(Token, Word) ->
|
||||
ct:pal(" TEST: seed banned word ~s", [Word]),
|
||||
_ = api_test_runner:admin_post(<<"/v1/admin/banned-words">>, Token, #{<<"word">> => Word}),
|
||||
ct:pal(" OK").
|
||||
|
||||
test_flag_creates_hit(AdminToken, BadWord) ->
|
||||
ct:pal(" TEST: flag policy creates hit via user content"),
|
||||
api_test_runner:admin_put(<<"/v1/admin/automod/settings">>, AdminToken, #{
|
||||
<<"keyword_action">> => <<"flag">>,
|
||||
<<"match_mode">> => <<"word_boundary">>,
|
||||
<<"report_threshold">> => 3
|
||||
}),
|
||||
User = api_test_runner:get_user_token(),
|
||||
CalId = api_test_runner:create_calendar(User, #{title => <<"AutomodCal">>}),
|
||||
Title = <<"Party with ", BadWord/binary>>,
|
||||
{ok, 201, _, Body} = api_test_runner:client_request(post,
|
||||
<<"/v1/calendars/", CalId/binary, "/events">>, User,
|
||||
jsx:encode(#{
|
||||
title => Title,
|
||||
start_time => api_test_runner:future_date_iso8601(),
|
||||
duration => 60
|
||||
})),
|
||||
#{<<"id">> := EventId, <<"status">> := Status} =
|
||||
jsx:decode(list_to_binary(Body), [return_maps]),
|
||||
?assertEqual(<<"frozen">>, Status),
|
||||
Hits = api_test_runner:admin_get(<<"/v1/admin/automod/hits?status=open">>, AdminToken),
|
||||
?assert(lists:any(fun(H) ->
|
||||
maps:get(<<"entity_id">>, H) =:= EventId andalso
|
||||
maps:get(<<"trigger">>, H) =:= <<"keyword">>
|
||||
end, Hits)),
|
||||
put({automod_event, BadWord}, EventId),
|
||||
ct:pal(" OK: event ~s frozen + hit", [EventId]).
|
||||
|
||||
test_list_hits_filter(Token) ->
|
||||
ct:pal(" TEST: list hits filter by trigger"),
|
||||
Hits = api_test_runner:admin_get(<<"/v1/admin/automod/hits?trigger=keyword">>, Token),
|
||||
?assert(is_list(Hits)),
|
||||
?assert(lists:all(fun(H) -> maps:get(<<"trigger">>, H) =:= <<"keyword">> end, Hits)),
|
||||
ct:pal(" OK: ~p", [length(Hits)]).
|
||||
|
||||
test_approve_restores(AdminToken, ModerToken, BadWord) ->
|
||||
ct:pal(" TEST: approve hit restores entity"),
|
||||
EventId = get({automod_event, BadWord}),
|
||||
Hits = api_test_runner:admin_get(<<"/v1/admin/automod/hits?status=open">>, AdminToken),
|
||||
Hit = hd([H || H <- Hits, maps:get(<<"entity_id">>, H) =:= EventId]),
|
||||
HitId = maps:get(<<"id">>, Hit),
|
||||
Resolved = api_test_runner:admin_put(
|
||||
<<"/v1/admin/automod/hits/", HitId/binary>>, ModerToken,
|
||||
#{<<"status">> => <<"approved">>}),
|
||||
?assertEqual(<<"approved">>, maps:get(<<"status">>, Resolved)),
|
||||
%% admin event fetch
|
||||
Ev = api_test_runner:admin_get(<<"/v1/admin/events/", EventId/binary>>, AdminToken),
|
||||
?assertEqual(<<"active">>, maps:get(<<"status">>, Ev)),
|
||||
ct:pal(" OK").
|
||||
|
||||
test_reject_keeps_frozen(AdminToken, BadWord) ->
|
||||
ct:pal(" TEST: reject hit keeps freeze"),
|
||||
User = api_test_runner:get_user_token(),
|
||||
CalId = api_test_runner:create_calendar(User, #{title => <<"AutomodCal2">>}),
|
||||
Title = <<"Again ", BadWord/binary>>,
|
||||
{ok, 201, _, Body} = api_test_runner:client_request(post,
|
||||
<<"/v1/calendars/", CalId/binary, "/events">>, User,
|
||||
jsx:encode(#{
|
||||
title => Title,
|
||||
start_time => api_test_runner:future_date_iso8601(),
|
||||
duration => 45
|
||||
})),
|
||||
#{<<"id">> := EventId} = jsx:decode(list_to_binary(Body), [return_maps]),
|
||||
Hits = api_test_runner:admin_get(<<"/v1/admin/automod/hits?status=open">>, AdminToken),
|
||||
Hit = hd([H || H <- Hits, maps:get(<<"entity_id">>, H) =:= EventId]),
|
||||
HitId = maps:get(<<"id">>, Hit),
|
||||
_ = api_test_runner:admin_put(<<"/v1/admin/automod/hits/", HitId/binary>>, AdminToken,
|
||||
#{<<"status">> => <<"rejected">>}),
|
||||
Ev = api_test_runner:admin_get(<<"/v1/admin/events/", EventId/binary>>, AdminToken),
|
||||
?assertEqual(<<"frozen">>, maps:get(<<"status">>, Ev)),
|
||||
ct:pal(" OK").
|
||||
|
||||
test_restore_defaults(Token) ->
|
||||
ct:pal(" TEST: restore default settings"),
|
||||
_ = api_test_runner:admin_put(<<"/v1/admin/automod/settings">>, Token, #{
|
||||
<<"keyword_action">> => <<"flag">>,
|
||||
<<"match_mode">> => <<"word_boundary">>,
|
||||
<<"report_threshold">> => 3
|
||||
}),
|
||||
ct:pal(" OK").
|
||||
Reference in New Issue
Block a user