diff --git a/server/src/.mockery.yaml b/server/src/.mockery.yaml index d8aca0eb11..75bec072d4 100644 --- a/server/src/.mockery.yaml +++ b/server/src/.mockery.yaml @@ -14,3 +14,5 @@ packages: all: true BoardSessions: all: true + Notes: + all: true diff --git a/server/src/api/notes_test.go b/server/src/api/notes_test.go index ff22c04b2d..2916e5c4dd 100644 --- a/server/src/api/notes_test.go +++ b/server/src/api/notes_test.go @@ -1,7 +1,6 @@ package api import ( - "context" "errors" "fmt" "github.com/go-chi/chi/v5" @@ -12,123 +11,13 @@ import ( "net/http/httptest" "scrumlr.io/server/common" "scrumlr.io/server/common/dto" - "scrumlr.io/server/common/filter" "scrumlr.io/server/identifiers" "scrumlr.io/server/logger" - "scrumlr.io/server/services" + "scrumlr.io/server/mocks/services" "strings" "testing" ) -type NotesMock struct { - services.Notes - mock.Mock -} - -func (m *NotesMock) Create(ctx context.Context, req dto.NoteCreateRequest) (*dto.Note, error) { - args := m.Called(req) - return args.Get(0).(*dto.Note), args.Error(1) -} -func (m *NotesMock) Get(ctx context.Context, id uuid.UUID) (*dto.Note, error) { - args := m.Called(id) - return args.Get(0).(*dto.Note), args.Error(1) -} -func (m *NotesMock) Delete(ctx context.Context, req dto.NoteDeleteRequest, id uuid.UUID) error { - args := m.Called(id) - return args.Error(0) - -} - -type BoardsMock struct { - services.Boards - mock.Mock -} - -type SessionsMock struct { - mock.Mock -} - -func (m *SessionsMock) SessionExists(ctx context.Context, boardID, userID uuid.UUID) (bool, error) { - args := m.Called(boardID, userID) - return args.Bool(0), args.Error(1) -} - -func (m *SessionsMock) ParticipantBanned(ctx context.Context, boardID, userID uuid.UUID) (bool, error) { - args := m.Called(boardID, userID) - return args.Bool(0), args.Error(1) -} - -func (m *SessionsMock) Connect(ctx context.Context, boardID, userID uuid.UUID) error { - args := m.Called(boardID, userID) - return args.Error(0) -} - -func (m *SessionsMock) Create(ctx context.Context, boardID, userID uuid.UUID) (*dto.BoardSession, error) { - args := m.Called(boardID, userID) - return args.Get(0).(*dto.BoardSession), args.Error(1) -} - -// Add other missing methods here -func (m *SessionsMock) Get(ctx context.Context, boardID, userID uuid.UUID) (*dto.BoardSession, error) { - args := m.Called(boardID, userID) - return args.Get(0).(*dto.BoardSession), args.Error(1) -} - -func (m *SessionsMock) Update(ctx context.Context, body dto.BoardSessionUpdateRequest) (*dto.BoardSession, error) { - args := m.Called(body) - return args.Get(0).(*dto.BoardSession), args.Error(1) -} - -func (m *SessionsMock) UpdateAll(ctx context.Context, body dto.BoardSessionsUpdateRequest) ([]*dto.BoardSession, error) { - args := m.Called(body) - return args.Get(0).([]*dto.BoardSession), args.Error(1) -} - -func (m *SessionsMock) List(ctx context.Context, boardID uuid.UUID, f filter.BoardSessionFilter) ([]*dto.BoardSession, error) { - args := m.Called(boardID, f) - return args.Get(0).([]*dto.BoardSession), args.Error(1) -} - -func (m *SessionsMock) Disconnect(ctx context.Context, boardID, userID uuid.UUID) error { - args := m.Called(boardID, userID) - return args.Error(0) -} - -func (m *SessionsMock) GetSessionRequest(ctx context.Context, boardID, userID uuid.UUID) (*dto.BoardSessionRequest, error) { - args := m.Called(boardID, userID) - return args.Get(0).(*dto.BoardSessionRequest), args.Error(1) -} - -func (m *SessionsMock) CreateSessionRequest(ctx context.Context, boardID, userID uuid.UUID) (*dto.BoardSessionRequest, error) { - args := m.Called(boardID, userID) - return args.Get(0).(*dto.BoardSessionRequest), args.Error(1) -} - -func (m *SessionsMock) ListSessionRequest(ctx context.Context, boardID uuid.UUID, statusQuery string) ([]*dto.BoardSessionRequest, error) { - args := m.Called(boardID, statusQuery) - return args.Get(0).([]*dto.BoardSessionRequest), args.Error(1) -} - -func (m *SessionsMock) UpdateSessionRequest(ctx context.Context, body dto.BoardSessionRequestUpdate) (*dto.BoardSessionRequest, error) { - args := m.Called(body) - return args.Get(0).(*dto.BoardSessionRequest), args.Error(1) -} - -func (m *SessionsMock) ModeratorSessionExists(ctx context.Context, boardID, userID uuid.UUID) (bool, error) { - args := m.Called(boardID, userID) - return args.Bool(0), args.Error(1) -} - -func (m *SessionsMock) SessionRequestExists(ctx context.Context, boardID, userID uuid.UUID) (bool, error) { - args := m.Called(boardID, userID) - return args.Bool(0), args.Error(1) -} - -func (m *BoardsMock) Get(ctx context.Context, id uuid.UUID) (*dto.Board, error) { - args := m.Called(id) - return args.Get(0).(*dto.Board), args.Error(1) -} - type NotesTestSuite struct { suite.Suite } @@ -167,38 +56,37 @@ func (suite *NotesTestSuite) TestCreateNote() { for _, tt := range tests { suite.Run(tt.name, func() { s := new(Server) - mock := new(NotesMock) + noteMock := services.NewMockNotes(suite.T()) testText := "asdf" boardId, _ := uuid.NewRandom() userId, _ := uuid.NewRandom() colId, _ := uuid.NewRandom() - mock.On("Create", dto.NoteCreateRequest{ - Board: boardId, - User: userId, - Text: testText, - Column: colId, - }).Return(&dto.Note{ - Text: testText, - }, tt.err) - - s.notes = mock + s.notes = noteMock req := NewTestRequestBuilder("POST", "/", strings.NewReader(fmt.Sprintf(`{ "column": "%s", "text" : "%s" }`, colId.String(), testText))) - req.req = logger.InitTestLoggerRequest(req.Request()) - req.AddToContext(identifiers.BoardIdentifier, boardId). AddToContext(identifiers.UserIdentifier, userId) + + noteMock.EXPECT().Create(req.req.Context(), dto.NoteCreateRequest{ + Board: boardId, + User: userId, + Text: testText, + Column: colId, + }).Return(&dto.Note{ + Text: testText, + }, tt.err) + rr := httptest.NewRecorder() s.createNote(rr, req.Request()) suite.Equal(tt.expectedCode, rr.Result().StatusCode) - mock.AssertExpectations(suite.T()) + noteMock.AssertExpectations(suite.T()) }) } @@ -233,23 +121,23 @@ func (suite *NotesTestSuite) TestGetNote() { for _, tt := range tests { suite.Run(tt.name, func() { s := new(Server) - mock := new(NotesMock) - s.notes = mock + noteMock := services.NewMockNotes(suite.T()) + s.notes = noteMock noteID, _ := uuid.NewRandom() - mock.On("Get", noteID).Return(&dto.Note{ - ID: noteID, - }, tt.err) - req := NewTestRequestBuilder("GET", "/", nil). AddToContext(identifiers.NoteIdentifier, noteID) + noteMock.EXPECT().Get(req.req.Context(), noteID).Return(&dto.Note{ + ID: noteID, + }, tt.err) + rr := httptest.NewRecorder() s.getNote(rr, req.Request()) suite.Equal(tt.expectedCode, rr.Result().StatusCode) - mock.AssertExpectations(suite.T()) + noteMock.AssertExpectations(suite.T()) }) } } @@ -280,49 +168,49 @@ func (suite *NotesTestSuite) TestDeleteNote() { for _, tt := range tests { suite.Run(tt.name, func() { s := new(Server) - noteMock := new(NotesMock) + + noteMock := services.NewMockNotes(suite.T()) + boardMock := services.NewMockBoards(suite.T()) + sessionMock := services.NewMockBoardSessions(suite.T()) + s.notes = noteMock - boardMock := new(BoardsMock) s.boards = boardMock - sessionMock := new(SessionsMock) s.sessions = sessionMock boardID, _ := uuid.NewRandom() userID, _ := uuid.NewRandom() noteID, _ := uuid.NewRandom() + r := chi.NewRouter() s.initNoteResources(r) - boardMock.On("Get", boardID).Return(&dto.Board{ + + req := NewTestRequestBuilder("DELETE", fmt.Sprintf("/notes/%s", noteID.String()), strings.NewReader(`{"deleteStack": false}`)) + req.req = logger.InitTestLoggerRequest(req.Request()) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("id", boardID.String()) + req.AddToContext(chi.RouteCtxKey, rctx) + req.AddToContext(identifiers.UserIdentifier, userID) + + boardMock.EXPECT().Get(mock.Anything, boardID).Return(&dto.Board{ ID: boardID, IsLocked: tt.isLocked, }, nil) // Mock the SessionExists method - sessionMock.On("SessionExists", boardID, userID).Return(true, nil) + sessionMock.EXPECT().SessionExists(req.req.Context(), boardID, userID).Return(true, nil) // Mock the ModeratorSessionExists method - sessionMock.On("ModeratorSessionExists", boardID, userID).Return(true, nil) + sessionMock.EXPECT().ModeratorSessionExists(mock.Anything, boardID, userID).Return(true, nil) // Mock the ParticipantBanned method - sessionMock.On("ParticipantBanned", boardID, userID).Return(false, nil) + sessionMock.EXPECT().ParticipantBanned(req.req.Context(), boardID, userID).Return(false, nil) if tt.isLocked { - noteMock.On("Delete", mock.Anything, mock.Anything).Return(nil) + noteMock.EXPECT().Delete(mock.Anything, dto.NoteDeleteRequest{DeleteStack: false}, noteID).Return(nil) } else { - boardMock.On("Get", boardID).Return(&dto.Board{ - ID: boardID, - IsLocked: tt.isLocked, - }, tt.err) - noteMock.On("Delete", mock.Anything).Return(tt.err) + noteMock.EXPECT().Delete(mock.Anything, dto.NoteDeleteRequest{DeleteStack: false}, noteID).Return(tt.err) } - req := NewTestRequestBuilder("DELETE", fmt.Sprintf("/notes/%s", noteID.String()), strings.NewReader(`{"deleteStack": false}`)) - req.req = logger.InitTestLoggerRequest(req.Request()) - rctx := chi.NewRouteContext() - rctx.URLParams.Add("id", boardID.String()) - req.AddToContext(chi.RouteCtxKey, rctx) - req.AddToContext(identifiers.UserIdentifier, userID) - rr := httptest.NewRecorder() r.ServeHTTP(rr, req.Request()) diff --git a/server/src/mocks/services/mock_Notes.go b/server/src/mocks/services/mock_Notes.go new file mode 100644 index 0000000000..66024de389 --- /dev/null +++ b/server/src/mocks/services/mock_Notes.go @@ -0,0 +1,382 @@ +// Code generated by mockery v2.51.0. DO NOT EDIT. + +package services + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + dto "scrumlr.io/server/common/dto" + + uuid "github.com/google/uuid" +) + +// MockNotes is an autogenerated mock type for the Notes type +type MockNotes struct { + mock.Mock +} + +type MockNotes_Expecter struct { + mock *mock.Mock +} + +func (_m *MockNotes) EXPECT() *MockNotes_Expecter { + return &MockNotes_Expecter{mock: &_m.Mock} +} + +// Create provides a mock function with given fields: ctx, body +func (_m *MockNotes) Create(ctx context.Context, body dto.NoteCreateRequest) (*dto.Note, error) { + ret := _m.Called(ctx, body) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 *dto.Note + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, dto.NoteCreateRequest) (*dto.Note, error)); ok { + return rf(ctx, body) + } + if rf, ok := ret.Get(0).(func(context.Context, dto.NoteCreateRequest) *dto.Note); ok { + r0 = rf(ctx, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*dto.Note) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, dto.NoteCreateRequest) error); ok { + r1 = rf(ctx, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockNotes_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type MockNotes_Create_Call struct { + *mock.Call +} + +// Create is a helper method to define mock.On call +// - ctx context.Context +// - body dto.NoteCreateRequest +func (_e *MockNotes_Expecter) Create(ctx interface{}, body interface{}) *MockNotes_Create_Call { + return &MockNotes_Create_Call{Call: _e.mock.On("Create", ctx, body)} +} + +func (_c *MockNotes_Create_Call) Run(run func(ctx context.Context, body dto.NoteCreateRequest)) *MockNotes_Create_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(dto.NoteCreateRequest)) + }) + return _c +} + +func (_c *MockNotes_Create_Call) Return(_a0 *dto.Note, _a1 error) *MockNotes_Create_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockNotes_Create_Call) RunAndReturn(run func(context.Context, dto.NoteCreateRequest) (*dto.Note, error)) *MockNotes_Create_Call { + _c.Call.Return(run) + return _c +} + +// Delete provides a mock function with given fields: ctx, body, id +func (_m *MockNotes) Delete(ctx context.Context, body dto.NoteDeleteRequest, id uuid.UUID) error { + ret := _m.Called(ctx, body, id) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, dto.NoteDeleteRequest, uuid.UUID) error); ok { + r0 = rf(ctx, body, id) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockNotes_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type MockNotes_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - ctx context.Context +// - body dto.NoteDeleteRequest +// - id uuid.UUID +func (_e *MockNotes_Expecter) Delete(ctx interface{}, body interface{}, id interface{}) *MockNotes_Delete_Call { + return &MockNotes_Delete_Call{Call: _e.mock.On("Delete", ctx, body, id)} +} + +func (_c *MockNotes_Delete_Call) Run(run func(ctx context.Context, body dto.NoteDeleteRequest, id uuid.UUID)) *MockNotes_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(dto.NoteDeleteRequest), args[2].(uuid.UUID)) + }) + return _c +} + +func (_c *MockNotes_Delete_Call) Return(_a0 error) *MockNotes_Delete_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockNotes_Delete_Call) RunAndReturn(run func(context.Context, dto.NoteDeleteRequest, uuid.UUID) error) *MockNotes_Delete_Call { + _c.Call.Return(run) + return _c +} + +// Get provides a mock function with given fields: ctx, id +func (_m *MockNotes) Get(ctx context.Context, id uuid.UUID) (*dto.Note, error) { + ret := _m.Called(ctx, id) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 *dto.Note + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) (*dto.Note, error)); ok { + return rf(ctx, id) + } + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) *dto.Note); ok { + r0 = rf(ctx, id) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*dto.Note) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockNotes_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type MockNotes_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - ctx context.Context +// - id uuid.UUID +func (_e *MockNotes_Expecter) Get(ctx interface{}, id interface{}) *MockNotes_Get_Call { + return &MockNotes_Get_Call{Call: _e.mock.On("Get", ctx, id)} +} + +func (_c *MockNotes_Get_Call) Run(run func(ctx context.Context, id uuid.UUID)) *MockNotes_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uuid.UUID)) + }) + return _c +} + +func (_c *MockNotes_Get_Call) Return(_a0 *dto.Note, _a1 error) *MockNotes_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockNotes_Get_Call) RunAndReturn(run func(context.Context, uuid.UUID) (*dto.Note, error)) *MockNotes_Get_Call { + _c.Call.Return(run) + return _c +} + +// Import provides a mock function with given fields: ctx, body +func (_m *MockNotes) Import(ctx context.Context, body dto.NoteImportRequest) (*dto.Note, error) { + ret := _m.Called(ctx, body) + + if len(ret) == 0 { + panic("no return value specified for Import") + } + + var r0 *dto.Note + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, dto.NoteImportRequest) (*dto.Note, error)); ok { + return rf(ctx, body) + } + if rf, ok := ret.Get(0).(func(context.Context, dto.NoteImportRequest) *dto.Note); ok { + r0 = rf(ctx, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*dto.Note) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, dto.NoteImportRequest) error); ok { + r1 = rf(ctx, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockNotes_Import_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Import' +type MockNotes_Import_Call struct { + *mock.Call +} + +// Import is a helper method to define mock.On call +// - ctx context.Context +// - body dto.NoteImportRequest +func (_e *MockNotes_Expecter) Import(ctx interface{}, body interface{}) *MockNotes_Import_Call { + return &MockNotes_Import_Call{Call: _e.mock.On("Import", ctx, body)} +} + +func (_c *MockNotes_Import_Call) Run(run func(ctx context.Context, body dto.NoteImportRequest)) *MockNotes_Import_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(dto.NoteImportRequest)) + }) + return _c +} + +func (_c *MockNotes_Import_Call) Return(_a0 *dto.Note, _a1 error) *MockNotes_Import_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockNotes_Import_Call) RunAndReturn(run func(context.Context, dto.NoteImportRequest) (*dto.Note, error)) *MockNotes_Import_Call { + _c.Call.Return(run) + return _c +} + +// List provides a mock function with given fields: ctx, id +func (_m *MockNotes) List(ctx context.Context, id uuid.UUID) ([]*dto.Note, error) { + ret := _m.Called(ctx, id) + + if len(ret) == 0 { + panic("no return value specified for List") + } + + var r0 []*dto.Note + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) ([]*dto.Note, error)); ok { + return rf(ctx, id) + } + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) []*dto.Note); ok { + r0 = rf(ctx, id) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*dto.Note) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockNotes_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' +type MockNotes_List_Call struct { + *mock.Call +} + +// List is a helper method to define mock.On call +// - ctx context.Context +// - id uuid.UUID +func (_e *MockNotes_Expecter) List(ctx interface{}, id interface{}) *MockNotes_List_Call { + return &MockNotes_List_Call{Call: _e.mock.On("List", ctx, id)} +} + +func (_c *MockNotes_List_Call) Run(run func(ctx context.Context, id uuid.UUID)) *MockNotes_List_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uuid.UUID)) + }) + return _c +} + +func (_c *MockNotes_List_Call) Return(_a0 []*dto.Note, _a1 error) *MockNotes_List_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockNotes_List_Call) RunAndReturn(run func(context.Context, uuid.UUID) ([]*dto.Note, error)) *MockNotes_List_Call { + _c.Call.Return(run) + return _c +} + +// Update provides a mock function with given fields: ctx, body +func (_m *MockNotes) Update(ctx context.Context, body dto.NoteUpdateRequest) (*dto.Note, error) { + ret := _m.Called(ctx, body) + + if len(ret) == 0 { + panic("no return value specified for Update") + } + + var r0 *dto.Note + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, dto.NoteUpdateRequest) (*dto.Note, error)); ok { + return rf(ctx, body) + } + if rf, ok := ret.Get(0).(func(context.Context, dto.NoteUpdateRequest) *dto.Note); ok { + r0 = rf(ctx, body) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*dto.Note) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, dto.NoteUpdateRequest) error); ok { + r1 = rf(ctx, body) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockNotes_Update_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Update' +type MockNotes_Update_Call struct { + *mock.Call +} + +// Update is a helper method to define mock.On call +// - ctx context.Context +// - body dto.NoteUpdateRequest +func (_e *MockNotes_Expecter) Update(ctx interface{}, body interface{}) *MockNotes_Update_Call { + return &MockNotes_Update_Call{Call: _e.mock.On("Update", ctx, body)} +} + +func (_c *MockNotes_Update_Call) Run(run func(ctx context.Context, body dto.NoteUpdateRequest)) *MockNotes_Update_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(dto.NoteUpdateRequest)) + }) + return _c +} + +func (_c *MockNotes_Update_Call) Return(_a0 *dto.Note, _a1 error) *MockNotes_Update_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockNotes_Update_Call) RunAndReturn(run func(context.Context, dto.NoteUpdateRequest) (*dto.Note, error)) *MockNotes_Update_Call { + _c.Call.Return(run) + return _c +} + +// NewMockNotes creates a new instance of MockNotes. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockNotes(t interface { + mock.TestingT + Cleanup(func()) +}) *MockNotes { + mock := &MockNotes{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +}