-module(api_admin_tests). -export([test/0]). test() -> io:format("Testing admin panel API...~n"), AdminURL = "http://localhost:8445", % Получаем admin-токен через test runner (уже проверенный) AdminToken = api_test_runner:get_admin_token(), %% TEST 1: Admin healthcheck (public) io:format(" TEST 1: Admin healthcheck... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/health", []}, [], []), io:format("OK~n"), %% TEST 2: Admin login (дополнительная проверка) io:format(" TEST 2: Admin login (attempt)... "), LoginBody = jsx:encode(#{<<"email">> => <<"global_admin@test.com">>, <<"password">> => <<"admin123">>}), case httpc:request(post, {AdminURL ++ "/v1/admin/login", [], "application/json", LoginBody}, [], []) of {ok, {{_, 200, _}, _, _}} -> io:format("OK (logged in)~n"); _ -> io:format("SKIPPED (credentials not found, using runner token)~n") end, %% TEST 3: Admin stats io:format(" TEST 3: Admin stats... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/stats", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 4: List users io:format(" TEST 4: List users... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/users", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 5: Get user by ID io:format(" TEST 5: Get user by ID... "), UserId = api_test_runner:get_user_id(), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/users/" ++ binary_to_list(UserId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 6: List reports io:format(" TEST 6: List reports... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/reports", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 7: List banned words io:format(" TEST 7: List banned words... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/banned-words", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 8: Add banned word io:format(" TEST 8: Add banned word... "), BannedWordBody = jsx:encode(#{<<"word">> => <<"test_banned_word">>}), {ok, {{_, 201, _}, _, _}} = httpc:request(post, {AdminURL ++ "/v1/admin/banned-words", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}], "application/json", BannedWordBody}, [], []), io:format("OK~n"), %% TEST 9: Delete banned word io:format(" TEST 9: Delete banned word... "), {ok, {{_, 200, _}, _, _}} = httpc:request(delete, {AdminURL ++ "/v1/admin/banned-words/test_banned_word", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 10: List tickets io:format(" TEST 10: List tickets... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/tickets", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 11: Create ticket io:format(" TEST 11: Create ticket... "), TicketBody = jsx:encode(#{<<"error_message">> => <<"Test error">>, <<"stacktrace">> => <<"trace">>}), {ok, {{_, 201, _}, _, TicketResp}} = httpc:request(post, {AdminURL ++ "/v1/admin/tickets", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}], "application/json", TicketBody}, [], []), #{<<"id">> := TicketId} = jsx:decode(list_to_binary(TicketResp), [return_maps]), io:format("OK~n"), %% TEST 12: Get ticket by ID io:format(" TEST 12: Get ticket by ID... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/tickets/" ++ binary_to_list(TicketId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 13: Update ticket io:format(" TEST 13: Update ticket... "), UpdateTicketBody = jsx:encode(#{<<"status">> => <<"closed">>}), {ok, {{_, 200, _}, _, _}} = httpc:request(put, {AdminURL ++ "/v1/admin/tickets/" ++ binary_to_list(TicketId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}], "application/json", UpdateTicketBody}, [], []), io:format("OK~n"), %% TEST 14: Delete ticket io:format(" TEST 14: Delete ticket... "), {ok, {{_, 200, _}, _, _}} = httpc:request(delete, {AdminURL ++ "/v1/admin/tickets/" ++ binary_to_list(TicketId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 15: Ticket stats io:format(" TEST 15: Ticket stats... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/tickets/stats", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 16: List subscriptions io:format(" TEST 16: List subscriptions... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/subscriptions", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 17: Create subscription io:format(" TEST 17: Create subscription... "), SubBody = jsx:encode(#{<<"user_id">> => UserId, <<"plan">> => <<"monthly">>}), {ok, {{_, 201, _}, _, SubResp}} = httpc:request(post, {AdminURL ++ "/v1/admin/subscriptions", [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}], "application/json", SubBody}, [], []), #{<<"id">> := SubId} = jsx:decode(list_to_binary(SubResp), [return_maps]), io:format("OK~n"), %% TEST 18: Get subscription by ID io:format(" TEST 18: Get subscription by ID... "), {ok, {{_, 200, _}, _, _}} = httpc:request(get, {AdminURL ++ "/v1/admin/subscriptions/" ++ binary_to_list(SubId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 19: Update subscription io:format(" TEST 19: Update subscription... "), UpdateSubBody = jsx:encode(#{<<"status">> => <<"cancelled">>}), {ok, {{_, 200, _}, _, _}} = httpc:request(put, {AdminURL ++ "/v1/admin/subscriptions/" ++ binary_to_list(SubId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}], "application/json", UpdateSubBody}, [], []), io:format("OK~n"), %% TEST 20: Delete subscription io:format(" TEST 20: Delete subscription... "), {ok, {{_, 200, _}, _, _}} = httpc:request(delete, {AdminURL ++ "/v1/admin/subscriptions/" ++ binary_to_list(SubId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}]}, [], []), io:format("OK~n"), %% TEST 21: Moderation - block user io:format(" TEST 21: Moderation - block user... "), ModBody = jsx:encode(#{<<"action">> => <<"block">>}), {ok, {{_, 200, _}, _, _}} = httpc:request(put, {AdminURL ++ "/v1/admin/user/" ++ binary_to_list(UserId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}], "application/json", ModBody}, [], []), io:format("OK~n"), %% TEST 22: Moderation - unblock user io:format(" TEST 22: Moderation - unblock user... "), UnblockBody = jsx:encode(#{<<"action">> => <<"unblock">>}), {ok, {{_, 200, _}, _, _}} = httpc:request(put, {AdminURL ++ "/v1/admin/user/" ++ binary_to_list(UserId), [{"Authorization", "Bearer " ++ binary_to_list(AdminToken)}], "application/json", UnblockBody}, [], []), io:format("OK~n"), io:format("~n✅ Admin API tests passed!~n"), {?MODULE, ok}.