Files
EventHubBack/test/api/admins/admin_tickets_tests.erl

152 lines
6.5 KiB
Erlang
Raw Permalink 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.
%%%-------------------------------------------------------------------
%%% @doc Тесты административного API для управления тикетами.
%%%
%%% Покрывает эндпоинты:
%%% GET /v1/admin/tickets
%%% GET /v1/admin/tickets/:id
%%% PUT /v1/admin/tickets/:id
%%% DELETE /v1/admin/tickets/:id
%%%
%%% Проверяет:
%%% - получение списка тикетов
%%% - получение тикета по ID
%%% - разрешение (resolve) и закрытие (close) тикета
%%% - назначение исполнителя
%%% - удаление тикета
%%% - фильтрацию по статусу
%%% - пагинацию
%%% @end
%%%-------------------------------------------------------------------
-module(admin_tickets_tests).
-include_lib("eunit/include/eunit.hrl").
-export([test/0]).
%%%===================================================================
%%% Главная тестовая функция
%%%===================================================================
-spec test() -> ok.
test() ->
ct:pal("=== Admin Tickets Tests ==="),
Token = api_test_runner:get_admin_token(),
UserToken = api_test_runner:get_user_token(),
% Создаём два тикета для разных проверок
Ticket1 = api_test_runner:client_post(<<"/v1/tickets">>, UserToken,
#{<<"error_message">> => <<"Test bug">>, <<"stacktrace">> => <<"trace">>}),
#{<<"id">> := Ticket1Id} = Ticket1,
Ticket2 = api_test_runner:client_post(<<"/v1/tickets">>, UserToken,
#{<<"error_message">> => <<"Another bug">>, <<"stacktrace">> => <<"trace2">>}),
#{<<"id">> := Ticket2Id} = Ticket2,
test_list_tickets(Token),
test_get_ticket(Token, Ticket1Id),
test_resolve_ticket(Token, Ticket1Id),
test_close_ticket(Token, Ticket1Id),
test_assign_ticket(Token, Ticket1Id),
test_filter_tickets(Token),
test_ticket_pagination(Token, Ticket2Id),
test_delete_ticket(Token, Ticket1Id),
test_delete_ticket(Token, Ticket2Id),
ct:pal("=== All admin tickets tests passed ==="),
ok.
%%%===================================================================
%%% Тестовые функции
%%%===================================================================
%% @doc GET /v1/admin/tickets проверяет получение списка тикетов.
%% Убеждается, что список не пуст.
-spec test_list_tickets(binary()) -> ok.
test_list_tickets(Token) ->
ct:pal(" TEST: List all tickets"),
Tickets = api_test_runner:admin_get(<<"/v1/admin/tickets">>, Token),
?assert(is_list(Tickets)),
?assert(length(Tickets) >= 1),
ct:pal(" OK: ~p tickets", [length(Tickets)]).
%% @doc GET /v1/admin/tickets/:id проверяет получение тикета по ID.
%% Убеждается, что статус нового тикета open.
-spec test_get_ticket(binary(), binary()) -> ok.
test_get_ticket(Token, TicketId) ->
ct:pal(" TEST: Get ticket by ID"),
Path = <<"/v1/admin/tickets/", TicketId/binary>>,
Ticket = api_test_runner:admin_get(Path, Token),
?assertEqual(TicketId, maps:get(<<"id">>, Ticket)),
?assertEqual(<<"open">>, maps:get(<<"status">>, Ticket)),
ct:pal(" OK").
%% @doc PUT /v1/admin/tickets/:id разрешение тикета (resolve).
%% Ожидается статус resolved после успешного выполнения.
-spec test_resolve_ticket(binary(), binary()) -> ok.
test_resolve_ticket(Token, TicketId) ->
ct:pal(" TEST: Resolve ticket"),
Path = <<"/v1/admin/tickets/", TicketId/binary>>,
Updated = api_test_runner:admin_put(Path, Token, #{
<<"status">> => <<"resolved">>,
<<"resolution_note">> => <<"Fixed">>
}),
?assertEqual(<<"resolved">>, maps:get(<<"status">>, Updated)),
?assertEqual(<<"Fixed">>, maps:get(<<"resolution_note">>, Updated)),
ct:pal(" OK").
%% @doc PUT /v1/admin/tickets/:id закрытие тикета (close).
-spec test_close_ticket(binary(), binary()) -> ok.
test_close_ticket(Token, TicketId) ->
ct:pal(" TEST: Close ticket"),
Path = <<"/v1/admin/tickets/", TicketId/binary>>,
Updated = api_test_runner:admin_put(Path, Token, #{<<"status">> => <<"closed">>}),
?assertEqual(<<"closed">>, maps:get(<<"status">>, Updated)),
ct:pal(" OK").
%% @doc PUT /v1/admin/tickets/:id назначение исполнителя.
-spec test_assign_ticket(binary(), binary()) -> ok.
test_assign_ticket(Token, TicketId) ->
ct:pal(" TEST: Assign ticket"),
Me = api_test_runner:admin_get(<<"/v1/admin/me">>, Token),
AdminId = maps:get(<<"id">>, Me),
Path = <<"/v1/admin/tickets/", TicketId/binary>>,
Updated = api_test_runner:admin_put(Path, Token, #{<<"assigned_to">> => AdminId}),
?assertEqual(AdminId, maps:get(<<"assigned_to">>, Updated)),
ct:pal(" OK").
%% @doc DELETE /v1/admin/tickets/:id удаление тикета.
-spec test_delete_ticket(binary(), binary()) -> ok.
test_delete_ticket(Token, TicketId) ->
ct:pal(" TEST: Delete ticket"),
Path = <<"/v1/admin/tickets/", TicketId/binary>>,
Deleted = api_test_runner:admin_delete(Path, Token),
?assertEqual(<<"deleted">>, maps:get(<<"status">>, Deleted)),
ct:pal(" OK").
%% @doc GET /v1/admin/tickets?status=... проверяет фильтрацию по статусу open.
%% Использует второй тикет, который всё ещё open.
-spec test_filter_tickets(binary()) -> ok.
test_filter_tickets(Token) ->
ct:pal(" TEST: Filter tickets by status=open"),
Tickets = api_test_runner:admin_get(<<"/v1/admin/tickets?status=open">>, Token),
?assert(is_list(Tickets)),
?assert(length(Tickets) >= 1),
[?assertEqual(<<"open">>, maps:get(<<"status">>, T)) || T <- Tickets],
ct:pal(" OK: ~p open tickets", [length(Tickets)]).
%% @doc GET /v1/admin/tickets?limit=...&offset=... проверяет пагинацию.
%% Использует второй тикет как гарантированно существующий.
-spec test_ticket_pagination(binary(), binary()) -> ok.
test_ticket_pagination(Token, _TicketId) ->
ct:pal(" TEST: Ticket pagination"),
Page1 = api_test_runner:admin_get(<<"/v1/admin/tickets?limit=1&offset=0">>, Token),
?assert(length(Page1) >= 1),
Page2 = api_test_runner:admin_get(<<"/v1/admin/tickets?limit=1&offset=1">>, Token),
?assert(length(Page2) >= 0),
case {Page1, Page2} of
{[First|_], [Second|_]} ->
Id1 = maps:get(<<"id">>, First),
Id2 = maps:get(<<"id">>, Second),
?assertNotEqual(Id1, Id2);
_ -> ok
end,
ct:pal(" OK").