%%%------------------------------------------------------------------- %%% @doc Тесты клиентского API для поиска. %%% %%% Покрывает эндпоинты: %%% GET /v1/search %%% %%% Проверяет: %%% - полнотекстовый поиск по названиям событий %%% - поиск с фильтрацией по типу (event/calendar) %%% - поиск с фильтрацией по тегам %%% - поиск с фильтрацией по датам (from/to) %%% - геопоиск (lat, lon, radius) %%% - пагинацию результатов %%% - ошибку 401 без токена %%% @end %%%------------------------------------------------------------------- -module(user_search_tests). -include_lib("eunit/include/eunit.hrl"). -export([test/0]). %%%=================================================================== %%% Главная тестовая функция %%%=================================================================== -spec test() -> ok. test() -> ct:pal("=== User Search Tests ==="), Token = api_test_runner:get_user_token(), % Создаём тестовые данные: календарь и несколько событий с тегами CalId = api_test_runner:create_calendar(Token, #{title => <<"SearchTestCal">>}), api_test_runner:client_post( <<"/v1/calendars/", CalId/binary, "/events">>, Token, #{title => <<"Python Workshop">>, start_time => <<"2026-06-01T10:00:00Z">>, duration => 60, tags => [<<"python">>, <<"workshop">>]}), api_test_runner:client_post( <<"/v1/calendars/", CalId/binary, "/events">>, Token, #{title => <<"JavaScript Meetup">>, start_time => <<"2026-06-15T10:00:00Z">>, duration => 60, tags => [<<"javascript">>]}), test_basic_search(Token), test_type_filter(Token), test_tag_filter(Token), test_date_filter(Token), test_geo_search(Token), test_search_pagination(Token), test_search_unauthorized(), ct:pal("=== All user search tests passed ==="), ok. %%%=================================================================== %%% Вспомогательная функция %%%=================================================================== %% @private Извлекает список событий из результата поиска. %% Ожидает ответ вида {"results": {"events": [...], "calendars": [...]}}. -spec extract_events(map()) -> list(). extract_events(#{<<"results">> := #{<<"events">> := Events}}) -> Events. %%%=================================================================== %%% Тестовые функции %%%=================================================================== test_basic_search(Token) -> ct:pal(" TEST: Basic search"), Events = extract_events( api_test_runner:client_get(<<"/v1/search?q=Python">>, Token)), ?assert(is_list(Events)), ?assert(length(Events) >= 1), ct:pal(" OK: ~p events found", [length(Events)]). test_type_filter(Token) -> ct:pal(" TEST: Search with type filter"), Events = extract_events( api_test_runner:client_get(<<"/v1/search?q=Python&type=event">>, Token)), ?assert(is_list(Events)), ?assert(length(Events) >= 1), ct:pal(" OK: ~p events", [length(Events)]). test_tag_filter(Token) -> ct:pal(" TEST: Search with tag filter"), Events = extract_events( api_test_runner:client_get(<<"/v1/search?tags=python">>, Token)), ?assert(is_list(Events)), ?assert(length(Events) >= 1), ct:pal(" OK: ~p events", [length(Events)]). test_date_filter(Token) -> ct:pal(" TEST: Search with date range"), Events = extract_events( api_test_runner:client_get( <<"/v1/search?from=2026-06-01T00:00:00Z&to=2026-06-15T23:59:59Z">>, Token)), ?assert(is_list(Events)), ?assert(length(Events) >= 1), ct:pal(" OK: ~p events", [length(Events)]). test_geo_search(Token) -> ct:pal(" TEST: Geo search"), Events = extract_events( api_test_runner:client_get( <<"/v1/search?lat=55.75&lon=37.61&radius=1">>, Token)), ?assert(is_list(Events)), ?assert(length(Events) >= 0), ct:pal(" OK: ~p events", [length(Events)]). test_search_pagination(Token) -> ct:pal(" TEST: Search pagination"), Events1 = extract_events( api_test_runner:client_get(<<"/v1/search?limit=1&offset=0">>, Token)), ?assertEqual(1, length(Events1)), Events2 = extract_events( api_test_runner:client_get(<<"/v1/search?limit=1&offset=1">>, Token)), ?assert(length(Events2) >= 0), ct:pal(" OK"). test_search_unauthorized() -> ct:pal(" TEST: Search without token"), Resp = api_test_runner:client_request(get, <<"/v1/search?q=test">>, <<>>), ?assertMatch({ok, 401, _, _}, Resp), ct:pal(" OK: got 401").