Rewrite and expand EUnit suite; run unit tests in CI from shared test image. Refs EventHub/EventHubBack#36 [skip ci]

This commit is contained in:
2026-07-17 15:16:46 +03:00
parent 9d2780fef4
commit 4fa802702f
54 changed files with 4240 additions and 2281 deletions
+161
View File
@@ -0,0 +1,161 @@
-module(core_user_tests).
-include_lib("eunit/include/eunit.hrl").
-include("records.hrl").
-define(TABLES, [user]).
setup() ->
eh_test_support:start_mnesia(),
eh_test_support:ensure_tables(?TABLES),
case mnesia:add_table_index(user, email) of
{atomic, ok} -> ok;
{aborted, {already_exists, user, email}} -> ok;
{aborted, Reason} -> error({add_index_failed, Reason})
end,
ok.
cleanup(_) ->
eh_test_support:clear_tables(?TABLES),
eh_test_support:delete_tables(?TABLES),
eh_test_support:stop_mnesia(),
ok.
core_user_test_() ->
{foreach, fun setup/0, fun cleanup/1, [
{"Create user", fun test_create/0},
{"Create user email exists", fun test_create_email_exists/0},
{"Get by id", fun test_get_by_id/0},
{"Get by email / email_exists", fun test_get_by_email/0},
{"List all and list_users", fun test_list/0},
{"Update fields", fun test_update/0},
{"Update status", fun test_update_status/0},
{"Update last login", fun test_update_last_login/0},
{"Block and unblock", fun test_block_unblock/0},
{"Soft delete", fun test_delete/0},
{"Count helpers", fun test_counts/0},
{"Create and delete bot", fun test_bot/0}
]}.
test_create() ->
Email = <<"user1@test.local">>,
{ok, User} = core_user:create(Email, <<"secret123">>),
?assertEqual(Email, User#user.email),
?assertEqual(user, User#user.role),
?assertEqual(pending, User#user.status),
?assertEqual(<<"user1">>, User#user.nickname),
?assert(is_binary(User#user.id)),
?assert(is_binary(User#user.password_hash)),
?assert(User#user.password_hash =/= <<"secret123">>).
test_create_email_exists() ->
Email = <<"dup@test.local">>,
{ok, _} = core_user:create(Email, <<"pass1">>),
?assertEqual({error, email_exists}, core_user:create(Email, <<"pass2">>)).
test_get_by_id() ->
{ok, User} = core_user:create(<<"byid@test.local">>, <<"pass">>),
{ok, Found} = core_user:get_by_id(User#user.id),
?assertEqual(User#user.id, Found#user.id),
?assertEqual({error, not_found}, core_user:get_by_id(<<"missing">>)).
test_get_by_email() ->
Email = <<"byemail@test.local">>,
{ok, User} = core_user:create(Email, <<"pass">>),
{ok, Found} = core_user:get_by_email(Email),
?assertEqual(User#user.id, Found#user.id),
?assertEqual(true, core_user:email_exists(Email)),
?assertEqual(false, core_user:email_exists(<<"nope@test.local">>)),
?assertEqual({error, not_found}, core_user:get_by_email(<<"nope@test.local">>)).
test_list() ->
?assertEqual([], core_user:list_all()),
{ok, U1} = core_user:create(<<"a@test.local">>, <<"pass">>),
{ok, U2} = core_user:create(<<"b@test.local">>, <<"pass">>),
?assertEqual(2, length(core_user:list_all())),
{ok, _} = core_user:delete(U1#user.id),
All = core_user:list_all(),
?assertEqual(2, length(All)),
{ok, ActiveMaps} = core_user:list_users(),
?assertEqual(1, length(ActiveMaps)),
[Map] = ActiveMaps,
?assertEqual(U2#user.id, maps:get(id, Map)),
?assertEqual(<<"b@test.local">>, maps:get(email, Map)).
test_update() ->
{ok, User} = core_user:create(<<"upd@test.local">>, <<"pass">>),
{ok, Updated} = core_user:update(User#user.id, [
{nickname, <<"nick">>},
{phone, <<"+7000">>},
{timezone, <<"UTC">>},
{status, active}
]),
?assertEqual(<<"nick">>, Updated#user.nickname),
?assertEqual(<<"+7000">>, Updated#user.phone),
?assertEqual(<<"UTC">>, Updated#user.timezone),
?assertEqual(active, Updated#user.status),
?assertEqual({error, not_found}, core_user:update(<<"missing">>, [{nickname, <<"x">>}])).
test_update_status() ->
{ok, User} = core_user:create(<<"st@test.local">>, <<"pass">>),
{ok, Updated} = core_user:update_status(User#user.id, frozen, <<"review">>),
?assertEqual(frozen, Updated#user.status),
?assertEqual(<<"review">>, Updated#user.reason),
?assertEqual({error, not_found},
core_user:update_status(<<"missing">>, active, <<>>)).
test_update_last_login() ->
{ok, User} = core_user:create(<<"login@test.local">>, <<"pass">>),
OldLogin = User#user.last_login,
{ok, Updated} = core_user:update_last_login(User#user.id),
?assert(Updated#user.last_login >= OldLogin),
?assertEqual({error, not_found}, core_user:update_last_login(<<"missing">>)).
test_block_unblock() ->
{ok, User} = core_user:create(<<"block@test.local">>, <<"pass">>),
{ok, Blocked} = core_user:block(User#user.id, <<"spam">>),
?assertEqual(blocked, Blocked#user.status),
?assertEqual(<<"spam">>, Blocked#user.reason),
{ok, Active} = core_user:unblock(User#user.id, <<"ok">>),
?assertEqual(active, Active#user.status),
?assertEqual(<<"ok">>, Active#user.reason),
?assertEqual({error, not_found}, core_user:block(<<"missing">>, <<"x">>)),
?assertEqual({error, not_found}, core_user:unblock(<<"missing">>, <<"x">>)).
test_delete() ->
{ok, User} = core_user:create(<<"del@test.local">>, <<"pass">>),
{ok, Deleted} = core_user:delete(User#user.id),
?assertEqual(deleted, Deleted#user.status),
{ok, StillThere} = core_user:get_by_id(User#user.id),
?assertEqual(deleted, StillThere#user.status),
?assertEqual({error, not_found}, core_user:delete(<<"missing">>)).
test_counts() ->
{ok, U1} = core_user:create(<<"c1@test.local">>, <<"pass">>),
{ok, _} = core_user:create(<<"c2@test.local">>, <<"pass">>),
{ok, _} = core_user:update_status(U1#user.id, active, <<>>),
?assertEqual(2, core_user:count_users()),
?assertEqual(1, core_user:count_pending_users()),
ByRole = core_user:count_users_by_role(),
?assertEqual(2, proplists:get_value(user, ByRole)),
ByStatus = core_user:count_users_by_status(),
?assertEqual(1, proplists:get_value(pending, ByStatus)),
?assertEqual(1, proplists:get_value(active, ByStatus)),
Now = calendar:universal_time(),
{{Y, M, D}, _} = Now,
From = {{Y, M, D}, {0, 0, 0}},
To = {{Y, M, D}, {23, 59, 59}},
ByDate = core_user:count_users_by_date(From, To),
?assert(lists:keyfind({Y, M, D}, 1, ByDate) =/= false),
PendingByDate = core_user:count_pending_users_by_date(From, To),
{_, PendingCount} = lists:keyfind({Y, M, D}, 1, PendingByDate),
?assertEqual(1, PendingCount).
test_bot() ->
Email = <<"bot@test.local">>,
{ok, Bot} = core_user:create_bot(Email, <<"botpass">>),
?assertEqual(bot, Bot#user.role),
?assertEqual(active, Bot#user.status),
?assertEqual({error, email_exists}, core_user:create_bot(Email, <<"other">>)),
?assertEqual(ok, core_user:delete_bot(Bot#user.id)),
?assertEqual({error, not_found}, core_user:get_by_id(Bot#user.id)),
?assertEqual({error, not_found}, core_user:delete_bot(<<"missing">>)).