From 5872bf9c2f9b81c7aad761d40a6970f6267f1424 Mon Sep 17 00:00:00 2001 From: Martin Kraft Date: Mon, 30 Jul 2018 15:06:08 -0400 Subject: Pr 9039 (#9187) * MM-11065: Allow to search and get archived channels from the API * Fixing more tests * Add some unit tests * Add includeDeleted parameter to session permissions check function * More test fixing * Adding archive channels list in channels search * Add restriction for archived channel edition * Reverting permissions checks modification * Changed the query parameter to include_deleted * Enable search archive channels as true by default * Adding tests for verify search on deleted channels * Allowing to override archive channels during the imports * Fixed test * Search in archive channels from the API must be explicitly requested * Removing includeDeleted parameter from GetChannelByName and GetChannelByNameForTeam * Back to ViewArchivedChannels config * Fixing tests * Reverting GetChannelByName parameter * Add include deleted parameter on GetChannel functions in plugins api * Fixing tests --- store/sqlstore/channel_store.go | 48 +++++++-- store/sqlstore/post_store.go | 7 +- store/store.go | 8 +- store/storetest/channel_store.go | 45 ++++---- store/storetest/mocks/ChannelStore.go | 24 ++--- store/storetest/post_store.go | 197 +++++++++++++++++++++++----------- 6 files changed, 220 insertions(+), 109 deletions(-) (limited to 'store') diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go index 63e924e21..c073680f4 100644 --- a/store/sqlstore/channel_store.go +++ b/store/sqlstore/channel_store.go @@ -303,6 +303,11 @@ func (s SqlChannelStore) CreateIndexesIfNotExists() { func (s SqlChannelStore) Save(channel *model.Channel, maxChannelsPerTeam int64) store.StoreChannel { return store.Do(func(result *store.StoreResult) { + if channel.DeleteAt != 0 { + result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) + return + } + if channel.Type == model.CHANNEL_DIRECT { result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest) return @@ -352,6 +357,11 @@ func (s SqlChannelStore) CreateDirectChannel(userId string, otherUserId string) func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) store.StoreChannel { return store.Do(func(result *store.StoreResult) { + if directchannel.DeleteAt != 0 { + result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) + return + } + if directchannel.Type != model.CHANNEL_DIRECT { result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest) return @@ -629,10 +639,14 @@ func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) store }) } -func (s SqlChannelStore) GetChannels(teamId string, userId string) store.StoreChannel { +func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool) store.StoreChannel { return store.Do(func(result *store.StoreResult) { + query := "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND DeleteAt = 0 AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName" + if includeDeleted { + query = "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName" + } data := &model.ChannelList{} - _, err := s.GetReplica().Select(data, "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND DeleteAt = 0 AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId}) + _, err := s.GetReplica().Select(data, query, map[string]interface{}{"TeamId": teamId, "UserId": userId}) if err != nil { result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError) @@ -1100,7 +1114,7 @@ func (s SqlChannelStore) IsUserInChannelUseCache(userId string, channelId string s.metrics.IncrementMemCacheMissCounter("All Channel Members for User") } - result := <-s.GetAllChannelMembersForUser(userId, true) + result := <-s.GetAllChannelMembersForUser(userId, true, false) if result.Err != nil { mlog.Error("SqlChannelStore.IsUserInChannelUseCache: " + result.Err.Error()) return false @@ -1147,7 +1161,7 @@ func (s SqlChannelStore) GetMemberForPost(postId string, userId string) store.St }) } -func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool) store.StoreChannel { +func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool, includeDeleted bool) store.StoreChannel { return store.Do(func(result *store.StoreResult) { if allowFromCache { if cacheItem, ok := allChannelMembersForUserCache.Get(userId); ok { @@ -1163,6 +1177,11 @@ func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCac s.metrics.IncrementMemCacheMissCounter("All Channel Members for User") } + var deletedClause string + if !includeDeleted { + deletedClause = "Channels.DeleteAt = 0 AND" + } + var data allChannelMembers _, err := s.GetReplica().Select(&data, ` SELECT @@ -1182,8 +1201,8 @@ func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCac LEFT JOIN Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id WHERE - Channels.DeleteAt = 0 - AND ChannelMembers.UserId = :UserId`, map[string]interface{}{"UserId": userId}) + `+deletedClause+` + ChannelMembers.UserId = :UserId`, map[string]interface{}{"UserId": userId}) if err != nil { result.Err = model.NewAppError("SqlChannelStore.GetAllChannelMembersForUser", "store.sql_channel.get_channels.get.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError) @@ -1515,8 +1534,13 @@ func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) store.S }) } -func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string) store.StoreChannel { +func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { return store.Do(func(result *store.StoreResult) { + deleteFilter := "AND DeleteAt = 0" + if includeDeleted { + deleteFilter = "" + } + queryFormat := ` SELECT * @@ -1525,7 +1549,7 @@ func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string) store.St WHERE TeamId = :TeamId AND Type = 'O' - AND DeleteAt = 0 + ` + deleteFilter + ` %v LIMIT 50` @@ -1555,8 +1579,12 @@ func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string) store.St }) } -func (s SqlChannelStore) SearchInTeam(teamId string, term string) store.StoreChannel { +func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { return store.Do(func(result *store.StoreResult) { + deleteFilter := "AND DeleteAt = 0" + if includeDeleted { + deleteFilter = "" + } searchQuery := ` SELECT * @@ -1565,7 +1593,7 @@ func (s SqlChannelStore) SearchInTeam(teamId string, term string) store.StoreCha WHERE TeamId = :TeamId AND Type = 'O' - AND DeleteAt = 0 + ` + deleteFilter + ` SEARCH_CLAUSE ORDER BY DisplayName LIMIT 100` diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go index 229005b73..90db80796 100644 --- a/store/sqlstore/post_store.go +++ b/store/sqlstore/post_store.go @@ -803,6 +803,11 @@ func (s *SqlPostStore) Search(teamId string, userId string, params *model.Search var posts []*model.Post + deletedQueryPart := "AND DeleteAt = 0" + if params.IncludeDeletedChannels { + deletedQueryPart = "" + } + searchQuery := ` SELECT * @@ -822,7 +827,7 @@ func (s *SqlPostStore) Search(teamId string, userId string, params *model.Search Id = ChannelId AND (TeamId = :TeamId OR TeamId = '') AND UserId = :UserId - AND DeleteAt = 0 + ` + deletedQueryPart + ` CHANNEL_FILTER) SEARCH_CLAUSE ORDER BY CreateAt DESC diff --git a/store/store.go b/store/store.go index 203c637ff..2f18a0d8f 100644 --- a/store/store.go +++ b/store/store.go @@ -131,7 +131,7 @@ type ChannelStore interface { GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) StoreChannel GetDeletedByName(team_id string, name string) StoreChannel GetDeleted(team_id string, offset int, limit int) StoreChannel - GetChannels(teamId string, userId string) StoreChannel + GetChannels(teamId string, userId string, includeDeleted bool) StoreChannel GetMoreChannels(teamId string, userId string, offset int, limit int) StoreChannel GetPublicChannelsForTeam(teamId string, offset int, limit int) StoreChannel GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) StoreChannel @@ -143,7 +143,7 @@ type ChannelStore interface { UpdateMember(member *model.ChannelMember) StoreChannel GetMembers(channelId string, offset, limit int) StoreChannel GetMember(channelId string, userId string) StoreChannel - GetAllChannelMembersForUser(userId string, allowFromCache bool) StoreChannel + GetAllChannelMembersForUser(userId string, allowFromCache bool, includeDeleted bool) StoreChannel InvalidateAllChannelMembersForUser(userId string) IsUserInChannelUseCache(userId string, channelId string) bool GetAllChannelMembersNotifyPropsForChannel(channelId string, allowFromCache bool) StoreChannel @@ -160,8 +160,8 @@ type ChannelStore interface { IncrementMentionCount(channelId string, userId string) StoreChannel AnalyticsTypeCount(teamId string, channelType string) StoreChannel GetMembersForUser(teamId string, userId string) StoreChannel - AutocompleteInTeam(teamId string, term string) StoreChannel - SearchInTeam(teamId string, term string) StoreChannel + AutocompleteInTeam(teamId string, term string, includeDeleted bool) StoreChannel + SearchInTeam(teamId string, term string, includeDeleted bool) StoreChannel SearchMore(userId string, teamId string, term string) StoreChannel GetMembersByIds(channelId string, userIds []string) StoreChannel AnalyticsDeletedTypeCount(teamId string, channelType string) StoreChannel diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go index ccf4b1c59..9b5ac9e38 100644 --- a/store/storetest/channel_store.go +++ b/store/storetest/channel_store.go @@ -493,7 +493,7 @@ func testChannelStoreDelete(t *testing.T, ss store.Store) { t.Fatal(r.Err) } - cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) + cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId, false) list := cresult.Data.(*model.ChannelList) if len(*list) != 1 { @@ -509,7 +509,7 @@ func testChannelStoreDelete(t *testing.T, ss store.Store) { <-ss.Channel().PermanentDelete(o2.Id) - cresult = <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) + cresult = <-ss.Channel().GetChannels(o1.TeamId, m1.UserId, false) t.Log(cresult.Err) if cresult.Err.Id != "store.sql_channel.get_channels.not_found.app_error" { t.Fatal("no channels should be found") @@ -555,7 +555,7 @@ func testChannelStoreGetByName(t *testing.T, ss store.Store) { store.Must(ss.Channel().Delete(r1.Data.(*model.Channel).Id, model.GetMillis())) - if err := (<-ss.Channel().GetByName(o1.TeamId, "", false)).Err; err == nil { + if err := (<-ss.Channel().GetByName(o1.TeamId, r1.Data.(*model.Channel).Name, false)).Err; err == nil { t.Fatal("Deleted channel should not be returned by GetByName()") } } @@ -617,8 +617,11 @@ func testChannelStoreGetDeletedByName(t *testing.T, ss store.Store) { o1.DisplayName = "Name" o1.Name = "zz" + model.NewId() + "b" o1.Type = model.CHANNEL_OPEN - o1.DeleteAt = model.GetMillis() store.Must(ss.Channel().Save(&o1, -1)) + now := model.GetMillis() + store.Must(ss.Channel().Delete(o1.Id, now)) + o1.DeleteAt = now + o1.UpdateAt = now if r1 := <-ss.Channel().GetDeletedByName(o1.TeamId, o1.Name); r1.Err != nil { t.Fatal(r1.Err) @@ -639,8 +642,8 @@ func testChannelStoreGetDeleted(t *testing.T, ss store.Store) { o1.DisplayName = "Channel1" o1.Name = "zz" + model.NewId() + "b" o1.Type = model.CHANNEL_OPEN - o1.DeleteAt = model.GetMillis() store.Must(ss.Channel().Save(&o1, -1)) + store.Must(ss.Channel().Delete(o1.Id, model.GetMillis())) cresult := <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) if cresult.Err != nil { @@ -678,8 +681,8 @@ func testChannelStoreGetDeleted(t *testing.T, ss store.Store) { o3.DisplayName = "Channel3" o3.Name = "zz" + model.NewId() + "b" o3.Type = model.CHANNEL_OPEN - o3.DeleteAt = model.GetMillis() store.Must(ss.Channel().Save(&o3, -1)) + store.Must(ss.Channel().SetDeleteAt(o3.Id, model.GetMillis(), model.GetMillis())) cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) if cresult.Err != nil { @@ -890,26 +893,26 @@ func testChannelStoreGetChannels(t *testing.T, ss store.Store) { m3.NotifyProps = model.GetDefaultChannelNotifyProps() store.Must(ss.Channel().SaveMember(&m3)) - cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) + cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId, false) list := cresult.Data.(*model.ChannelList) if (*list)[0].Id != o1.Id { t.Fatal("missing channel") } - acresult := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, false) + acresult := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, false, false) ids := acresult.Data.(map[string]string) if _, ok := ids[o1.Id]; !ok { t.Fatal("missing channel") } - acresult2 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true) + acresult2 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true, false) ids2 := acresult2.Data.(map[string]string) if _, ok := ids2[o1.Id]; !ok { t.Fatal("missing channel") } - acresult3 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true) + acresult3 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true, false) ids3 := acresult3.Data.(map[string]string) if _, ok := ids3[o1.Id]; !ok { t.Fatal("missing channel") @@ -1913,12 +1916,12 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { o12.Type = model.CHANNEL_OPEN store.Must(ss.Channel().Save(&o12, -1)) - for name, search := range map[string]func(teamId string, term string) store.StoreChannel{ + for name, search := range map[string]func(teamId string, term string, includeDeleted bool) store.StoreChannel{ "AutocompleteInTeam": ss.Channel().AutocompleteInTeam, "SearchInTeam": ss.Channel().SearchInTeam, } { t.Run(name, func(t *testing.T) { - if result := <-search(o1.TeamId, "ChannelA"); result.Err != nil { + if result := <-search(o1.TeamId, "ChannelA", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -1927,7 +1930,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, ""); result.Err != nil { + if result := <-search(o1.TeamId, "", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -1936,7 +1939,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "blargh"); result.Err != nil { + if result := <-search(o1.TeamId, "blargh", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -1945,7 +1948,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "off-"); result.Err != nil { + if result := <-search(o1.TeamId, "off-", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -1962,7 +1965,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "off-topic"); result.Err != nil { + if result := <-search(o1.TeamId, "off-topic", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -1975,7 +1978,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "town square"); result.Err != nil { + if result := <-search(o1.TeamId, "town square", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -1988,7 +1991,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "the"); result.Err != nil { + if result := <-search(o1.TeamId, "the", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -2002,7 +2005,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "Mobile"); result.Err != nil { + if result := <-search(o1.TeamId, "Mobile", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -2016,7 +2019,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "now searchable"); result.Err != nil { + if result := <-search(o1.TeamId, "now searchable", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) @@ -2029,7 +2032,7 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { } } - if result := <-search(o1.TeamId, "town square |"); result.Err != nil { + if result := <-search(o1.TeamId, "town square |", false); result.Err != nil { t.Fatal(result.Err) } else { channels := result.Data.(*model.ChannelList) diff --git a/store/storetest/mocks/ChannelStore.go b/store/storetest/mocks/ChannelStore.go index 4929557ea..4cbf9cb77 100644 --- a/store/storetest/mocks/ChannelStore.go +++ b/store/storetest/mocks/ChannelStore.go @@ -46,12 +46,12 @@ func (_m *ChannelStore) AnalyticsTypeCount(teamId string, channelType string) st } // AutocompleteInTeam provides a mock function with given fields: teamId, term -func (_m *ChannelStore) AutocompleteInTeam(teamId string, term string) store.StoreChannel { +func (_m *ChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { ret := _m.Called(teamId, term) var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, string) store.StoreChannel); ok { - r0 = rf(teamId, term) + if rf, ok := ret.Get(0).(func(string, string, bool) store.StoreChannel); ok { + r0 = rf(teamId, term, includeDeleted) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(store.StoreChannel) @@ -147,12 +147,12 @@ func (_m *ChannelStore) GetAll(teamId string) store.StoreChannel { } // GetAllChannelMembersForUser provides a mock function with given fields: userId, allowFromCache -func (_m *ChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool) store.StoreChannel { +func (_m *ChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool, includeDeleted bool) store.StoreChannel { ret := _m.Called(userId, allowFromCache) var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, bool) store.StoreChannel); ok { - r0 = rf(userId, allowFromCache) + if rf, ok := ret.Get(0).(func(string, bool, bool) store.StoreChannel); ok { + r0 = rf(userId, allowFromCache, includeDeleted) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(store.StoreChannel) @@ -259,12 +259,12 @@ func (_m *ChannelStore) GetChannelUnread(channelId string, userId string) store. } // GetChannels provides a mock function with given fields: teamId, userId -func (_m *ChannelStore) GetChannels(teamId string, userId string) store.StoreChannel { +func (_m *ChannelStore) GetChannels(teamId string, userId string, includeDeleted bool) store.StoreChannel { ret := _m.Called(teamId, userId) var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, string) store.StoreChannel); ok { - r0 = rf(teamId, userId) + if rf, ok := ret.Get(0).(func(string, string, bool) store.StoreChannel); ok { + r0 = rf(teamId, userId, includeDeleted) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(store.StoreChannel) @@ -776,12 +776,12 @@ func (_m *ChannelStore) SaveMember(member *model.ChannelMember) store.StoreChann } // SearchInTeam provides a mock function with given fields: teamId, term -func (_m *ChannelStore) SearchInTeam(teamId string, term string) store.StoreChannel { +func (_m *ChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { ret := _m.Called(teamId, term) var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, string) store.StoreChannel); ok { - r0 = rf(teamId, term) + if rf, ok := ret.Get(0).(func(string, string, bool) store.StoreChannel); ok { + r0 = rf(teamId, term, includeDeleted) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(store.StoreChannel) diff --git a/store/storetest/post_store.go b/store/storetest/post_store.go index 1159af37f..da1b069a2 100644 --- a/store/storetest/post_store.go +++ b/store/storetest/post_store.go @@ -13,6 +13,7 @@ import ( "github.com/mattermost/mattermost-server/store" "github.com/mattermost/mattermost-server/utils" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestPostStore(t *testing.T, ss store.Store) { @@ -839,6 +840,20 @@ func testPostStoreSearch(t *testing.T, ss store.Store) { c2.Type = model.CHANNEL_OPEN c2 = (<-ss.Channel().Save(c2, -1)).Data.(*model.Channel) + c3 := &model.Channel{} + c3.TeamId = teamId + c3.DisplayName = "Channel1" + c3.Name = "zz" + model.NewId() + "b" + c3.Type = model.CHANNEL_OPEN + c3 = (<-ss.Channel().Save(c3, -1)).Data.(*model.Channel) + <-ss.Channel().Delete(c3.Id, model.GetMillis()) + + m3 := model.ChannelMember{} + m3.ChannelId = c3.Id + m3.UserId = userId + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m3)) + o1 := &model.Post{} o1.ChannelId = c1.Id o1.UserId = model.NewId() @@ -877,69 +892,129 @@ func testPostStoreSearch(t *testing.T, ss store.Store) { o5.Hashtags = "#secret #howdy" o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) - r1 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "corey", IsHashtag: false})).Data.(*model.PostList) - if len(r1.Order) != 1 || r1.Order[0] != o1.Id { - t.Fatal("returned wrong search result") - } - - r3 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "new", IsHashtag: false})).Data.(*model.PostList) - if len(r3.Order) != 2 || (r3.Order[0] != o1.Id && r3.Order[1] != o1.Id) { - t.Fatal("returned wrong search result") - } - - r4 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "john", IsHashtag: false})).Data.(*model.PostList) - if len(r4.Order) != 1 || r4.Order[0] != o2.Id { - t.Fatal("returned wrong search result") - } - - r5 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter*", IsHashtag: false})).Data.(*model.PostList) - if len(r5.Order) != 1 || r5.Order[0] != o1.Id { - t.Fatal("returned wrong search result") - } - - r6 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "#hashtag", IsHashtag: true})).Data.(*model.PostList) - if len(r6.Order) != 1 || r6.Order[0] != o4.Id { - t.Fatal("returned wrong search result") - } - - r7 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "#secret", IsHashtag: true})).Data.(*model.PostList) - if len(r7.Order) != 1 || r7.Order[0] != o5.Id { - t.Fatal("returned wrong search result") - } - - r8 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "@thisshouldmatchnothing", IsHashtag: true})).Data.(*model.PostList) - if len(r8.Order) != 0 { - t.Fatal("returned wrong search result") - } - - r9 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "mattermost jersey", IsHashtag: false})).Data.(*model.PostList) - if len(r9.Order) != 0 { - t.Fatal("returned wrong search result") - } - - r9a := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "corey new york", IsHashtag: false})).Data.(*model.PostList) - if len(r9a.Order) != 1 { - t.Fatal("returned wrong search result") - } - - r10 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter* jer*", IsHashtag: false})).Data.(*model.PostList) - if len(r10.Order) != 0 { - t.Fatal("returned wrong search result") - } - - r11 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "message blargh", IsHashtag: false})).Data.(*model.PostList) - if len(r11.Order) != 1 { - t.Fatal("returned wrong search result") - } + o6 := &model.Post{} + o6.ChannelId = c3.Id + o6.UserId = model.NewId() + o6.Hashtags = "#hashtag" + o6 = (<-ss.Post().Save(o6)).Data.(*model.Post) - r12 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "blargh>", IsHashtag: false})).Data.(*model.PostList) - if len(r12.Order) != 1 { - t.Fatal("returned wrong search result") + o7 := &model.Post{} + o7.ChannelId = c3.Id + o7.UserId = model.NewId() + o7.Message = "New Jersey is where John is from corey new york" + o7 = (<-ss.Post().Save(o7)).Data.(*model.Post) + + o8 := &model.Post{} + o8.ChannelId = c3.Id + o8.UserId = model.NewId() + o8.Message = "Deleted" + o8 = (<-ss.Post().Save(o8)).Data.(*model.Post) + + tt := []struct { + name string + searchParams *model.SearchParams + extectedResultsCount int + expectedMessageResultIds []string + }{ + { + "normal-search-1", + &model.SearchParams{Terms: "corey"}, + 1, + []string{o1.Id}, + }, + { + "normal-search-2", + &model.SearchParams{Terms: "new"}, + 2, + []string{o1.Id, o2.Id}, + }, + { + "normal-search-3", + &model.SearchParams{Terms: "john"}, + 1, + []string{o2.Id}, + }, + { + "wildcard-search", + &model.SearchParams{Terms: "matter*"}, + 1, + []string{o1.Id}, + }, + { + "hashtag-search", + &model.SearchParams{Terms: "#hashtag", IsHashtag: true}, + 1, + []string{o4.Id}, + }, + { + "hashtag-search-2", + &model.SearchParams{Terms: "#secret", IsHashtag: true}, + 1, + []string{o5.Id}, + }, + { + "no-match-mention", + &model.SearchParams{Terms: "@thisshouldmatchnothing", IsHashtag: true}, + 0, + []string{}, + }, + { + "no-results-search", + &model.SearchParams{Terms: "mattermost jersey"}, + 0, + []string{}, + }, + { + "multiple-words-search", + &model.SearchParams{Terms: "corey new york"}, + 1, + []string{o1.Id}, + }, + { + "multiple-wildcard-search", + &model.SearchParams{Terms: "matter* jer*"}, + 0, + []string{}, + }, + { + "search-with-work-next-to-a-symbol", + &model.SearchParams{Terms: "message blargh"}, + 1, + []string{o4.Id}, + }, + { + "search-with-or", + &model.SearchParams{Terms: "Jersey corey", OrTerms: true}, + 2, + []string{o1.Id, o2.Id}, + }, + { + "search-with-or-and-deleted", + &model.SearchParams{Terms: "Jersey corey", OrTerms: true, IncludeDeletedChannels: true}, + 3, + []string{o1.Id, o2.Id, o7.Id}, + }, + { + "search-hashtag-deleted", + &model.SearchParams{Terms: "#hashtag", IsHashtag: true, IncludeDeletedChannels: true}, + 2, + []string{o4.Id, o6.Id}, + }, + { + "search-deleted-only", + &model.SearchParams{Terms: "Deleted", IncludeDeletedChannels: true}, + 1, + []string{o8.Id}, + }, } - - r13 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "Jersey corey", IsHashtag: false, OrTerms: true})).Data.(*model.PostList) - if len(r13.Order) != 2 { - t.Fatal("returned wrong search result") + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + result := (<-ss.Post().Search(teamId, userId, tc.searchParams)).Data.(*model.PostList) + require.Len(t, result.Order, tc.extectedResultsCount) + for _, expectedMessageResultId := range tc.expectedMessageResultIds { + assert.Contains(t, result.Order, expectedMessageResultId) + } + }) } } -- cgit v1.2.3-1-g7c22