Files
EventHubBack/test/unit/admin_handler_tickets_tests.erl

231 lines
9.9 KiB
Erlang
Raw 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.
-module(admin_handler_tickets_tests).
-include_lib("eunit/include/eunit.hrl").
-include("records.hrl").
setup() ->
ok = meck:new(cowboy_req, [non_strict]),
ok = meck:new(handler_auth, [non_strict]),
ok = meck:new(core_user, [non_strict]),
ok = meck:new(core_ticket, [non_strict]),
ok = meck:expect(cowboy_req, reply,
fun(Code, Headers, Body, Req) ->
put(test_reply, {Code, Headers, Body, Req})
end),
ok.
cleanup(_) ->
meck:unload(core_ticket),
meck:unload(core_user),
meck:unload(handler_auth),
meck:unload(cowboy_req).
admin_tickets_test_() ->
{setup, fun setup/0, fun cleanup/1, [
{"GET /admin/tickets success", fun test_list/0},
{"GET /admin/tickets forbidden", fun test_list_forbidden/0},
{"POST /admin/tickets success", fun test_create/0},
{"POST /admin/tickets missing error_message", fun test_create_missing/0},
{"GET /admin/tickets/:id success", fun test_get/0},
{"GET /admin/tickets/:id not found", fun test_get_not_found/0},
{"PUT /admin/tickets/:id success", fun test_update/0},
{"PUT /admin/tickets/:id not found", fun test_update_not_found/0},
{"DELETE /admin/tickets/:id success", fun test_delete/0},
{"DELETE /admin/tickets/:id not found", fun test_delete_not_found/0},
{"PATCH /admin/tickets method not allowed", fun test_wrong_method/0}
]}.
%% GET список тикетов (успех)
test_list() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"GET">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> undefined end), % для маршрута без id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
Ticket = #ticket{
id = <<"t1">>,
error_hash = <<"hash1">>,
error_message = <<"Error message">>,
stacktrace = <<"stack">>,
context = <<"ctx">>,
count = 1,
first_seen = {{2026,4,28},{12,0,0}},
last_seen = {{2026,4,28},{12,0,0}},
status = open,
assigned_to = undefined,
resolution_note = undefined
},
ok = meck:expect(core_ticket, list_all, fun() -> [Ticket] end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, RespBody, _} = erase(test_reply),
?assertEqual(200, Status),
[#{<<"id">> := <<"t1">>, <<"error_message">> := <<"Error message">>}] =
jsx:decode(RespBody, [return_maps]).
%% GET запрещён
test_list_forbidden() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"GET">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> undefined end), % для маршрута без id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {error, 403, <<"Admin access required">>, Req} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, _, _} = erase(test_reply),
?assertEqual(403, Status).
%% POST создание тикета
test_create() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"POST">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> undefined end), % для маршрута без id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
BodyMap = #{<<"error_message">> => <<"Bug">>, <<"stacktrace">> => <<"trace">>},
ok = meck:expect(cowboy_req, read_body,
fun(Req) -> {ok, jsx:encode(BodyMap), Req} end),
Created = #ticket{id = <<"t_new">>, error_message = <<"Bug">>, status = open},
ok = meck:expect(core_ticket, create_ticket, fun(_) -> {ok, Created} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, RespBody, _} = erase(test_reply),
?assertEqual(201, Status),
#{<<"error_message">> := <<"Bug">>} = jsx:decode(RespBody, [return_maps]).
%% POST отсутствует поле error_message
test_create_missing() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"POST">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> undefined end), % для маршрута без id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
ok = meck:expect(cowboy_req, read_body,
fun(Req) -> {ok, jsx:encode(#{<<"title">> => <<"No msg">>}), Req} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, _, _} = erase(test_reply),
?assertEqual(400, Status).
%% GET один тикет по ID
test_get() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"GET">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> <<"t1">> end), % для маршрута с id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
Ticket = #ticket{id = <<"t1">>, error_message = <<"Test">>, status = open},
ok = meck:expect(core_ticket, get_by_id,
fun(<<"t1">>) -> {ok, Ticket} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, RespBody, _} = erase(test_reply),
?assertEqual(200, Status),
#{<<"id">> := <<"t1">>} = jsx:decode(RespBody, [return_maps]).
%% GET тикет не найден
test_get_not_found() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"GET">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> <<"t99">> end), % для маршрута с id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
ok = meck:expect(core_ticket, get_by_id,
fun(_) -> {error, not_found} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, _, _} = erase(test_reply),
?assertEqual(404, Status).
%% PUT обновление тикета
test_update() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"PUT">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> <<"t1">> end), % для маршрута с id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
ok = meck:expect(cowboy_req, read_body,
fun(Req) -> {ok, jsx:encode(#{<<"status">> => <<"closed">>}), Req} end),
Updated = #ticket{id = <<"t1">>, status = closed},
ok = meck:expect(core_ticket, update_ticket,
fun(<<"t1">>, _) -> {ok, Updated} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, RespBody, _} = erase(test_reply),
?assertEqual(200, Status),
#{<<"status">> := <<"closed">>} = jsx:decode(RespBody, [return_maps]).
%% PUT тикет не найден
test_update_not_found() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"PUT">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> <<"t99">> end), % для маршрута с id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
ok = meck:expect(cowboy_req, read_body,
fun(Req) -> {ok, jsx:encode(#{<<"status">> => <<"closed">>}), Req} end),
ok = meck:expect(core_ticket, update_ticket,
fun(_, _) -> {error, not_found} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, _, _} = erase(test_reply),
?assertEqual(404, Status).
%% DELETE удаление тикета
test_delete() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"DELETE">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> <<"t1">> end), % для маршрута с id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
ok = meck:expect(core_ticket, delete_ticket,
fun(<<"t1">>) -> {ok, deleted} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, RespBody, _} = erase(test_reply),
?assertEqual(200, Status),
#{<<"status">> := <<"deleted">>} = jsx:decode(RespBody, [return_maps]).
%% DELETE тикет не найден
test_delete_not_found() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"DELETE">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> <<"t99">> end), % для маршрута с id
ok = meck:expect(handler_auth, authenticate,
fun(Req) -> {ok, <<"adm1">>, Req} end),
AdminUser = #user{id = <<"adm1">>, role = admin},
ok = meck:expect(core_user, get_by_id,
fun(<<"adm1">>) -> {ok, AdminUser} end),
ok = meck:expect(core_ticket, delete_ticket,
fun(_) -> {error, not_found} end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, _, _} = erase(test_reply),
?assertEqual(404, Status).
%% Неправильный метод
test_wrong_method() ->
ok = meck:expect(cowboy_req, method, fun(_) -> <<"PATCH">> end),
ok = meck:expect(cowboy_req, binding,
fun(id, _) -> undefined end), % для маршрута без id
ok = meck:expect(cowboy_req, reply,
fun(Code, Headers, Body, Req) ->
put(test_reply, {Code, Headers, Body, Req})
end),
{ok, _, _} = admin_handler_tickets:init(req, []),
{Status, _, RespBody, _} = erase(test_reply),
?assertEqual(405, Status),
#{<<"error">> := <<"Method not allowed">>} = jsx:decode(RespBody, [return_maps]).