249 lines
10 KiB
Erlang
249 lines
10 KiB
Erlang
-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). |