mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
195 lines
6.2 KiB
Erlang
195 lines
6.2 KiB
Erlang
%% SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
-module(guild_thread_push_tests).
|
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
-define(G, 1).
|
|
-define(A, 10).
|
|
-define(B, 11).
|
|
-define(C, 12).
|
|
-define(OUT, 13).
|
|
-define(AUTHOR, 14).
|
|
-define(TEXT, 100).
|
|
-define(THREAD, 500).
|
|
-define(VIEW, 1024).
|
|
-define(SEND, 2048).
|
|
-define(CONFIG_KEY, channel_threads_config).
|
|
|
|
with_config(Fun) ->
|
|
Previous = persistent_term:get(?CONFIG_KEY, undefined),
|
|
Config = (channel_threads_config:default_config())#{
|
|
enabled => true,
|
|
included_users =>
|
|
#{integer_to_binary(Id) => true || Id <- [?A, ?B, ?C, ?AUTHOR]}
|
|
},
|
|
persistent_term:put(?CONFIG_KEY, Config),
|
|
try
|
|
Fun()
|
|
after
|
|
case Previous of
|
|
undefined -> persistent_term:erase(?CONFIG_KEY);
|
|
_ -> persistent_term:put(?CONFIG_KEY, Previous)
|
|
end
|
|
end.
|
|
|
|
raw_data() ->
|
|
Gid = integer_to_binary(?G),
|
|
Member = fun(Id) ->
|
|
#{
|
|
<<"user">> => #{<<"id">> => integer_to_binary(Id)},
|
|
<<"roles">> => [],
|
|
<<"joined_at">> => <<"2026-01-01T00:00:00Z">>
|
|
}
|
|
end,
|
|
#{
|
|
<<"guild">> => #{<<"id">> => Gid, <<"owner_id">> => <<"999">>, <<"features">> => []},
|
|
<<"roles">> => [
|
|
#{
|
|
<<"id">> => Gid,
|
|
<<"permissions">> => integer_to_binary(?VIEW bor ?SEND),
|
|
<<"position">> => 0
|
|
}
|
|
],
|
|
<<"channels">> => [
|
|
#{<<"id">> => <<"100">>, <<"type">> => 0, <<"permission_overwrites">> => []}
|
|
],
|
|
<<"members">> => [Member(Id) || Id <- [?A, ?B, ?C, ?OUT, ?AUTHOR]],
|
|
<<"emojis">> => [],
|
|
<<"stickers">> => []
|
|
}.
|
|
|
|
thread_member(UserId) ->
|
|
#{
|
|
<<"id">> => integer_to_binary(?THREAD),
|
|
<<"user_id">> => integer_to_binary(UserId),
|
|
<<"join_timestamp">> => <<"2026-01-01T00:00:00.000Z">>,
|
|
<<"flags">> => 1
|
|
}.
|
|
|
|
state(Active) ->
|
|
Payload = guild_thread_load:load_payload(#{
|
|
<<"threads">> => [
|
|
#{
|
|
<<"id">> => integer_to_binary(?THREAD),
|
|
<<"guild_id">> => integer_to_binary(?G),
|
|
<<"parent_id">> => integer_to_binary(?TEXT),
|
|
<<"type">> => 11,
|
|
<<"name">> => <<"ideas">>,
|
|
<<"thread_metadata">> => #{<<"archived">> => false, <<"locked">> => false}
|
|
}
|
|
],
|
|
<<"thread_members">> => [thread_member(?A), thread_member(?OUT)]
|
|
}),
|
|
Base = #{
|
|
id => ?G,
|
|
member_count => 5,
|
|
data => guild_data_index:normalize_map(raw_data()),
|
|
sessions => #{
|
|
<<"b">> => #{session_id => <<"b">>, user_id => ?B, pid => self()},
|
|
<<"a">> => #{session_id => <<"a">>, user_id => ?A, pid => self()}
|
|
}
|
|
},
|
|
Gate =
|
|
case Active of
|
|
true ->
|
|
#{
|
|
thread_gate => #{active => true, version => 1},
|
|
thread_tainted => true,
|
|
thread_load => {ok, Payload}
|
|
};
|
|
false ->
|
|
#{}
|
|
end,
|
|
guild_thread_load:install(Gate, Base).
|
|
|
|
with_state(Active, Fun) ->
|
|
with_config(fun() ->
|
|
State = state(Active),
|
|
try
|
|
Fun(State)
|
|
after
|
|
guild_thread_store:destroy(guild_thread_gate:store(State))
|
|
end
|
|
end).
|
|
|
|
mention_request(ChannelId, Overrides) ->
|
|
maps:merge(
|
|
#{
|
|
channel_id => ChannelId,
|
|
author_id => ?AUTHOR,
|
|
mention_everyone => false,
|
|
mention_here => false,
|
|
role_ids => [],
|
|
user_ids => []
|
|
},
|
|
Overrides
|
|
).
|
|
|
|
everyone(Request, State) ->
|
|
{reply, #{everyone_user_ids := Ids}, _} =
|
|
guild_members_mutation:resolve_mention_sources(Request, State),
|
|
lists:sort(Ids).
|
|
|
|
everyone_in_a_thread_reaches_recipient_active_members_only_test() ->
|
|
with_state(true, fun(State) ->
|
|
Request = mention_request(?THREAD, #{mention_everyone => true}),
|
|
?assertEqual([?A], everyone(Request, State)),
|
|
?assertEqual(
|
|
[?A, ?B, ?C, ?OUT],
|
|
everyone(mention_request(?TEXT, #{mention_everyone => true}), State)
|
|
)
|
|
end).
|
|
|
|
here_in_a_thread_needs_membership_and_a_connection_test() ->
|
|
with_state(true, fun(State) ->
|
|
Request = mention_request(?THREAD, #{mention_here => true}),
|
|
?assertEqual([?A], everyone(Request, State)),
|
|
?assertEqual([?A, ?B], everyone(mention_request(?TEXT, #{mention_here => true}), State))
|
|
end).
|
|
|
|
direct_mentions_in_a_thread_skip_inactive_recipients_test() ->
|
|
with_state(true, fun(State) ->
|
|
{reply, #{direct_user_ids := Ids}, _} =
|
|
guild_members_mutation:resolve_mention_sources(
|
|
mention_request(?THREAD, #{user_ids => [?B, ?OUT]}), State
|
|
),
|
|
?assertEqual([?B], lists:sort(Ids))
|
|
end).
|
|
|
|
paged_everyone_in_a_thread_lists_members_only_test() ->
|
|
with_state(true, fun(State) ->
|
|
Request = (mention_request(?THREAD, #{mention_everyone => true}))#{
|
|
limit => 100, cursor => undefined
|
|
},
|
|
{reply, #{mentions := Entries}, _} =
|
|
guild_members_mutation:resolve_mention_sources_page(Request, State),
|
|
?assertEqual([?A], lists:sort([entry_user_id(E) || E <- Entries]))
|
|
end).
|
|
|
|
inactive_guild_mentions_are_unchanged_test() ->
|
|
with_state(false, fun(State) ->
|
|
?assertEqual(undefined, guild_thread_push:mention_universe(?THREAD, State)),
|
|
?assertEqual(
|
|
[?A, ?B, ?C, ?OUT],
|
|
everyone(mention_request(?TEXT, #{mention_everyone => true}), State)
|
|
)
|
|
end).
|
|
|
|
passive_threads_follow_membership_test() ->
|
|
with_state(true, fun(State) ->
|
|
?assertMatch(
|
|
[#{<<"name">> := <<"ideas">>}],
|
|
guild_thread_push:passive_threads(#{thread_viewer => true}, ?A, State)
|
|
),
|
|
?assertEqual(
|
|
[], guild_thread_push:passive_threads(#{thread_viewer => true}, ?B, State)
|
|
),
|
|
?assertEqual([], guild_thread_push:passive_threads(#{}, ?A, State))
|
|
end).
|
|
|
|
entry_user_id(#{user_id := UserId}) -> UserId;
|
|
entry_user_id(#{<<"user_id">> := UserId}) -> snowflake_id:parse_optional(UserId);
|
|
entry_user_id(UserId) when is_integer(UserId) -> UserId;
|
|
entry_user_id(Other) -> Other.
|