Stage 4
This commit is contained in:
23
test/handler_search_tests.erl
Normal file
23
test/handler_search_tests.erl
Normal file
@@ -0,0 +1,23 @@
|
||||
-module(handler_search_tests).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
handler_search_test_() ->
|
||||
case is_server_running() of
|
||||
true ->
|
||||
[
|
||||
{"Search API requires authentication", fun test_search_requires_auth/0}
|
||||
];
|
||||
false ->
|
||||
io:format("Skipping handler tests: server not running~n"),
|
||||
[]
|
||||
end.
|
||||
|
||||
is_server_running() ->
|
||||
case httpc:request(get, {"http://localhost:8080/health", []}, [], [{timeout, 1000}]) of
|
||||
{ok, {{_, 200, _}, _, _}} -> true;
|
||||
_ -> false
|
||||
end.
|
||||
|
||||
test_search_requires_auth() ->
|
||||
{ok, {{_, 401, _}, _, Body}} = httpc:request(get, {"http://localhost:8080/v1/search?type=event", []}, [], []),
|
||||
?assertMatch(#{<<"error">> := _}, jsx:decode(Body, [return_maps])).
|
||||
249
test/logic_search_tests.erl
Normal file
249
test/logic_search_tests.erl
Normal file
@@ -0,0 +1,249 @@
|
||||
-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).
|
||||
50
test/scripts/run_tests.sh
Normal file
50
test/scripts/run_tests.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo "============================================================"
|
||||
echo " FULL TEST CYCLE"
|
||||
echo "============================================================"
|
||||
|
||||
# Остановка старых процессов
|
||||
echo "[1/4] Stopping old servers..."
|
||||
pkill -f "beam.*eventhub" 2>/dev/null || true
|
||||
rm -rf Mnesia.*
|
||||
sleep 2
|
||||
|
||||
# Запуск сервера в фоне
|
||||
echo "[2/4] Starting server..."
|
||||
./test/scripts/start_server_bg.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to start server"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Запуск тестов
|
||||
echo "[3/4] Running tests..."
|
||||
chmod +x test/scripts/*.sh
|
||||
cd test/scripts
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
./test_runner.sh -s "$1"
|
||||
else
|
||||
./test_runner.sh -s
|
||||
fi
|
||||
|
||||
TEST_RESULT=$?
|
||||
|
||||
# Остановка сервера
|
||||
echo ""
|
||||
echo "[4/4] Stopping server..."
|
||||
pkill -f "beam.*eventhub" 2>/dev/null || true
|
||||
|
||||
echo "============================================================"
|
||||
if [ $TEST_RESULT -eq 0 ]; then
|
||||
echo "🎉 ALL TESTS PASSED!"
|
||||
else
|
||||
echo "❌ TESTS FAILED"
|
||||
fi
|
||||
echo "============================================================"
|
||||
|
||||
exit $TEST_RESULT
|
||||
39
test/scripts/start_server_bg.sh
Normal file
39
test/scripts/start_server_bg.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
echo "PROJECT_ROOT: $PROJECT_ROOT"
|
||||
# Очистка
|
||||
echo "Stopping old processes..."
|
||||
pkill beam 2>/dev/null || true
|
||||
rm -rf Mnesia.*
|
||||
sleep 2
|
||||
|
||||
# Компиляция
|
||||
echo "Compiling..."
|
||||
rebar3 compile > /dev/null 2>&1
|
||||
|
||||
# Запуск в фоне через erl
|
||||
echo "Starting server in background..."
|
||||
erl -sname eventhub_test \
|
||||
-pa _build/default/lib/*/ebin \
|
||||
-eval "application:ensure_all_started(eventhub)" \
|
||||
-noshell \
|
||||
-detached
|
||||
|
||||
# Ждём запуска
|
||||
echo "Waiting for server..."
|
||||
for i in {1..30}; do
|
||||
if curl -s http://localhost:8080/health 2>/dev/null | grep -q "ok"; then
|
||||
echo "✓ Server ready at http://localhost:8080"
|
||||
pgrep -f "beam.*eventhub_test"
|
||||
exit 0
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✗ Server failed to start"
|
||||
pkill beam 2>/dev/null || true
|
||||
exit 1
|
||||
@@ -1,50 +1,298 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "============================================================"
|
||||
echo " EVENTHUB FULL API TEST SUITE"
|
||||
echo "============================================================"
|
||||
echo ""
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Проверяем, что сервер запущен
|
||||
if ! curl -s "http://localhost:8080/health" | grep -q "ok"; then
|
||||
echo "❌ Server is not running. Please start the server first."
|
||||
exit 1
|
||||
fi
|
||||
PROJECT_ROOT="$(cd "$SCRIPTS_DIR/../.." && pwd)"
|
||||
BASE_URL="http://localhost:8080"
|
||||
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
SKIPPED=0
|
||||
SERVER_STARTED=false
|
||||
SERVER_PID=""
|
||||
|
||||
run_test() {
|
||||
# ============================================================================
|
||||
# Вспомогательные функции
|
||||
# ============================================================================
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
||||
log_step() { echo -e "${CYAN}[STEP]${NC} $1"; }
|
||||
|
||||
# Очистка при выходе
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo "▶ Running $1..."
|
||||
if bash "$SCRIPTS_DIR/$1"; then
|
||||
((PASSED++))
|
||||
echo "✅ $1 PASSED"
|
||||
else
|
||||
((FAILED++))
|
||||
echo "❌ $1 FAILED"
|
||||
log_info "Cleaning up..."
|
||||
|
||||
if [ -n "$SERVER_PID" ] && kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
log_info "Stopping server (PID: $SERVER_PID)..."
|
||||
kill "$SERVER_PID" 2>/dev/null
|
||||
wait "$SERVER_PID" 2>/dev/null
|
||||
|
||||
# Убеждаемся, что все beam процессы остановлены
|
||||
pkill -f "beam.*eventhub" 2>/dev/null || true
|
||||
log_success "Server stopped"
|
||||
fi
|
||||
|
||||
# Удаляем временные файлы
|
||||
rm -f /tmp/eventhub_test_*.log 2>/dev/null
|
||||
}
|
||||
|
||||
# Обработчик сигналов
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
# Проверка порта
|
||||
check_port() {
|
||||
local port=$1
|
||||
if lsof -i ":$port" > /dev/null 2>&1 || netstat -tuln 2>/dev/null | grep -q ":$port "; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Ожидание запуска сервера
|
||||
wait_for_server() {
|
||||
local max_attempts=30
|
||||
local attempt=0
|
||||
|
||||
log_info "Waiting for server to start..."
|
||||
|
||||
while [ $attempt -lt $max_attempts ]; do
|
||||
if curl -s "$BASE_URL/health" | grep -q "ok"; then
|
||||
log_success "Server is ready (took $attempt seconds)"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
((attempt++))
|
||||
echo -n "."
|
||||
done
|
||||
echo ""
|
||||
|
||||
log_error "Server failed to start within $max_attempts seconds"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Запуск сервера
|
||||
start_server() {
|
||||
echo -e "${CYAN}[STEP]${NC} Starting EventHub server..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
if [ ! -f "rebar.config" ]; then
|
||||
echo -e "${RED}[ERROR]${NC} rebar.config not found in $(pwd)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} Project root: $(pwd)"
|
||||
|
||||
# Очищаем старые данные
|
||||
rm -rf Mnesia.* 2>/dev/null
|
||||
pkill -f "beam.*eventhub_test" 2>/dev/null || true
|
||||
sleep 1
|
||||
|
||||
# Компилируем
|
||||
echo -e "${BLUE}[INFO]${NC} Compiling..."
|
||||
rebar3 compile > /dev/null 2>&1
|
||||
|
||||
# Запускаем сервер через erl (более надёжно для фона)
|
||||
LOG_FILE="/tmp/eventhub_test_server.log"
|
||||
echo -e "${BLUE}[INFO]${NC} Starting server..."
|
||||
|
||||
# Запускаем в фоне с перенаправлением вывода
|
||||
rebar3 shell --sname eventhub_test </dev/null > "$LOG_FILE" 2>&1 &
|
||||
SERVER_PID=$!
|
||||
|
||||
# Даём процессу время запуститься
|
||||
sleep 3
|
||||
|
||||
# Проверяем, жив ли процесс
|
||||
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
echo -e "${RED}[ERROR]${NC} Server process died immediately"
|
||||
echo -e "${YELLOW}[INFO]${NC} Check log: $LOG_FILE"
|
||||
cat "$LOG_FILE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} Server PID: $SERVER_PID"
|
||||
|
||||
# Ждём готовности
|
||||
for i in {1..30}; do
|
||||
echo -n "."
|
||||
if curl -s "http://localhost:8080/health" 2>/dev/null | grep -q "ok"; then
|
||||
echo ""
|
||||
echo -e "${GREEN}[SUCCESS]${NC} Server ready at http://localhost:8080"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
echo ""
|
||||
echo -e "${RED}[ERROR]${NC} Server died during startup"
|
||||
echo -e "${YELLOW}[INFO]${NC} Last lines of log:"
|
||||
tail -30 "$LOG_FILE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo -e "${RED}[ERROR]${NC} Server failed to respond"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Остановка сервера
|
||||
stop_server() {
|
||||
if [ "$SERVER_STARTED" = true ] && [ -n "$SERVER_PID" ]; then
|
||||
log_step "Stopping EventHub server..."
|
||||
|
||||
# Останавливаем нашу ноду
|
||||
if kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
kill "$SERVER_PID" 2>/dev/null
|
||||
wait "$SERVER_PID" 2>/dev/null
|
||||
fi
|
||||
|
||||
# Останавливаем все связанные beam процессы
|
||||
pkill -f "beam.*eventhub_test" 2>/dev/null || true
|
||||
|
||||
SERVER_STARTED=false
|
||||
log_success "Server stopped"
|
||||
sleep 2
|
||||
fi
|
||||
}
|
||||
|
||||
run_test "test_auth_api.sh"
|
||||
run_test "test_calendar_api.sh"
|
||||
run_test "test_event_api.sh"
|
||||
run_test "test_booking_api.sh"
|
||||
# Проверка, запущен ли сервер
|
||||
is_server_running() {
|
||||
curl -s "$BASE_URL/health" | grep -q "ok"
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo " TEST SUMMARY"
|
||||
echo "============================================================"
|
||||
echo "Passed: $PASSED"
|
||||
echo "Failed: $FAILED"
|
||||
echo "============================================================"
|
||||
# Запуск одного тестового скрипта
|
||||
run_test_script() {
|
||||
local script_path=$1
|
||||
local script_name=$(basename "$script_path")
|
||||
|
||||
if [ $FAILED -eq 0 ]; then
|
||||
echo "🎉 ALL TESTS PASSED!"
|
||||
exit 0
|
||||
else
|
||||
echo "❌ SOME TESTS FAILED"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo -e "${CYAN}[RUNNING]${NC} $script_name"
|
||||
echo "============================================================"
|
||||
|
||||
# Даём скрипту права на выполнение
|
||||
chmod +x "$script_path" 2>/dev/null
|
||||
|
||||
# Запускаем тест
|
||||
if bash "$script_path"; then
|
||||
echo ""
|
||||
echo -e "${GREEN}[PASSED]${NC} $script_name"
|
||||
return 0
|
||||
else
|
||||
echo ""
|
||||
echo -e "${RED}[FAILED]${NC} $script_name"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Главная логика
|
||||
# ============================================================================
|
||||
main() {
|
||||
echo "============================================================"
|
||||
echo " EVENTHUB FULL API TEST SUITE"
|
||||
echo "============================================================"
|
||||
echo ""
|
||||
|
||||
# Проверяем, не запущен ли уже сервер
|
||||
if is_server_running; then
|
||||
log_warning "Server is already running on port 8080"
|
||||
read -p "Use existing server? [Y/n]: " USE_EXISTING
|
||||
if [[ "$USE_EXISTING" =~ ^[Nn] ]]; then
|
||||
log_error "Please stop the existing server first: make stop"
|
||||
exit 1
|
||||
fi
|
||||
log_info "Using existing server"
|
||||
else
|
||||
# Проверяем, свободен ли порт
|
||||
if check_port 8080; then
|
||||
log_error "Port 8080 is in use by another process"
|
||||
log_info "Please free the port or stop the other process"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Запускаем сервер
|
||||
if ! start_server; then
|
||||
log_error "Failed to start server"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "Server is ready at $BASE_URL"
|
||||
|
||||
# Получаем список всех тестовых скриптов
|
||||
TEST_SCRIPTS=$(find "$SCRIPTS_DIR" -maxdepth 1 -name "test_*.sh" ! -name "test_all.sh" ! -name "test_runner.sh" -type f | sort)
|
||||
|
||||
if [ -z "$TEST_SCRIPTS" ]; then
|
||||
log_warning "No test scripts found in $SCRIPTS_DIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "Found test scripts:"
|
||||
for script in $TEST_SCRIPTS; do
|
||||
echo " - $(basename "$script")"
|
||||
done
|
||||
|
||||
# Счётчики времени
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
# Запускаем все тесты
|
||||
for script in $TEST_SCRIPTS; do
|
||||
if run_test_script "$script"; then
|
||||
((PASSED++))
|
||||
else
|
||||
((FAILED++))
|
||||
fi
|
||||
done
|
||||
|
||||
END_TIME=$(date +%s)
|
||||
DURATION=$((END_TIME - START_TIME))
|
||||
|
||||
# Останавливаем сервер, если мы его запускали
|
||||
if [ "$SERVER_STARTED" = true ]; then
|
||||
echo ""
|
||||
stop_server
|
||||
fi
|
||||
|
||||
# Итоговый отчёт
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo " TEST SUMMARY"
|
||||
echo "============================================================"
|
||||
echo -e "Total scripts: $((PASSED + FAILED))"
|
||||
echo -e "${GREEN}Passed: $PASSED${NC}"
|
||||
echo -e "${RED}Failed: $FAILED${NC}"
|
||||
if [ $SKIPPED -gt 0 ]; then
|
||||
echo -e "${YELLOW}Skipped: $SKIPPED${NC}"
|
||||
fi
|
||||
echo -e "Duration: ${DURATION}s"
|
||||
echo "============================================================"
|
||||
|
||||
if [ $FAILED -eq 0 ]; then
|
||||
echo ""
|
||||
echo -e "${GREEN}🎉 ALL TESTS PASSED!${NC}"
|
||||
return 0
|
||||
else
|
||||
echo ""
|
||||
echo -e "${RED}❌ SOME TESTS FAILED${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Запуск
|
||||
main "$@"
|
||||
exit $?
|
||||
228
test/scripts/test_runner.sh
Normal file
228
test/scripts/test_runner.sh
Normal file
@@ -0,0 +1,228 @@
|
||||
#!/bin/bash
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPTS_DIR/../.." && pwd)"
|
||||
BASE_URL="http://localhost:8080"
|
||||
|
||||
SERVER_STARTED=false
|
||||
SERVER_PID=""
|
||||
|
||||
# ============================================================================
|
||||
# Функции
|
||||
# ============================================================================
|
||||
cleanup() {
|
||||
if [ "$SERVER_STARTED" = true ] && [ -n "$SERVER_PID" ]; then
|
||||
echo ""
|
||||
echo -e "${BLUE}[INFO]${NC} Stopping server..."
|
||||
kill "$SERVER_PID" 2>/dev/null
|
||||
wait "$SERVER_PID" 2>/dev/null
|
||||
pkill -f "beam.*eventhub_test" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [options] [pattern]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h, --help Show this help"
|
||||
echo " -l, --list List available test scripts"
|
||||
echo " -v, --verbose Verbose output"
|
||||
echo " -s, --server Use existing server (don't start/stop)"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 Run all tests"
|
||||
echo " $0 auth Run tests matching 'auth'"
|
||||
echo " $0 booking Run tests matching 'booking'"
|
||||
echo " $0 -l List all test scripts"
|
||||
echo " $0 -s Use already running server"
|
||||
}
|
||||
|
||||
list_scripts() {
|
||||
echo "Available test scripts:"
|
||||
find "$SCRIPTS_DIR" -maxdepth 1 -name "test_*.sh" ! -name "test_all.sh" ! -name "test_runner.sh" -type f | sort | while read script; do
|
||||
name=$(basename "$script")
|
||||
echo " - $name"
|
||||
done
|
||||
}
|
||||
|
||||
start_server() {
|
||||
echo -e "${CYAN}[STEP]${NC} Starting EventHub server..."
|
||||
|
||||
# Переходим в корень проекта
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Проверяем, что мы в правильной директории
|
||||
if [ ! -f "rebar.config" ]; then
|
||||
echo -e "${RED}[ERROR]${NC} rebar.config not found in $(pwd)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} Project root: $(pwd)"
|
||||
|
||||
# Компилируем если нужно
|
||||
if [ ! -d "_build" ]; then
|
||||
echo -e "${BLUE}[INFO]${NC} Compiling project..."
|
||||
rebar3 compile
|
||||
fi
|
||||
|
||||
# Запускаем сервер
|
||||
LOG_FILE="/tmp/eventhub_test_server.log"
|
||||
echo -e "${BLUE}[INFO]${NC} Starting server, log: $LOG_FILE"
|
||||
|
||||
rebar3 shell --sname eventhub_test > "$LOG_FILE" 2>&1 &
|
||||
SERVER_PID=$!
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} Server PID: $SERVER_PID"
|
||||
|
||||
# Ждём готовности
|
||||
for i in {1..30}; do
|
||||
echo -n "."
|
||||
if curl -s "http://localhost:8080/health" 2>/dev/null | grep -q "ok"; then
|
||||
echo ""
|
||||
echo -e "${GREEN}[SUCCESS]${NC} Server ready (took $i seconds)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Проверяем, не умер ли процесс
|
||||
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
echo ""
|
||||
echo -e "${RED}[ERROR]${NC} Server process died"
|
||||
echo -e "${YELLOW}[INFO]${NC} Last 20 lines of log:"
|
||||
tail -20 "$LOG_FILE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo -e "${RED}[ERROR]${NC} Server failed to start within 30 seconds"
|
||||
echo -e "${YELLOW}[INFO]${NC} Last 20 lines of log:"
|
||||
tail -20 "$LOG_FILE"
|
||||
return 1
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Парсинг аргументов
|
||||
# ============================================================================
|
||||
VERBOSE=false
|
||||
USE_EXISTING=false
|
||||
PATTERN=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-l|--list)
|
||||
list_scripts
|
||||
exit 0
|
||||
;;
|
||||
-v|--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
-s|--server)
|
||||
USE_EXISTING=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
PATTERN="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ============================================================================
|
||||
# Главная логика
|
||||
# ============================================================================
|
||||
echo "============================================================"
|
||||
echo " EVENTHUB TEST RUNNER"
|
||||
echo "============================================================"
|
||||
echo ""
|
||||
|
||||
if [ "$USE_EXISTING" = false ]; then
|
||||
if ! start_server; then
|
||||
exit 1
|
||||
fi
|
||||
SERVER_STARTED=true
|
||||
else
|
||||
if ! curl -s "$BASE_URL/health" | grep -q "ok"; then
|
||||
echo -e "${RED}[ERROR]${NC} Server is not running"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}[SUCCESS]${NC} Using existing server"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Находим тесты
|
||||
if [ -n "$PATTERN" ]; then
|
||||
TEST_SCRIPTS=$(find "$SCRIPTS_DIR" -maxdepth 1 -name "test_*${PATTERN}*.sh" ! -name "test_all.sh" ! -name "test_runner.sh" -type f | sort)
|
||||
else
|
||||
TEST_SCRIPTS=$(find "$SCRIPTS_DIR" -maxdepth 1 -name "test_*.sh" ! -name "test_all.sh" ! -name "test_runner.sh" -type f | sort)
|
||||
fi
|
||||
|
||||
if [ -z "$TEST_SCRIPTS" ]; then
|
||||
echo -e "${YELLOW}[WARNING]${NC} No test scripts found"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} Running tests:"
|
||||
for script in $TEST_SCRIPTS; do
|
||||
echo " - $(basename "$script")"
|
||||
done
|
||||
echo ""
|
||||
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
|
||||
for script in $TEST_SCRIPTS; do
|
||||
script_name=$(basename "$script")
|
||||
echo "============================================================"
|
||||
echo -e "${CYAN}[RUNNING]${NC} $script_name"
|
||||
echo "============================================================"
|
||||
|
||||
if $VERBOSE; then
|
||||
bash "$script"
|
||||
EXIT_CODE=$?
|
||||
else
|
||||
bash "$script"
|
||||
EXIT_CODE=$?
|
||||
fi
|
||||
|
||||
if [ $EXIT_CODE -eq 0 ]; then
|
||||
echo -e "${GREEN}[PASSED]${NC} $script_name"
|
||||
((PASSED++))
|
||||
else
|
||||
echo -e "${RED}[FAILED]${NC} $script_name"
|
||||
((FAILED++))
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "============================================================"
|
||||
echo " TEST SUMMARY"
|
||||
echo "============================================================"
|
||||
echo -e "Scripts run: $((PASSED + FAILED))"
|
||||
echo -e "${GREEN}Passed: $PASSED${NC}"
|
||||
echo -e "${RED}Failed: $FAILED${NC}"
|
||||
echo "============================================================"
|
||||
|
||||
if [ $FAILED -eq 0 ]; then
|
||||
echo -e "${GREEN}🎉 ALL TESTS PASSED!${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}❌ SOME TESTS FAILED${NC}"
|
||||
exit 1
|
||||
fi
|
||||
393
test/scripts/test_search_api.sh
Normal file
393
test/scripts/test_search_api.sh
Normal file
@@ -0,0 +1,393 @@
|
||||
#!/bin/bash
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
BASE_URL="http://localhost:8080"
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
||||
|
||||
extract_json() {
|
||||
echo "$1" | grep -o "\"$2\":\"[^\"]*\"" | head -1 | sed "s/\"$2\":\"//;s/\"$//"
|
||||
}
|
||||
|
||||
http_post() {
|
||||
local url=$1; local data=$2; local token=$3
|
||||
if [ -n "$token" ]; then
|
||||
curl -s -X POST "$url" -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d "$data"
|
||||
else
|
||||
curl -s -X POST "$url" -H "Content-Type: application/json" -d "$data"
|
||||
fi
|
||||
}
|
||||
|
||||
http_get() {
|
||||
local url=$1; local token=$2
|
||||
if [ -n "$token" ]; then
|
||||
curl -s -X GET "$url" -H "Authorization: Bearer $token"
|
||||
else
|
||||
curl -s -X GET "$url"
|
||||
fi
|
||||
}
|
||||
|
||||
http_put() {
|
||||
local url=$1; local data=$2; local token=$3
|
||||
curl -s -X PUT "$url" -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d "$data"
|
||||
}
|
||||
|
||||
url_encode() {
|
||||
echo -n "$1" | sed 's/ /%20/g;s/,/%2C/g'
|
||||
}
|
||||
|
||||
echo "============================================================"
|
||||
echo " EVENTHUB SEARCH API TEST SCRIPT"
|
||||
echo "============================================================"
|
||||
echo ""
|
||||
|
||||
log_info "Checking if server is running..."
|
||||
if ! curl -s "$BASE_URL/health" | grep -q "ok"; then
|
||||
log_error "Server is not running"
|
||||
exit 1
|
||||
fi
|
||||
log_success "Server is running"
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "STEP 1: Create test users"
|
||||
log_info "============================================================"
|
||||
|
||||
OWNER_EMAIL="search_owner_$(date +%s)@example.com"
|
||||
OWNER_PASSWORD="owner123"
|
||||
|
||||
log_info "Creating calendar owner..."
|
||||
response=$(http_post "$BASE_URL/v1/register" "{\"email\":\"$OWNER_EMAIL\",\"password\":\"$OWNER_PASSWORD\"}" "")
|
||||
OWNER_TOKEN=$(extract_json "$response" "token")
|
||||
OWNER_ID=$(extract_json "$response" "id")
|
||||
|
||||
if [ -z "$OWNER_TOKEN" ]; then
|
||||
log_error "Failed to create owner"
|
||||
exit 1
|
||||
fi
|
||||
log_success "Owner created: $OWNER_EMAIL"
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "STEP 2: Create calendar with tags"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Creating calendar..."
|
||||
response=$(http_post "$BASE_URL/v1/calendars" \
|
||||
"{\"title\":\"Tech Events Calendar\",\"description\":\"Calendar for technology events and workshops\",\"tags\":[\"tech\",\"programming\",\"workshop\"]}" "$OWNER_TOKEN")
|
||||
CALENDAR_ID=$(extract_json "$response" "id")
|
||||
log_success "Calendar created with tags: $CALENDAR_ID"
|
||||
|
||||
# Добавляем теги через обновление
|
||||
http_put "$BASE_URL/v1/calendars/$CALENDAR_ID" "{\"tags\":[\"tech\",\"programming\",\"workshop\"]}" "$OWNER_TOKEN" > /dev/null
|
||||
log_success "Calendar created with tags: $CALENDAR_ID"
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "STEP 3: Create events with different properties"
|
||||
log_info "============================================================"
|
||||
|
||||
# Функция для создания события
|
||||
create_event() {
|
||||
local title=$1
|
||||
local description=$2
|
||||
local start_time=$3
|
||||
local tags=$4
|
||||
local lat=$5
|
||||
local lon=$6
|
||||
local address=$7
|
||||
|
||||
local location_json="null"
|
||||
if [ -n "$lat" ] && [ -n "$lon" ]; then
|
||||
location_json="{\"address\":\"$address\",\"lat\":$lat,\"lon\":$lon}"
|
||||
fi
|
||||
|
||||
local tags_json="[]"
|
||||
if [ -n "$tags" ]; then
|
||||
tags_json="$tags"
|
||||
fi
|
||||
|
||||
local data="{\"title\":\"$title\",\"description\":\"$description\",\"start_time\":\"$start_time\",\"duration\":60,\"tags\":$tags_json"
|
||||
if [ "$location_json" != "null" ]; then
|
||||
data="$data,\"location\":$location_json"
|
||||
fi
|
||||
data="$data}"
|
||||
|
||||
response=$(http_post "$BASE_URL/v1/calendars/$CALENDAR_ID/events" "$data" "$OWNER_TOKEN")
|
||||
local event_id=$(extract_json "$response" "id")
|
||||
|
||||
echo "$event_id"
|
||||
}
|
||||
|
||||
log_info "Creating Python Workshop event..."
|
||||
WORKSHOP_ID=$(create_event "Python Workshop" "Learn Python programming basics" "2026-06-01T10:00:00Z" \
|
||||
"[\"python\",\"workshop\",\"programming\"]" "55.7558" "37.6173" "Moscow, Russia")
|
||||
log_success "Created: $WORKSHOP_ID"
|
||||
|
||||
log_info "Creating JavaScript Conference event..."
|
||||
JS_ID=$(create_event "JavaScript Conference" "Annual JS conference for developers" "2026-06-15T09:00:00Z" \
|
||||
"[\"javascript\",\"conference\",\"web\"]" "55.7558" "37.6173" "Moscow, Russia")
|
||||
log_success "Created: $JS_ID"
|
||||
|
||||
log_info "Creating Yoga Class event (no tags)..."
|
||||
YOGA_ID=$(create_event "Yoga Class" "Morning yoga session" "2026-06-10T08:00:00Z" \
|
||||
"" "" "" "")
|
||||
log_success "Created: $YOGA_ID"
|
||||
|
||||
log_info "Creating Tech Meetup in another city..."
|
||||
MEETUP_ID=$(create_event "Tech Meetup" "Networking for tech professionals" "2026-06-20T18:00:00Z" \
|
||||
"[\"networking\",\"tech\"]" "59.9343" "30.3351" "Saint Petersburg, Russia")
|
||||
log_success "Created: $MEETUP_ID"
|
||||
|
||||
log_info "Creating past event..."
|
||||
PAST_ID=$(create_event "Past Event" "This event already happened" "2020-01-01T10:00:00Z" \
|
||||
"[\"past\"]" "" "" "")
|
||||
log_success "Created: $PAST_ID"
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 1: Search by text query"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Searching for 'Python'..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&q=Python" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "Python Workshop"; then
|
||||
log_success "Found Python Workshop"
|
||||
else
|
||||
log_error "Python Workshop not found"
|
||||
fi
|
||||
|
||||
log_info "Searching for 'conference'..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&q=conference" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "JavaScript Conference"; then
|
||||
log_success "Found JavaScript Conference"
|
||||
else
|
||||
log_error "JavaScript Conference not found"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 2: Search by tags"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Searching for events with tag 'python'..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&tags=python" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "Python Workshop"; then
|
||||
log_success "Found Python Workshop by tag"
|
||||
else
|
||||
log_error "Python Workshop not found by tag"
|
||||
fi
|
||||
|
||||
log_info "Searching for multiple tags 'tech,workshop'..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&tags=tech,workshop" "$OWNER_TOKEN")
|
||||
log_success "Multiple tag search completed"
|
||||
|
||||
log_info "Searching for tag 'yoga' (should be empty)..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&tags=yoga" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q '"total":0'; then
|
||||
log_success "Yoga tag correctly returned no results (no tags on event)"
|
||||
else
|
||||
log_warning "Yoga event has no tags, but might appear in results"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 3: Search by date range"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Searching events in June 2026..."
|
||||
FROM="2026-06-01T00:00:00Z"
|
||||
TO="2026-06-30T23:59:59Z"
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&from=$FROM&to=$TO" "$OWNER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "Python Workshop"; then
|
||||
log_success "Found June events"
|
||||
else
|
||||
log_error "June events not found"
|
||||
fi
|
||||
|
||||
log_info "Searching past events only..."
|
||||
FROM="2019-01-01T00:00:00Z"
|
||||
TO="2021-01-01T00:00:00Z"
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&from=$FROM&to=$TO" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "Past Event"; then
|
||||
log_success "Found past event"
|
||||
else
|
||||
log_error "Past event not found"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 4: Geo-location search"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Searching events within 5km of Moscow center..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&lat=55.7558&lon=37.6173&radius=5" "$OWNER_TOKEN")
|
||||
|
||||
if echo "$response" | grep -q "Python Workshop"; then
|
||||
log_success "Found Moscow events"
|
||||
else
|
||||
log_error "Moscow events not found"
|
||||
fi
|
||||
|
||||
log_info "Searching events within 1km of Moscow (should find fewer)..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&lat=55.7558&lon=37.6173&radius=1" "$OWNER_TOKEN")
|
||||
log_success "Radius search completed"
|
||||
|
||||
log_info "Searching events in Saint Petersburg..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&lat=59.9343&lon=30.3351&radius=10" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "Tech Meetup"; then
|
||||
log_success "Found Saint Petersburg event"
|
||||
else
|
||||
log_error "Saint Petersburg event not found"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 5: Combined search"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Search: text 'Python' + tag 'workshop'..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&q=Python&tags=workshop" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "Python Workshop"; then
|
||||
log_success "Combined text+tag search successful"
|
||||
else
|
||||
log_error "Combined search failed"
|
||||
fi
|
||||
|
||||
log_info "Search: tag 'javascript' + date range..."
|
||||
FROM="2026-06-01T00:00:00Z"
|
||||
TO="2026-06-30T23:59:59Z"
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&tags=javascript&from=$FROM&to=$TO" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "JavaScript Conference"; then
|
||||
log_success "Combined tag+date search successful"
|
||||
else
|
||||
log_error "Combined search failed"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 6: Pagination"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Search with limit=2..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&limit=2" "$OWNER_TOKEN")
|
||||
COUNT=$(echo "$response" | grep -o "\"id\"" | wc -l)
|
||||
if [ "$COUNT" -le 2 ]; then
|
||||
log_success "Pagination limit works (got $COUNT results)"
|
||||
else
|
||||
log_error "Pagination limit failed (got $COUNT results)"
|
||||
fi
|
||||
|
||||
log_info "Search with offset=2..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&limit=2&offset=2" "$OWNER_TOKEN")
|
||||
log_success "Pagination offset works"
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 7: Sorting"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Sort by start_time ascending..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&sort=start_time&order=asc" "$OWNER_TOKEN")
|
||||
log_success "Sort ascending completed"
|
||||
|
||||
log_info "Sort by start_time descending..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&sort=start_time&order=desc" "$OWNER_TOKEN")
|
||||
log_success "Sort descending completed"
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 8: Calendar search"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Searching calendars by text..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=calendar&q=Tech" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "Tech Events Calendar"; then
|
||||
log_success "Found calendar by text"
|
||||
else
|
||||
log_error "Calendar not found by text"
|
||||
fi
|
||||
|
||||
log_info "Searching calendars by tag..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=calendar&tags=tech" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "Tech Events Calendar"; then
|
||||
log_success "Found calendar by tag"
|
||||
else
|
||||
log_error "Calendar not found by tag"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 9: Search all (events + calendars)"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Searching all (no type specified)..."
|
||||
response=$(http_get "$BASE_URL/v1/search?q=Tech" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q "events" && echo "$response" | grep -q "calendars"; then
|
||||
log_success "All search returned both events and calendars"
|
||||
else
|
||||
log_warning "All search may not have returned both types"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 10: Empty search results"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Searching for non-existent text..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&q=nonexistenttext12345" "$OWNER_TOKEN")
|
||||
if echo "$response" | grep -q '"total":0'; then
|
||||
log_success "Empty search handled correctly"
|
||||
else
|
||||
log_error "Empty search not handled correctly"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_info "============================================================"
|
||||
log_info "TEST 11: Commercial calendar visibility"
|
||||
log_info "============================================================"
|
||||
|
||||
log_info "Creating commercial calendar..."
|
||||
response=$(http_post "$BASE_URL/v1/calendars" \
|
||||
"{\"title\":\"Public Commercial Calendar\",\"type\":\"commercial\"}" "$OWNER_TOKEN")
|
||||
COMMERCIAL_ID=$(extract_json "$response" "id")
|
||||
log_success "Commercial calendar created: $COMMERCIAL_ID"
|
||||
|
||||
log_info "Creating event in commercial calendar..."
|
||||
response=$(http_post "$BASE_URL/v1/calendars/$COMMERCIAL_ID/events" \
|
||||
"{\"title\":\"Public Event\",\"start_time\":\"2026-06-01T10:00:00Z\",\"duration\":60}" "$OWNER_TOKEN")
|
||||
log_success "Public event created"
|
||||
|
||||
log_info "Creating another user to test visibility..."
|
||||
OTHER_EMAIL="search_other_$(date +%s)@example.com"
|
||||
response=$(http_post "$BASE_URL/v1/register" "{\"email\":\"$OTHER_EMAIL\",\"password\":\"test123\"}" "")
|
||||
OTHER_TOKEN=$(extract_json "$response" "token")
|
||||
|
||||
log_info "Other user searching for public event..."
|
||||
response=$(http_get "$BASE_URL/v1/search?type=event&q=Public" "$OTHER_TOKEN")
|
||||
if echo "$response" | grep -q "Public Event"; then
|
||||
log_success "Other user can see public event in commercial calendar"
|
||||
else
|
||||
log_error "Other user cannot see public event"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
log_success "SEARCH API TESTS COMPLETED!"
|
||||
echo "============================================================"
|
||||
echo ""
|
||||
echo "Summary of created resources:"
|
||||
echo " Owner: $OWNER_EMAIL"
|
||||
echo " Calendar: $CALENDAR_ID"
|
||||
echo " Commercial Calendar: $COMMERCIAL_ID"
|
||||
echo " Events created: 5"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user