Skip to content

Commit 51d4911

Browse files
committed
feat(api): add session's events listing
1 parent 109856d commit 51d4911

File tree

10 files changed

+633
-70
lines changed

10 files changed

+633
-70
lines changed

api/routes/routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ func NewRouter(service services.Service, opts ...Option) *echo.Echo {
132132

133133
publicAPI.GET(GetSessionsURL, routesmiddleware.Authorize(gateway.Handler(handler.GetSessionList)))
134134
publicAPI.GET(GetSessionURL, routesmiddleware.Authorize(gateway.Handler(handler.GetSession)))
135+
publicAPI.GET(ListEventsSessionsURL, routesmiddleware.Authorize(gateway.Handler(handler.ListEventsSession)))
135136

136137
publicAPI.GET(GetStatsURL, routesmiddleware.Authorize(gateway.Handler(handler.GetStats)))
137138
publicAPI.GET(GetSystemInfoURL, gateway.Handler(handler.GetSystemInfo))

api/routes/session.go

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ import (
1313
)
1414

1515
const (
16-
GetSessionsURL = "/sessions"
17-
GetSessionURL = "/sessions/:uid"
18-
UpdateSessionURL = "/sessions/:uid"
19-
CreateSessionURL = "/sessions"
20-
FinishSessionURL = "/sessions/:uid/finish"
21-
KeepAliveSessionURL = "/sessions/:uid/keepalive"
22-
EventsSessionsURL = "/sessions/:uid/events"
16+
GetSessionsURL = "/sessions"
17+
GetSessionURL = "/sessions/:uid"
18+
UpdateSessionURL = "/sessions/:uid"
19+
CreateSessionURL = "/sessions"
20+
FinishSessionURL = "/sessions/:uid/finish"
21+
KeepAliveSessionURL = "/sessions/:uid/keepalive"
22+
EventsSessionsURL = "/sessions/:uid/events"
23+
ListEventsSessionsURL = "/sessions/:uid/events"
2324
)
2425

2526
const (
@@ -164,7 +165,7 @@ func (h *Handler) EventSession(c gateway.Context) error {
164165
return err
165166
}
166167

167-
if err := h.service.EventSession(c.Ctx(), models.UID(req.UID), &models.SessionEvent{
168+
if err := h.service.SaveEventSession(c.Ctx(), models.UID(req.UID), &models.SessionEvent{
168169
Session: req.UID,
169170
Type: models.SessionEventType(r.Type),
170171
Timestamp: r.Timestamp,
@@ -175,3 +176,31 @@ func (h *Handler) EventSession(c gateway.Context) error {
175176
}
176177
}
177178
}
179+
180+
func (h *Handler) ListEventsSession(c gateway.Context) error {
181+
req := new(requests.SessionListEvents)
182+
183+
if err := c.Bind(req); err != nil {
184+
return err
185+
}
186+
187+
req.Paginator.Normalize()
188+
req.Sorter.Normalize()
189+
190+
if err := req.Filters.Unmarshal(); err != nil {
191+
return err
192+
}
193+
194+
if err := c.Validate(req); err != nil {
195+
return err
196+
}
197+
198+
events, counter, err := h.service.ListEventsSession(c.Ctx(), models.UID(req.UID), req.Paginator, req.Filters, req.Sorter)
199+
if err != nil {
200+
return err
201+
}
202+
203+
c.Response().Header().Set("X-Total-Count", strconv.Itoa(counter))
204+
205+
return c.JSON(http.StatusOK, events)
206+
}

api/routes/session_test.go

Lines changed: 187 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"io"
88
"net/http"
99
"net/http/httptest"
10+
"net/url"
11+
"strconv"
1012
"strings"
1113
"testing"
1214

@@ -399,7 +401,7 @@ func TestEventSession(t *testing.T) {
399401

400402
webSocketUpgraderMock.On("Upgrade", gomock.Anything, gomock.Anything).Return(conn, nil).Once()
401403

402-
mock.On("EventSession", gomock.Anything, models.UID(uid), gomock.Anything).
404+
mock.On("SaveEventSession", gomock.Anything, models.UID(uid), gomock.Anything).
403405
Return(errors.New("not able record")).Once()
404406
},
405407
expected: http.StatusInternalServerError,
@@ -422,7 +424,7 @@ func TestEventSession(t *testing.T) {
422424

423425
webSocketUpgraderMock.On("Upgrade", gomock.Anything, gomock.Anything).Return(conn, nil).Once()
424426

425-
mock.On("EventSession", gomock.Anything, models.UID(uid),
427+
mock.On("SaveEventSession", gomock.Anything, models.UID(uid),
426428
gomock.Anything).Return(nil).Once()
427429

428430
conn.On("ReadJSON", gomock.Anything).Return(&websocket.CloseError{
@@ -468,3 +470,186 @@ func TestEventSession(t *testing.T) {
468470
})
469471
}
470472
}
473+
474+
func TestListEventsSession(t *testing.T) {
475+
mock := new(mocks.Service)
476+
477+
cases := []struct {
478+
title string
479+
req *requests.SessionListEvents
480+
requiredMocks func()
481+
expectedStatus int
482+
expectedCounter string
483+
}{
484+
{
485+
title: "fails to list session's events when input data is invalid",
486+
req: &requests.SessionListEvents{
487+
UID: "",
488+
Paginator: query.Paginator{},
489+
Sorter: query.Sorter{},
490+
Filters: query.Filters{},
491+
},
492+
requiredMocks: func() {},
493+
expectedStatus: http.StatusBadRequest,
494+
expectedCounter: "",
495+
},
496+
{
497+
title: "fails to list session's events when cannot validate input params",
498+
req: &requests.SessionListEvents{
499+
UID: "",
500+
Paginator: query.Paginator{Page: 1, PerPage: 10},
501+
Sorter: query.Sorter{By: "name", Order: "asc"},
502+
Filters: query.Filters{},
503+
},
504+
requiredMocks: func() {},
505+
expectedStatus: http.StatusBadRequest,
506+
expectedCounter: "",
507+
},
508+
{
509+
title: "fails to list session's events when service fails because session doesn't exist",
510+
req: &requests.SessionListEvents{
511+
UID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
512+
Paginator: query.Paginator{Page: 1, PerPage: 10},
513+
Sorter: query.Sorter{By: "name", Order: "asc"},
514+
Filters: query.Filters{},
515+
},
516+
requiredMocks: func() {
517+
mock.
518+
On("ListEventsSession",
519+
gomock.Anything,
520+
models.UID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
521+
gomock.Anything,
522+
gomock.Anything,
523+
gomock.Anything,
524+
).
525+
Return(nil, 0, svc.ErrSessionNotFound).
526+
Once()
527+
},
528+
expectedStatus: http.StatusNotFound,
529+
expectedCounter: "",
530+
},
531+
{
532+
title: "fails to list session's events when service fails",
533+
req: &requests.SessionListEvents{
534+
UID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
535+
Paginator: query.Paginator{Page: 1, PerPage: 10},
536+
Sorter: query.Sorter{By: "name", Order: "asc"},
537+
Filters: query.Filters{},
538+
},
539+
requiredMocks: func() {
540+
mock.
541+
On("ListEventsSession",
542+
gomock.Anything,
543+
models.UID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
544+
gomock.Anything,
545+
gomock.Anything,
546+
gomock.Anything,
547+
).
548+
Return(nil, 0, errors.New("")).
549+
Once()
550+
},
551+
expectedStatus: http.StatusInternalServerError,
552+
expectedCounter: "",
553+
},
554+
{
555+
title: "success to list session's events when it is empty",
556+
req: &requests.SessionListEvents{
557+
UID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
558+
Paginator: query.Paginator{Page: 1, PerPage: 10},
559+
Sorter: query.Sorter{By: "name", Order: "asc"},
560+
Filters: query.Filters{},
561+
},
562+
requiredMocks: func() {
563+
mock.
564+
On("ListEventsSession",
565+
gomock.Anything,
566+
models.UID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
567+
gomock.Anything,
568+
gomock.Anything,
569+
gomock.Anything,
570+
).
571+
Return([]models.SessionEvent{}, 0, nil).
572+
Once()
573+
},
574+
expectedStatus: http.StatusOK,
575+
expectedCounter: "0",
576+
},
577+
{
578+
title: "success to list session's events with one item",
579+
req: &requests.SessionListEvents{
580+
UID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
581+
Paginator: query.Paginator{Page: 1, PerPage: 10},
582+
Sorter: query.Sorter{By: "name", Order: "asc"},
583+
Filters: query.Filters{},
584+
},
585+
requiredMocks: func() {
586+
mock.
587+
On("ListEventsSession",
588+
gomock.Anything,
589+
models.UID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
590+
gomock.Anything,
591+
gomock.Anything,
592+
gomock.Anything,
593+
).
594+
Return([]models.SessionEvent{
595+
{},
596+
}, 1, nil).
597+
Once()
598+
},
599+
expectedStatus: http.StatusOK,
600+
expectedCounter: "1",
601+
},
602+
{
603+
title: "success to list session's events with more than one item",
604+
req: &requests.SessionListEvents{
605+
UID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
606+
Paginator: query.Paginator{Page: 1, PerPage: 10},
607+
Sorter: query.Sorter{By: "name", Order: "asc"},
608+
Filters: query.Filters{},
609+
},
610+
requiredMocks: func() {
611+
mock.
612+
On("ListEventsSession",
613+
gomock.Anything,
614+
models.UID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
615+
gomock.Anything,
616+
gomock.Anything,
617+
gomock.Anything,
618+
).
619+
Return([]models.SessionEvent{
620+
{},
621+
{},
622+
}, 2, nil).
623+
Once()
624+
},
625+
expectedStatus: http.StatusOK,
626+
expectedCounter: "2",
627+
},
628+
}
629+
630+
for _, tc := range cases {
631+
t.Run(tc.title, func(t *testing.T) {
632+
tc.requiredMocks()
633+
634+
urlVal := &url.Values{}
635+
urlVal.Set("page", strconv.Itoa(tc.req.Page))
636+
urlVal.Set("per_page", strconv.Itoa(tc.req.PerPage))
637+
urlVal.Set("sort_by", tc.req.By)
638+
urlVal.Set("order_by", tc.req.Order)
639+
640+
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/sessions/%s/events?"+urlVal.Encode(), tc.req.UID), nil)
641+
req.Header.Set("Content-Type", "application/json")
642+
req.Header.Set("X-Role", authorizer.RoleOwner.String())
643+
644+
rec := httptest.NewRecorder()
645+
646+
e := NewRouter(mock)
647+
e.ServeHTTP(rec, req)
648+
649+
assert.Equal(t, tc.expectedStatus, rec.Result().StatusCode)
650+
assert.Equal(t, tc.expectedCounter, rec.Header().Get("X-Total-Count"))
651+
})
652+
}
653+
654+
mock.AssertExpectations(t)
655+
}

api/services/mocks/services.go

Lines changed: 56 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)