Files
fluxer/fluxer_gateway/test/guild_dm_partners_tests.erl

213 lines
6.9 KiB
Erlang

%% SPDX-License-Identifier: AGPL-3.0-or-later
-module(guild_dm_partners_tests).
-typing([eqwalizer]).
-include_lib("eunit/include/eunit.hrl").
-define(GUILD_ID, 42).
-define(VIEWER_ROLE, 1000).
-define(OTHER_ROLE, 2000).
-define(SESSION, <<"session-10">>).
-define(FLAG, dm_presence_mutual_context).
registration_notifies_mutual_partners_test() ->
with_flag(true, fun() ->
State = register_partners(state(), [20, 30, 777]),
?assertEqual({dm_partner_mutual, ?GUILD_ID, [20]}, receive_mutual()),
?assert(maps:is_key(?SESSION, maps:get(dm_partners, State)))
end).
unknown_session_is_not_registered_test() ->
with_flag(true, fun() ->
{noreply, State} = guild_dm_partners:handle_cast(
{update_dm_partners, <<"missing">>, [20]}, state()
),
?assertEqual(#{}, maps:get(dm_partners, State, #{})),
?assertEqual(none, receive_mutual())
end).
disabled_flag_does_not_register_test() ->
with_flag(false, fun() ->
State = register_partners(state(), [20]),
?assertEqual(#{}, maps:get(dm_partners, State, #{})),
?assertEqual(none, receive_mutual())
end).
unchanged_eligibility_is_not_sent_again_test() ->
with_flag(true, fun() ->
State = register_partners(state(), [20]),
{dm_partner_mutual, _, [20]} = receive_mutual(),
_ = register_partners(State, [20, 777]),
?assertEqual(none, receive_mutual())
end).
partner_leaving_the_guild_withdraws_the_partner_test() ->
with_flag(true, fun() ->
Before = register_partners(state(), [20]),
{dm_partner_mutual, _, [20]} = receive_mutual(),
After = without_member(20, Before),
_ = guild_dm_partners:maybe_reevaluate(
guild_member_remove, #{<<"user">> => #{<<"id">> => <<"20">>}}, Before, After
),
?assertEqual({dm_partner_mutual, ?GUILD_ID, []}, receive_mutual())
end).
guild_wide_event_without_visibility_change_does_nothing_test() ->
with_flag(true, fun() ->
Before = register_partners(state(), [20]),
{dm_partner_mutual, _, [20]} = receive_mutual(),
Renamed = with_channels(
[
(channel(500, viewer_overwrites()))#{<<"name">> => <<"renamed">>},
channel(600, other_overwrites())
],
Before
),
_ = guild_dm_partners:maybe_reevaluate(channel_update, #{}, Before, Renamed),
?assertEqual(none, receive_mutual())
end).
guild_wide_visibility_change_reevaluates_test() ->
with_flag(true, fun() ->
Before = register_partners(state(), [30]),
?assertEqual(none, receive_mutual()),
Opened = with_channels(
[
channel(500, viewer_overwrites() ++ [overwrite(?OTHER_ROLE, 0)]),
channel(600, other_overwrites())
],
Before
),
_ = guild_dm_partners:maybe_reevaluate(channel_update, #{}, Before, Opened),
?assertEqual({dm_partner_mutual, ?GUILD_ID, [30]}, receive_mutual())
end).
partner_role_change_after_registration_reevaluates_test() ->
with_flag(true, fun() ->
Before = register_partners(state(), [30]),
?assertEqual(none, receive_mutual()),
After = with_member(member(30, [?VIEWER_ROLE]), Before),
_ = guild_dm_partners:maybe_reevaluate(
guild_member_update, #{<<"user">> => #{<<"id">> => <<"30">>}}, Before, After
),
?assertEqual({dm_partner_mutual, ?GUILD_ID, [30]}, receive_mutual())
end).
disconnected_sessions_are_dropped_on_reevaluation_test() ->
with_flag(true, fun() ->
Before = register_partners(state(), [20]),
{dm_partner_mutual, _, [20]} = receive_mutual(),
Gone = Before#{sessions => #{}},
After = guild_dm_partners:maybe_reevaluate(guild_role_delete, #{}, Before, Gone#{
virtual_channel_access => #{1 => sets:new()}
}),
?assertEqual(#{}, maps:get(dm_partners, After))
end).
register_partners(State, PartnerIds) ->
{noreply, NewState} = guild_dm_partners:handle_cast(
{update_dm_partners, ?SESSION, PartnerIds}, State
),
NewState.
state() ->
Base = #{
id => ?GUILD_ID,
virtual_channel_access => #{},
data => data(
[channel(500, viewer_overwrites()), channel(600, other_overwrites())], members()
)
},
Viewable = guild_sessions:build_viewable_channel_map(
guild_visibility:get_user_viewable_channels(10, Base)
),
Base#{
sessions => #{
?SESSION => #{user_id => 10, pid => self(), viewable_channels => Viewable}
}
}.
data(Channels, Members) ->
#{
<<"guild">> => #{<<"owner_id">> => <<"7">>},
<<"roles">> => [role(?GUILD_ID), role(?VIEWER_ROLE), role(?OTHER_ROLE)],
<<"members">> => Members,
<<"channels">> => Channels,
<<"channel_index">> => guild_data_index:build_id_index(Channels)
}.
members() ->
maps:from_list(
[{7, member(7, [])}] ++
[{Id, member(Id, [?VIEWER_ROLE])} || Id <- [10, 20]] ++
[{30, member(30, [?OTHER_ROLE])}]
).
without_member(UserId, #{data := Data} = State) ->
State#{data => Data#{<<"members">> => maps:remove(UserId, maps:get(<<"members">>, Data))}}.
with_member(Member, #{data := Data} = State) ->
#{<<"user">> := #{<<"id">> := RawId}} = Member,
Members = maps:get(<<"members">>, Data),
State#{data => Data#{<<"members">> => Members#{binary_to_integer(RawId) => Member}}}.
with_channels(Channels, #{data := Data} = State) ->
State#{
data => Data#{
<<"channels">> => Channels,
<<"channel_index">> => guild_data_index:build_id_index(Channels)
}
}.
role(RoleId) ->
#{<<"id">> => integer_to_binary(RoleId), <<"permissions">> => <<"0">>}.
member(UserId, RoleIds) ->
#{
<<"user">> => #{<<"id">> => integer_to_binary(UserId)},
<<"roles">> => [integer_to_binary(RoleId) || RoleId <- RoleIds]
}.
viewer_overwrites() ->
[overwrite(?VIEWER_ROLE, 0)].
other_overwrites() ->
[overwrite(?OTHER_ROLE, 0)].
overwrite(TargetId, Type) ->
#{
<<"id">> => integer_to_binary(TargetId),
<<"type">> => Type,
<<"allow">> => integer_to_binary(constants:view_channel_permission()),
<<"deny">> => <<"0">>
}.
channel(ChannelId, Overwrites) ->
#{
<<"id">> => integer_to_binary(ChannelId),
<<"type">> => 0,
<<"permission_overwrites">> => Overwrites
}.
receive_mutual() ->
receive
{dm_partner_mutual, _, _} = Msg -> Msg
after 100 ->
none
end.
with_flag(Value, Fun) ->
Previous = application:get_env(fluxer_gateway, ?FLAG),
application:set_env(fluxer_gateway, ?FLAG, Value),
try
Fun()
after
restore_flag(Previous)
end.
restore_flag(undefined) ->
application:unset_env(fluxer_gateway, ?FLAG);
restore_flag({ok, Value}) ->
application:set_env(fluxer_gateway, ?FLAG, Value).