Files
EventHubBack/test/logic_search_tests.erl
2026-04-20 21:04:16 +03:00

249 lines
10 KiB
Erlang
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-module(logic_search_tests).
-include_lib("eunit/include/eunit.hrl").
-include("records.hrl").
setup() ->
mnesia:start(),
mnesia:create_table(user, [
{attributes, record_info(fields, user)},
{ram_copies, [node()]}
]),
mnesia:create_table(calendar, [
{attributes, record_info(fields, calendar)},
{ram_copies, [node()]}
]),
mnesia:create_table(event, [
{attributes, record_info(fields, event)},
{ram_copies, [node()]}
]),
ok.
cleanup(_) ->
mnesia:delete_table(event),
mnesia:delete_table(calendar),
mnesia:delete_table(user),
mnesia:stop(),
ok.
logic_search_test_() ->
{foreach,
fun setup/0,
fun cleanup/1,
[
{"Search events by text", fun test_search_events_by_text/0},
{"Search events by tags", fun test_search_events_by_tags/0},
{"Search events by date range", fun test_search_events_by_date/0},
{"Search events by location", fun test_search_events_by_location/0},
{"Combined search", fun test_combined_search/0},
{"Search calendars", fun test_search_calendars/0},
{"Search all", fun test_search_all/0},
{"Pagination", fun test_pagination/0},
{"Sorting", fun test_sorting/0},
{"Access control in search", fun test_access_control/0},
{"Empty search results", fun test_empty_search/0}
]}.
%% Вспомогательные функции
create_test_user(Role) ->
UserId = base64:encode(crypto:strong_rand_bytes(16), #{mode => urlsafe, padding => false}),
User = #user{
id = UserId,
email = <<UserId/binary, "@test.com">>,
password_hash = <<"hash">>,
role = Role,
status = active,
created_at = calendar:universal_time(),
updated_at = calendar:universal_time()
},
mnesia:dirty_write(User),
UserId.
create_test_calendar(OwnerId, Type, Tags) ->
{ok, Calendar} = core_calendar:create(OwnerId, <<"Test Calendar">>, <<"Description">>, manual),
core_calendar:update(Calendar#calendar.id, [{type, Type}, {tags, Tags}]),
{ok, Updated} = core_calendar:get_by_id(Calendar#calendar.id),
Updated#calendar.id.
create_test_event(CalendarId, Title, Description, StartTime, Tags, Location) ->
{ok, Event} = core_event:create(CalendarId, Title, StartTime, 60),
Updates = [{description, Description}, {tags, Tags}],
Updates2 = case Location of
undefined -> Updates;
_ -> [{location, Location} | Updates]
end,
core_event:update(Event#event.id, Updates2),
{ok, Updated} = core_event:get_by_id(Event#event.id),
Updated#event.id.
%% Тесты
test_search_events_by_text() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
StartTime = {{2026, 6, 1}, {10, 0, 0}},
create_test_event(CalendarId, <<"Python Workshop">>, <<"Learn Python">>, StartTime, [], undefined),
create_test_event(CalendarId, <<"JavaScript Conference">>, <<"JS for everyone">>, StartTime, [], undefined),
create_test_event(CalendarId, <<"Yoga Class">>, <<"Morning yoga">>, StartTime, [], undefined),
Params = #{},
{ok, Total, Results} = logic_search:search(<<"event">>, <<"Python">>, OwnerId, Params),
?assertEqual(1, Total),
?assertEqual(1, length(Results)),
{ok, Total2, _Results2} = logic_search:search(<<"event">>, <<"conference">>, OwnerId, Params),
?assertEqual(1, Total2).
test_search_events_by_tags() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
StartTime = {{2026, 6, 1}, {10, 0, 0}},
create_test_event(CalendarId, <<"Event 1">>, <<"">>, StartTime, [<<"python">>, <<"workshop">>], undefined),
create_test_event(CalendarId, <<"Event 2">>, <<"">>, StartTime, [<<"javascript">>, <<"conference">>], undefined),
create_test_event(CalendarId, <<"Event 3">>, <<"">>, StartTime, [<<"python">>, <<"advanced">>], undefined),
% Поиск по одному тегу
Params = #{tags => <<"python">>},
{ok, Total, _} = logic_search:search(<<"event">>, undefined, OwnerId, Params),
?assertEqual(2, Total), % Event 1 и Event 3
% Поиск по тегу, который есть только у одного события
Params2 = #{tags => <<"workshop">>},
{ok, Total2, _} = logic_search:search(<<"event">>, undefined, OwnerId, Params2),
?assertEqual(1, Total2), % Только Event 1
% Поиск по тегу, которого нет
Params3 = #{tags => <<"nonexistent">>},
{ok, Total3, _} = logic_search:search(<<"event">>, undefined, OwnerId, Params3),
?assertEqual(0, Total3).
test_search_events_by_date() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
create_test_event(CalendarId, <<"June Event">>, <<"">>, {{2026, 6, 15}, {10, 0, 0}}, [], undefined),
create_test_event(CalendarId, <<"July Event">>, <<"">>, {{2026, 7, 15}, {10, 0, 0}}, [], undefined),
create_test_event(CalendarId, <<"August Event">>, <<"">>, {{2026, 8, 15}, {10, 0, 0}}, [], undefined),
Params = #{from => {{2026, 6, 1}, {0, 0, 0}}, to => {{2026, 6, 30}, {23, 59, 59}}},
{ok, Total, _} = logic_search:search(<<"event">>, undefined, OwnerId, Params),
?assertEqual(1, Total).
test_search_events_by_location() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
StartTime = {{2026, 6, 1}, {10, 0, 0}},
MoscowLoc = #location{address = <<"Moscow">>, lat = 55.7558, lon = 37.6173},
SpbLoc = #location{address = <<"SPb">>, lat = 59.9343, lon = 30.3351},
create_test_event(CalendarId, <<"Moscow Event">>, <<"">>, StartTime, [], MoscowLoc),
create_test_event(CalendarId, <<"SPb Event">>, <<"">>, StartTime, [], SpbLoc),
Params = #{lat => 55.7558, lon => 37.6173, radius => 10},
{ok, Total, _Results} = logic_search:search(<<"event">>, undefined, OwnerId, Params),
?assertEqual(1, Total),
Params2 = #{lat => 59.9343, lon => 30.3351, radius => 10},
{ok, Total2, _} = logic_search:search(<<"event">>, undefined, OwnerId, Params2),
?assertEqual(1, Total2).
test_combined_search() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
StartTime = {{2026, 6, 15}, {10, 0, 0}},
create_test_event(CalendarId, <<"Python Workshop">>, <<"Learn Python">>, StartTime, [<<"python">>, <<"workshop">>], undefined),
create_test_event(CalendarId, <<"Python Advanced">>, <<"Advanced Python">>, {{2026, 7, 15}, {10, 0, 0}}, [<<"python">>, <<"advanced">>], undefined),
Params = #{from => {{2026, 6, 1}, {0, 0, 0}}, to => {{2026, 6, 30}, {23, 59, 59}}, tags => <<"python">>},
{ok, Total, _} = logic_search:search(<<"event">>, <<"Workshop">>, OwnerId, Params),
?assertEqual(1, Total).
test_search_calendars() ->
OwnerId = create_test_user(user),
create_test_calendar(OwnerId, personal, [<<"tech">>, <<"programming">>]),
create_test_calendar(OwnerId, commercial, [<<"yoga">>, <<"wellness">>]),
Params = #{tags => <<"tech">>},
{ok, Total, _} = logic_search:search(<<"calendar">>, undefined, OwnerId, Params),
?assertEqual(1, Total),
{ok, Total2, _} = logic_search:search(<<"calendar">>, <<"Calendar">>, OwnerId, #{}),
?assertEqual(2, Total2).
test_search_all() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
StartTime = {{2026, 6, 1}, {10, 0, 0}},
create_test_event(CalendarId, <<"Test Event">>, <<"">>, StartTime, [], undefined),
{ok, Total, Results} = logic_search:search(undefined, <<"Test">>, OwnerId, #{}),
?assert(Total >= 2),
?assert(maps:is_key(events, Results)),
?assert(maps:is_key(calendars, Results)).
test_pagination() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
StartTime = {{2026, 6, 1}, {10, 0, 0}},
lists:foreach(fun(I) ->
Title = iolist_to_binary(["Event ", integer_to_binary(I)]),
create_test_event(CalendarId, Title, <<"">>, StartTime, [], undefined)
end, [1, 2, 3, 4, 5]),
Params = #{limit => 2, offset => 0},
{ok, Total, Results} = logic_search:search(<<"event">>, undefined, OwnerId, Params),
?assertEqual(5, Total),
?assertEqual(2, length(Results)),
Params2 = #{limit => 2, offset => 2},
{ok, _, Results2} = logic_search:search(<<"event">>, undefined, OwnerId, Params2),
?assertEqual(2, length(Results2)),
Params3 = #{limit => 2, offset => 4},
{ok, _, Results3} = logic_search:search(<<"event">>, undefined, OwnerId, Params3),
?assertEqual(1, length(Results3)).
test_sorting() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
create_test_event(CalendarId, <<"Early">>, <<"">>, {{2026, 6, 1}, {10, 0, 0}}, [], undefined),
create_test_event(CalendarId, <<"Late">>, <<"">>, {{2026, 6, 30}, {10, 0, 0}}, [], undefined),
Params = #{sort => <<"start_time">>, order => <<"asc">>},
{ok, _, [First | _]} = logic_search:search(<<"event">>, undefined, OwnerId, Params),
?assertMatch(#{title := <<"Early">>}, First),
Params2 = #{sort => <<"start_time">>, order => <<"desc">>},
{ok, _, [First2 | _]} = logic_search:search(<<"event">>, undefined, OwnerId, Params2),
?assertMatch(#{title := <<"Late">>}, First2).
test_access_control() ->
OwnerId = create_test_user(user),
OtherId = create_test_user(user),
PersonalId = create_test_calendar(OwnerId, personal, []),
CommercialId = create_test_calendar(OwnerId, commercial, []),
StartTime = {{2026, 6, 1}, {10, 0, 0}},
create_test_event(PersonalId, <<"Personal Event">>, <<"">>, StartTime, [], undefined),
create_test_event(CommercialId, <<"Public Event">>, <<"">>, StartTime, [], undefined),
% Другой пользователь видит только коммерческие события
{ok, Total, Results} = logic_search:search(<<"event">>, undefined, OtherId, #{}),
?assertEqual(1, Total),
[Event] = Results,
?assertMatch(#{title := <<"Public Event">>}, Event).
test_empty_search() ->
OwnerId = create_test_user(user),
CalendarId = create_test_calendar(OwnerId, personal, []),
StartTime = {{2026, 6, 1}, {10, 0, 0}},
create_test_event(CalendarId, <<"Test">>, <<"">>, StartTime, [], undefined),
{ok, Total, Results} = logic_search:search(<<"event">>, <<"nonexistent">>, OwnerId, #{}),
?assertEqual(0, Total),
?assertEqual([], Results).