From d7db16f59a79b55a816dc204d0d8040b1be2d978 Mon Sep 17 00:00:00 2001 From: kshitij katiyar <90389917+Kshitij-Katiyar@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:24:44 +0530 Subject: [PATCH] Added server testcases for engine/calendar.go file (#415) * [MM-836]: Added server testcases for engine/calendar.go file * [add_engine/calender.go_testcase]: review fixes * [add_engine/calender.go_testcase]: removed unused variables --- calendar/engine/calendar_test.go | 439 +++++++++++++++++++++++++++++++ calendar/engine/test_utils.go | 100 +++++++ 2 files changed, 539 insertions(+) create mode 100644 calendar/engine/calendar_test.go create mode 100644 calendar/engine/test_utils.go diff --git a/calendar/engine/calendar_test.go b/calendar/engine/calendar_test.go new file mode 100644 index 00000000..6aa1ad8d --- /dev/null +++ b/calendar/engine/calendar_test.go @@ -0,0 +1,439 @@ +package engine + +import ( + "fmt" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/pkg/errors" + + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/remote" + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/store" + + "github.com/mattermost/mattermost/server/public/model" + "github.com/stretchr/testify/require" +) + +func TestViewCalendar(t *testing.T) { + mscalendar, mockStore, _, _, _, mockClient, _ := GetMockSetup(t) + now := time.Now() + from := now.Add(-time.Hour) + to := now.Add(time.Hour) + + tests := []struct { + name string + user *User + setupMock func() + assertions func(t *testing.T, events []*remote.Event, err error) + }{ + { + name: "error filtering with client", + user: GetMockUser(nil, model.NewString(MockMMModelUserID), MockMMUserID), + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("error loading the user")).Times(1) + }, + assertions: func(t *testing.T, _ []*remote.Event, err error) { + require.ErrorContains(t, err, "error loading the user") + }, + }, + { + name: "error getting calendar view", + user: GetMockUser(model.NewString(MockRemoteUserID), model.NewString(MockMMModelUserID), MockMMUserID), + setupMock: func() { + mockClient.EXPECT().GetDefaultCalendarView(MockRemoteUserID, from, to).Return(nil, fmt.Errorf("error getting calendar view")).Times(1) + }, + assertions: func(t *testing.T, _ []*remote.Event, err error) { + require.EqualError(t, err, "error getting calendar view") + }, + }, + { + name: "successful calendar view", + user: GetMockUser(model.NewString(MockRemoteUserID), model.NewString(MockMMModelUserID), MockMMUserID), + setupMock: func() { + mockClient.EXPECT().GetDefaultCalendarView(MockRemoteUserID, from, to).Return([]*remote.Event{{Subject: "Test Event"}}, nil).Times(1) + }, + assertions: func(t *testing.T, events []*remote.Event, err error) { + require.NoError(t, err) + require.NotNil(t, events) + require.Len(t, events, 1) + require.Equal(t, "Test Event", events[0].Subject, "Expected first event's subject to be %s, but got %s", "Test Event", events[0].Subject) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMock() + + events, err := mscalendar.ViewCalendar(tt.user, from, to) + + tt.assertions(t, events, err) + }) + } +} + +func TestGetTodayCalendarEvents(t *testing.T) { + mscalendar, mockStore, _, _, _, mockClient, _ := GetMockSetup(t) + now := time.Now() + timezone := "America/Los_Angeles" + from, to := getTodayHoursForTimezone(now, timezone) + + tests := []struct { + name string + user *User + setupMock func() + assertions func(t *testing.T, events []*remote.Event, err error) + }{ + { + name: "error expanding remote user", + user: GetMockUser(nil, model.NewString(MockMMModelUserID), MockMMUserID), + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("error loading the user")).Times(1) + }, + assertions: func(t *testing.T, _ []*remote.Event, err error) { + require.ErrorContains(t, err, "error loading the user") + }, + }, + { + name: "error getting calendar view", + user: GetMockUser(model.NewString(MockRemoteUserID), model.NewString(MockMMModelUserID), MockMMUserID), + setupMock: func() { + mockClient.EXPECT().GetDefaultCalendarView(MockRemoteUserID, from, to).Return(nil, fmt.Errorf("error getting calendar view")).Times(1) + }, + assertions: func(t *testing.T, _ []*remote.Event, err error) { + require.EqualError(t, err, "error getting calendar view") + }, + }, + { + name: "successful calendar view", + user: GetMockUser(model.NewString(MockRemoteUserID), model.NewString(MockMMModelUserID), MockMMUserID), + setupMock: func() { + mockClient.EXPECT().GetDefaultCalendarView(MockRemoteUserID, from, to).Return([]*remote.Event{{Subject: "Today's Test Event"}}, nil).Times(1) + }, + assertions: func(t *testing.T, events []*remote.Event, err error) { + require.NoError(t, err) + require.NotNil(t, events) + require.Len(t, events, 1) + require.Equal(t, "Today's Test Event", events[0].Subject, "Expected first event's subject to be %s, but got %s", "Today's Test Event", events[0].Subject) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMock() + + events, err := mscalendar.getTodayCalendarEvents(tt.user, now, timezone) + + tt.assertions(t, events, err) + }) + } +} + +func TestCreateCalendar(t *testing.T) { + mscalendar, mockStore, _, _, _, mockClient, _ := GetMockSetup(t) + + tests := []struct { + name string + user *User + calendar *remote.Calendar + setupMock func() + assertions func(t *testing.T, createdCalendar *remote.Calendar, err error) + }{ + { + name: "error expanding user", + user: GetMockUser(nil, nil, MockMMUserID), + calendar: GetMockCalendar(MockCalendarName), + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("error loading the user")).Times(1) + }, + assertions: func(t *testing.T, _ *remote.Calendar, err error) { + require.ErrorContains(t, err, "error loading the user") + }, + }, + { + name: "error creating calendar", + user: GetMockUser(model.NewString(MockRemoteUserID), model.NewString(MockMMModelUserID), MockMMUserID), + calendar: GetMockCalendar(MockCalendarName), + setupMock: func() { + mockClient.EXPECT().CreateCalendar(MockRemoteUserID, &remote.Calendar{Name: MockCalendarName}).Return(nil, fmt.Errorf("error creating calendar")).Times(1) + }, + assertions: func(t *testing.T, _ *remote.Calendar, err error) { + require.EqualError(t, err, "error creating calendar") + }, + }, + { + name: "successful calendar creation", + user: GetMockUser(model.NewString(MockRemoteUserID), model.NewString(MockMMModelUserID), MockMMUserID), + calendar: GetMockCalendar(MockCalendarName), + setupMock: func() { + mockClient.EXPECT().CreateCalendar(MockRemoteUserID, &remote.Calendar{Name: MockCalendarName}).Return(&remote.Calendar{Name: "Created Test Calendar"}, nil).Times(1) + }, + assertions: func(t *testing.T, createdCalendar *remote.Calendar, err error) { + require.NoError(t, err) + require.NotNil(t, createdCalendar) + require.Equal(t, "Created Test Calendar", createdCalendar.Name, "Expected calendar name to be %s, but got %s", "Created Test Calendar", createdCalendar.Name) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMock() + createdCalendar, err := mscalendar.CreateCalendar(tt.user, tt.calendar) + tt.assertions(t, createdCalendar, err) + }) + } +} + +func TestCreateEvent(t *testing.T) { + mscalendar, mockStore, mockPoster, _, mockPluginAPI, mockClient, mockLogger := GetMockSetup(t) + + tests := []struct { + name string + user *User + event *remote.Event + setupMock func() + assertions func(t *testing.T, createdEvent *remote.Event, err error) + expectedEvent *remote.Event + }{ + { + name: "error expanding user", + user: GetMockUser(nil, nil, MockMMUserID), + event: GetMockEvent(MockEventName, nil, nil, nil, nil), + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("error loading the user")).Times(1) + }, + assertions: func(t *testing.T, createdEvent *remote.Event, err error) { + require.ErrorContains(t, err, "error loading the user") + }, + }, + { + name: "error creating direct message", + user: GetMockUser(model.NewString(MockRemoteUserID), nil, MockMMUserID), + event: GetMockEvent(MockEventName, nil, nil, nil, nil), + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("not found")).Times(1) + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockPoster.EXPECT().DM(MockMMUserID, gomock.AssignableToTypeOf(""), "testDisplayName", "testDisplayName", "testCommandTrigger").Return("", fmt.Errorf("error creating DM")).Times(1) + mockLogger.EXPECT().Warnf("CreateEvent error creating DM. err=%v", gomock.Any()) + mockClient.EXPECT().CreateEvent(MockRemoteUserID, gomock.Any()).Return(&remote.Event{}, nil).Times(1) + }, + assertions: func(t *testing.T, createdEvent *remote.Event, err error) { + require.NoError(t, err) + require.NotNil(t, createdEvent) + require.Equal(t, &remote.Event{}, createdEvent) + }, + }, + { + name: "error creating event", + user: GetMockUser(model.NewString(MockRemoteUserID), nil, MockMMUserID), + event: GetMockEvent(MockEventName, nil, nil, nil, nil), + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("not found")).Times(1) + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockPoster.EXPECT().DM(MockMMUserID, gomock.AssignableToTypeOf(""), "testDisplayName", "testDisplayName", "testCommandTrigger").Return("", fmt.Errorf("error creating DM")).Times(1).Return("", nil) + mockClient.EXPECT().CreateEvent(MockRemoteUserID, &remote.Event{Subject: "Test Event"}).Return(nil, fmt.Errorf("error creating event")).Times(1) + }, + assertions: func(t *testing.T, createdEvent *remote.Event, err error) { + require.EqualError(t, err, "error creating event") + }, + }, + { + name: "successful event creation", + user: GetMockUser(model.NewString(MockRemoteUserID), nil, MockMMUserID), + event: GetMockEvent( + MockEventName, + &remote.Location{DisplayName: "Test Location"}, + &remote.DateTime{DateTime: "2024-10-01T09:00:00", TimeZone: "UTC"}, + &remote.DateTime{DateTime: "2024-10-01T10:00:00", TimeZone: "UTC"}, + []*remote.Attendee{{EmailAddress: &remote.EmailAddress{Address: "attendee1@example.com"}}}, + ), + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("not found")).Times(1) + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockPoster.EXPECT().DM(MockMMUserID, gomock.AssignableToTypeOf(""), "testDisplayName", "testDisplayName", "testCommandTrigger").Return("", fmt.Errorf("error creating DM")).Times(1).Return("", nil) + mockClient.EXPECT().CreateEvent(MockRemoteUserID, &remote.Event{ + Subject: "Test Event", + Location: &remote.Location{DisplayName: "Test Location"}, + Start: &remote.DateTime{DateTime: "2024-10-01T09:00:00", TimeZone: "UTC"}, + End: &remote.DateTime{DateTime: "2024-10-01T10:00:00", TimeZone: "UTC"}, + Attendees: []*remote.Attendee{{EmailAddress: &remote.EmailAddress{Address: "attendee1@example.com"}}}, + }).Return(&remote.Event{Subject: "Created Test Event", ID: "123"}, nil).Times(1) + }, + assertions: func(t *testing.T, createdEvent *remote.Event, err error) { + require.NoError(t, err) + require.NotNil(t, createdEvent) + require.Equal(t, &remote.Event{Subject: "Created Test Event", ID: "123"}, createdEvent) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMock() + createdEvent, err := mscalendar.CreateEvent(tt.user, tt.event, []string{MockMMUserID}) + tt.assertions(t, createdEvent, err) + }) + } +} + +func TestDeleteCalendar(t *testing.T) { + mscalendar, mockStore, _, _, mockPluginAPI, mockClient, _ := GetMockSetup(t) + user := GetMockUser(nil, nil, MockMMUserID) + + tests := []struct { + name string + setupMock func() + assertions func(t *testing.T, err error) + }{ + { + name: "error filtering with client", + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("error loading the user")).Times(1) + }, + assertions: func(t *testing.T, err error) { + require.ErrorContains(t, err, "error loading the user") + }, + }, + { + name: "error deleting calendar", + setupMock: func() { + user.User = &store.User{Remote: &remote.User{ID: MockRemoteUserID}} + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockClient.EXPECT().DeleteCalendar(user.User.Remote.ID, MockCalendarID).Return(errors.New("deletion error")).Times(1) + }, + assertions: func(t *testing.T, err error) { + require.EqualError(t, err, "deletion error") + }, + }, + { + name: "successful calendar deletion", + setupMock: func() { + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockClient.EXPECT().DeleteCalendar(user.User.Remote.ID, MockCalendarID).Return(nil).Times(1) + }, + assertions: func(t *testing.T, err error) { + require.NoError(t, err) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMock() + + err := mscalendar.DeleteCalendar(user, MockCalendarID) + + tt.assertions(t, err) + }) + } +} + +func TestFindMeetingTimes(t *testing.T) { + mscalendar, mockStore, _, _, mockPluginAPI, mockClient, _ := GetMockSetup(t) + user := GetMockUser(nil, nil, MockMMUserID) + + meetingParams := &remote.FindMeetingTimesParameters{} + + tests := []struct { + name string + setupMock func() + assertions func(t *testing.T, err error, results *remote.MeetingTimeSuggestionResults) + }{ + { + name: "error filtering with client", + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("error loading the user")).Times(1) + }, + assertions: func(t *testing.T, err error, results *remote.MeetingTimeSuggestionResults) { + require.ErrorContains(t, err, "error loading the user") + require.Nil(t, results) + }, + }, + { + name: "error finding meeting times", + setupMock: func() { + user.User = &store.User{Remote: &remote.User{ID: MockRemoteUserID}} + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockClient.EXPECT().FindMeetingTimes(user.User.Remote.ID, meetingParams).Return(nil, errors.New("finding times error")).Times(1) + }, + assertions: func(t *testing.T, err error, results *remote.MeetingTimeSuggestionResults) { + require.EqualError(t, err, "finding times error") + require.Nil(t, results) + }, + }, + { + name: "successful meeting time retrieval", + setupMock: func() { + user.User = &store.User{Remote: &remote.User{ID: MockRemoteUserID}} + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockClient.EXPECT().FindMeetingTimes(user.User.Remote.ID, meetingParams).Return(&remote.MeetingTimeSuggestionResults{}, nil).Times(1) + }, + assertions: func(t *testing.T, err error, results *remote.MeetingTimeSuggestionResults) { + require.NoError(t, err) + require.NotNil(t, results) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMock() + + results, err := mscalendar.FindMeetingTimes(user, meetingParams) + + tt.assertions(t, err, results) + }) + } +} + +func TestGetCalendars(t *testing.T) { + mscalendar, mockStore, _, _, mockPluginAPI, mockClient, _ := GetMockSetup(t) + user := GetMockUser(nil, nil, MockMMUserID) + + tests := []struct { + name string + setupMock func() + assertions func(t *testing.T, err error, calendars []*remote.Calendar) + }{ + { + name: "error filtering with client", + setupMock: func() { + mockStore.EXPECT().LoadUser(MockMMUserID).Return(nil, errors.New("error loading the user")).Times(1) + }, + assertions: func(t *testing.T, err error, calendars []*remote.Calendar) { + require.ErrorContains(t, err, "error loading the user") + require.Nil(t, calendars) + }, + }, + { + name: "error getting calendars", + setupMock: func() { + user.User = &store.User{Remote: &remote.User{ID: MockRemoteUserID}} + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockClient.EXPECT().GetCalendars(user.User.Remote.ID).Return(nil, errors.New("getting calendars error")).Times(1) + }, + assertions: func(t *testing.T, err error, calendars []*remote.Calendar) { + require.EqualError(t, err, "getting calendars error") + require.Nil(t, calendars) + }, + }, + { + name: "successful calendars retrieval", + setupMock: func() { + user.User = &store.User{Remote: &remote.User{ID: MockRemoteUserID}} + mockPluginAPI.EXPECT().GetMattermostUser(MockMMUserID) + mockClient.EXPECT().GetCalendars(user.User.Remote.ID).Return([]*remote.Calendar{{ID: "calendar1"}}, nil).Times(1) + }, + assertions: func(t *testing.T, err error, calendars []*remote.Calendar) { + require.NoError(t, err) + require.Equal(t, []*remote.Calendar{{ID: "calendar1"}}, calendars) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMock() + + calendars, err := mscalendar.GetCalendars(user) + + tt.assertions(t, err, calendars) + }) + } +} diff --git a/calendar/engine/test_utils.go b/calendar/engine/test_utils.go new file mode 100644 index 00000000..9af095b7 --- /dev/null +++ b/calendar/engine/test_utils.go @@ -0,0 +1,100 @@ +package engine + +import ( + "testing" + + "github.com/golang/mock/gomock" + + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/config" + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/engine/mock_plugin_api" + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/remote" + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/remote/mock_remote" + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/store" + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/store/mock_store" + "github.com/mattermost/mattermost-plugin-mscalendar/calendar/utils/bot/mock_bot" + + "github.com/mattermost/mattermost/server/public/model" +) + +const ( + MockRemoteUserID = "testRemoteUserID" + MockMMModelUserID = "testMMModelUserID" + MockMMUserID = "testMMUserID" + + MockCalendarName = "Test Calendar" + MockCalendarID = "testCalendarID" + + MockEventName = "Test Event" +) + +// revive:disable:unexported-return +func GetMockSetup(t *testing.T) (*mscalendar, *mock_store.MockStore, *mock_bot.MockPoster, *mock_remote.MockRemote, *mock_plugin_api.MockPluginAPI, *mock_remote.MockClient, *mock_bot.MockLogger) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockStore := mock_store.NewMockStore(ctrl) + mockPoster := mock_bot.NewMockPoster(ctrl) + mockRemote := mock_remote.NewMockRemote(ctrl) + mockPluginAPI := mock_plugin_api.NewMockPluginAPI(ctrl) + mockClient := mock_remote.NewMockClient(ctrl) + mockLogger := mock_bot.NewMockLogger(ctrl) + + env := Env{ + Dependencies: &Dependencies{ + Store: mockStore, + Poster: mockPoster, + Remote: mockRemote, + PluginAPI: mockPluginAPI, + Logger: mockLogger, + }, + } + + mscalendar := &mscalendar{ + Env: env, + client: mockClient, + } + + mscalendar.Config = &config.Config{ + Provider: config.ProviderConfig{ + DisplayName: "testDisplayName", + CommandTrigger: "testCommandTrigger", + }, + PluginVersion: "1.0.0", + } + + return mscalendar, mockStore, mockPoster, mockRemote, mockPluginAPI, mockClient, mockLogger +} + +func GetMockUser(remoteUserID, mmModelUserID *string, mmUserID string) *User { + user := (*store.User)(nil) + if remoteUserID != nil { + user = &store.User{Remote: &remote.User{ID: *remoteUserID}} + } + + mmUser := (*model.User)(nil) + if mmModelUserID != nil { + mmUser = &model.User{Id: *mmModelUserID} + } + + return &User{ + User: user, + MattermostUser: mmUser, + MattermostUserID: mmUserID, + } +} + +func GetMockCalendar(name string) *remote.Calendar { + return &remote.Calendar{ + Name: name, + } +} + +func GetMockEvent(subject string, location *remote.Location, start, end *remote.DateTime, attendees []*remote.Attendee) *remote.Event { + return &remote.Event{ + Subject: subject, + Location: location, + Start: start, + End: end, + Attendees: attendees, + } +}