Doug Lauder
2023-03-22 17:22:27 -04:00
коммит произвёл GitHub
родитель b61c096497
Коммит c943ed6859
13276 изменённых файлов: 1695615 добавлений и 223189 удалений

Просмотреть файл

@@ -0,0 +1,233 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package searchtest
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/server/channels/store"
)
var searchChannelStoreTests = []searchTest{
{
Name: "Should be able to autocomplete a channel by name",
Fn: testAutocompleteChannelByName,
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete a channel by name (Postgres)",
Fn: testAutocompleteChannelByNamePostgres,
Tags: []string{EnginePostgres},
},
{
Name: "Should be able to autocomplete a channel by display name",
Fn: testAutocompleteChannelByDisplayName,
Tags: []string{EngineAll},
},
{
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by - character",
Fn: testAutocompleteChannelByNameSplittedWithDashChar,
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by - character (Postgres)",
Fn: testAutocompleteChannelByNameSplittedWithDashCharPostgres,
Tags: []string{EnginePostgres},
},
{
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by _ character",
Fn: testAutocompleteChannelByNameSplittedWithUnderscoreChar,
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete a channel by a part of its display name when has parts splitted by whitespace character",
Fn: testAutocompleteChannelByDisplayNameSplittedByWhitespaces,
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete retrieving all channels if the term is empty",
Fn: testAutocompleteAllChannelsIfTermIsEmpty,
Tags: []string{EngineAll},
},
{
Name: "Should be able to autocomplete channels in a case insensitive manner",
Fn: testSearchChannelsInCaseInsensitiveManner,
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete channels in a case insensitive manner (Postgres)",
Fn: testSearchChannelsInCaseInsensitiveMannerPostgres,
Tags: []string{EnginePostgres},
},
{
Name: "Should support to autocomplete having a hyphen as the last character",
Fn: testSearchShouldSupportHavingHyphenAsLastCharacter,
Tags: []string{EngineAll},
},
{
Name: "Should support to autocomplete with archived channels",
Fn: testSearchShouldSupportAutocompleteWithArchivedChannels,
Tags: []string{EngineAll},
},
}
func TestSearchChannelStore(t *testing.T, s store.Store, testEngine *SearchTestEngine) {
th := &SearchTestHelper{
Store: s,
}
err := th.SetupBasicFixtures()
require.NoError(t, err)
defer th.CleanFixtures()
runTestSearch(t, testEngine, searchChannelStoreTests, th)
}
func testAutocompleteChannelByName(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "Channel Alternate", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
private, err := th.createChannel(th.Team.Id, "channel-altprivate", "Channel AltPrivate", "Channel Private", model.ChannelTypePrivate, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(private)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id, th.ChannelAnotherTeam.Id}, res2)
}
func testAutocompleteChannelByNamePostgres(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "Channel Alternate", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
}
func testAutocompleteChannelByDisplayName(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
private, err := th.createChannel(th.Team.Id, "channel-altprivate", "ChannelAltPrivate", "Channel Private", model.ChannelTypePrivate, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(private)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChannelA", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "ChannelA", false, false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id, th.ChannelAnotherTeam.Id}, res2)
}
func testAutocompleteChannelByNameSplittedWithDashChar(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
}
func testAutocompleteChannelByNameSplittedWithDashCharPostgres(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
}
func testAutocompleteChannelByNameSplittedWithUnderscoreChar(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel_alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel_a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{alternate.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel_a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{alternate.Id}, res2)
}
func testAutocompleteChannelByDisplayNameSplittedByWhitespaces(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "Channel A", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{alternate.Id}, res)
}
func testAutocompleteAllChannelsIfTermIsEmpty(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
other, err := th.createChannel(th.Team.Id, "other-channel", "Other Channel", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
defer th.deleteChannel(other)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id, other.Id}, res)
}
func testSearchChannelsInCaseInsensitiveManner(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channela", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
res, err = th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChAnNeL-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channela", false, false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, alternate.Id}, res2)
res2, err = th.Store.Channel().Autocomplete(th.User.Id, "ChAnNeL-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, alternate.Id}, res2)
}
func testSearchChannelsInCaseInsensitiveMannerPostgres(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channela", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
res, err = th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChAnNeL-a", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
}
func testSearchShouldSupportHavingHyphenAsLastCharacter(t *testing.T, th *SearchTestHelper) {
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
require.NoError(t, err)
defer th.deleteChannel(alternate)
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-", false, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel-", false, false)
require.NoError(t, err)
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res2)
}
func testSearchShouldSupportAutocompleteWithArchivedChannels(t *testing.T, th *SearchTestHelper) {
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-", true, false)
require.NoError(t, err)
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, th.ChannelDeleted.Id}, res)
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

512
server/channels/store/searchtest/helper.go Обычный файл
Просмотреть файл

@@ -0,0 +1,512 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package searchtest
import (
"fmt"
"testing"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/server/channels/store"
)
type SearchTestHelper struct {
Store store.Store
Team *model.Team
AnotherTeam *model.Team
User *model.User
User2 *model.User
UserAnotherTeam *model.User
ChannelBasic *model.Channel
ChannelPrivate *model.Channel
ChannelAnotherTeam *model.Channel
ChannelDeleted *model.Channel
}
func (th *SearchTestHelper) SetupBasicFixtures() error {
// Remove users from previous tests
err := th.cleanAllUsers()
if err != nil {
return err
}
// Create teams
team, err := th.createTeam("searchtest-team", "Searchtest team", model.TeamOpen)
if err != nil {
return err
}
anotherTeam, err := th.createTeam("another-searchtest-team", "Another Searchtest team", model.TeamOpen)
if err != nil {
return err
}
// Create users
user, err := th.createUser("basicusername1", "basicnickname1", "basicfirstname1", "basiclastname1")
if err != nil {
return err
}
user2, err := th.createUser("basicusername2", "basicnickname2", "basicfirstname2", "basiclastname2")
if err != nil {
return err
}
useranother, err := th.createUser("basicusername3", "basicnickname3", "basicfirstname3", "basiclastname3")
if err != nil {
return err
}
// Create channels
channelBasic, err := th.createChannel(team.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, nil, false)
if err != nil {
return err
}
channelPrivate, err := th.createChannel(team.Id, "channel-private", "ChannelPrivate", "", model.ChannelTypePrivate, nil, false)
if err != nil {
return err
}
channelDeleted, err := th.createChannel(team.Id, "channel-deleted", "ChannelA (deleted)", "", model.ChannelTypeOpen, nil, true)
if err != nil {
return err
}
channelAnotherTeam, err := th.createChannel(anotherTeam.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, nil, false)
if err != nil {
return err
}
err = th.addUserToTeams(user, []string{team.Id, anotherTeam.Id})
if err != nil {
return err
}
err = th.addUserToTeams(user2, []string{team.Id, anotherTeam.Id})
if err != nil {
return err
}
err = th.addUserToTeams(useranother, []string{anotherTeam.Id})
if err != nil {
return err
}
err = th.addUserToChannels(user, []string{channelBasic.Id, channelPrivate.Id, channelDeleted.Id})
if err != nil {
return err
}
err = th.addUserToChannels(user2, []string{channelPrivate.Id, channelDeleted.Id})
if err != nil {
return err
}
err = th.addUserToChannels(useranother, []string{channelAnotherTeam.Id})
if err != nil {
return err
}
th.Team = team
th.AnotherTeam = anotherTeam
th.User = user
th.User2 = user2
th.UserAnotherTeam = useranother
th.ChannelBasic = channelBasic
th.ChannelPrivate = channelPrivate
th.ChannelAnotherTeam = channelAnotherTeam
th.ChannelDeleted = channelDeleted
return nil
}
func (th *SearchTestHelper) CleanFixtures() error {
err := th.deleteChannels([]*model.Channel{
th.ChannelBasic, th.ChannelPrivate, th.ChannelAnotherTeam, th.ChannelDeleted,
})
if err != nil {
return err
}
err = th.deleteTeam(th.Team)
if err != nil {
return err
}
err = th.deleteTeam(th.AnotherTeam)
if err != nil {
return err
}
err = th.cleanAllUsers()
if err != nil {
return err
}
return nil
}
func (th *SearchTestHelper) createTeam(name, displayName, teamType string) (*model.Team, error) {
return th.Store.Team().Save(&model.Team{
Name: name,
DisplayName: displayName,
Type: teamType,
})
}
func (th *SearchTestHelper) deleteTeam(team *model.Team) error {
err := th.Store.Team().RemoveAllMembersByTeam(team.Id)
if err != nil {
return err
}
return th.Store.Team().PermanentDelete(team.Id)
}
func (th *SearchTestHelper) makeEmail() string {
return "success_" + model.NewId() + "@simulator.amazon.com"
}
func (th *SearchTestHelper) createUser(username, nickname, firstName, lastName string) (*model.User, error) {
return th.Store.User().Save(&model.User{
Username: username,
Password: username,
Nickname: nickname,
FirstName: firstName,
LastName: lastName,
Email: th.makeEmail(),
})
}
func (th *SearchTestHelper) createGuest(username, nickname, firstName, lastName string) (*model.User, error) {
return th.Store.User().Save(&model.User{
Username: username,
Password: username,
Nickname: nickname,
FirstName: firstName,
LastName: lastName,
Email: th.makeEmail(),
Roles: model.SystemGuestRoleId,
})
}
func (th *SearchTestHelper) deleteUser(user *model.User) error {
return th.Store.User().PermanentDelete(user.Id)
}
func (th *SearchTestHelper) deleteBotUser(botID string) error {
if err := th.deleteBot(botID); err != nil {
return err
}
return th.Store.User().PermanentDelete(botID)
}
func (th *SearchTestHelper) cleanAllUsers() error {
users, err := th.Store.User().GetAll()
if err != nil {
return err
}
for _, u := range users {
err := th.deleteUser(u)
if err != nil {
return err
}
}
return nil
}
func (th *SearchTestHelper) createBot(username, displayName, ownerID string) (*model.Bot, error) {
botModel := &model.Bot{
Username: username,
DisplayName: displayName,
OwnerId: ownerID,
}
user, err := th.Store.User().Save(model.UserFromBot(botModel))
if err != nil {
return nil, errors.New(err.Error())
}
botModel.UserId = user.Id
bot, err := th.Store.Bot().Save(botModel)
if err != nil {
th.Store.User().PermanentDelete(bot.UserId)
return nil, errors.New(err.Error())
}
return bot, nil
}
func (th *SearchTestHelper) deleteBot(botID string) error {
err := th.Store.Bot().PermanentDelete(botID)
if err != nil {
return errors.New(err.Error())
}
return nil
}
func (th *SearchTestHelper) createChannel(teamID, name, displayName, purpose string, channelType model.ChannelType, user *model.User, deleted bool) (*model.Channel, error) {
channel, err := th.Store.Channel().Save(&model.Channel{
TeamId: teamID,
DisplayName: displayName,
Name: name,
Type: channelType,
Purpose: purpose,
}, 999)
if err != nil {
return nil, err
}
if user != nil {
err = th.addUserToChannels(user, []string{channel.Id})
if err != nil {
return nil, err
}
}
if deleted {
err := th.Store.Channel().Delete(channel.Id, model.GetMillis())
if err != nil {
return nil, err
}
}
return channel, nil
}
func (th *SearchTestHelper) createDirectChannel(teamID, name, displayName string, users []*model.User) (*model.Channel, error) {
channel := &model.Channel{
TeamId: teamID,
Name: name,
DisplayName: displayName,
Type: model.ChannelTypeDirect,
}
m1 := &model.ChannelMember{}
m1.ChannelId = channel.Id
m1.UserId = users[0].Id
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
m2 := &model.ChannelMember{}
m2.ChannelId = channel.Id
m2.UserId = users[0].Id
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
channel, err := th.Store.Channel().SaveDirectChannel(channel, m1, m2)
if err != nil {
return nil, err
}
return channel, nil
}
func (th *SearchTestHelper) createGroupChannel(teamID, displayName string, users []*model.User) (*model.Channel, error) {
userIDS := make([]string, len(users))
for _, user := range users {
userIDS = append(userIDS, user.Id)
}
group := &model.Channel{
TeamId: teamID,
Name: model.GetGroupNameFromUserIds(userIDS),
DisplayName: displayName,
Type: model.ChannelTypeGroup,
}
channel, err := th.Store.Channel().Save(group, 10000)
if err != nil {
return nil, errors.New(err.Error())
}
for _, user := range users {
err := th.addUserToChannels(user, []string{channel.Id})
if err != nil {
return nil, err
}
}
return channel, nil
}
func (th *SearchTestHelper) deleteChannel(channel *model.Channel) error {
err := th.Store.Channel().PermanentDeleteMembersByChannel(channel.Id)
if err != nil {
return err
}
return th.Store.Channel().PermanentDelete(channel.Id)
}
func (th *SearchTestHelper) deleteChannels(channels []*model.Channel) error {
for _, channel := range channels {
err := th.deleteChannel(channel)
if err != nil {
return err
}
}
return nil
}
func (th *SearchTestHelper) createPostModel(userID, channelID, message, hashtags, postType string, createAt int64, pinned bool) *model.Post {
return &model.Post{
Message: message,
ChannelId: channelID,
PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()),
UserId: userID,
Hashtags: hashtags,
IsPinned: pinned,
CreateAt: createAt,
Type: postType,
}
}
func (th *SearchTestHelper) createPost(userID, channelID, message, hashtags, postType string, createAt int64, pinned bool) (*model.Post, error) {
var creationTime int64 = 1000000
if createAt > 0 {
creationTime = createAt
}
postModel := th.createPostModel(userID, channelID, message, hashtags, postType, creationTime, pinned)
return th.Store.Post().Save(postModel)
}
func (th *SearchTestHelper) createFileInfoModel(creatorID, postID, name, content, extension, mimeType string, createAt, size int64) *model.FileInfo {
return &model.FileInfo{
CreatorId: creatorID,
PostId: postID,
CreateAt: createAt,
UpdateAt: createAt,
DeleteAt: 0,
Name: name,
Content: content,
Path: name,
Extension: extension,
Size: size,
MimeType: mimeType,
}
}
func (th *SearchTestHelper) createFileInfo(creatorID, postID, name, content, extension, mimeType string, createAt, size int64) (*model.FileInfo, error) {
var creationTime int64 = 1000000
if createAt > 0 {
creationTime = createAt
}
fileInfoModel := th.createFileInfoModel(creatorID, postID, name, content, extension, mimeType, creationTime, size)
return th.Store.FileInfo().Save(fileInfoModel)
}
func (th *SearchTestHelper) createReply(userID, message, hashtags string, parent *model.Post, createAt int64, pinned bool) (*model.Post, error) {
replyModel := th.createPostModel(userID, parent.ChannelId, message, hashtags, parent.Type, createAt, pinned)
replyModel.RootId = parent.Id
return th.Store.Post().Save(replyModel)
}
func (th *SearchTestHelper) deleteUserPosts(userID string) error {
err := th.Store.Post().PermanentDeleteByUser(userID)
if err != nil {
return errors.New(err.Error())
}
return nil
}
func (th *SearchTestHelper) deleteUserFileInfos(userID string) error {
if _, err := th.Store.FileInfo().PermanentDeleteByUser(userID); err != nil {
return errors.New(err.Error())
}
return nil
}
func (th *SearchTestHelper) addUserToTeams(user *model.User, teamIDS []string) error {
for _, teamID := range teamIDS {
_, err := th.Store.Team().SaveMember(&model.TeamMember{TeamId: teamID, UserId: user.Id}, -1)
if err != nil {
return errors.New(err.Error())
}
}
return nil
}
func (th *SearchTestHelper) addUserToChannels(user *model.User, channelIDS []string) error {
for _, channelID := range channelIDS {
_, err := th.Store.Channel().SaveMember(&model.ChannelMember{
ChannelId: channelID,
UserId: user.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
if err != nil {
return errors.New(err.Error())
}
}
return nil
}
func (th *SearchTestHelper) assertUsersMatchInAnyOrder(t *testing.T, expected, actual []*model.User) {
expectedUsernames := make([]string, 0, len(expected))
for _, user := range expected {
user.Sanitize(map[string]bool{})
expectedUsernames = append(expectedUsernames, user.Username)
}
actualUsernames := make([]string, 0, len(actual))
for _, user := range actual {
user.Sanitize(map[string]bool{})
actualUsernames = append(actualUsernames, user.Username)
}
if assert.ElementsMatch(t, expectedUsernames, actualUsernames) {
assert.ElementsMatch(t, expected, actual)
}
}
func (th *SearchTestHelper) checkPostInSearchResults(t *testing.T, postID string, searchResults map[string]*model.Post) {
t.Helper()
postIDS := make([]string, len(searchResults))
for ID := range searchResults {
postIDS = append(postIDS, ID)
}
assert.Contains(t, postIDS, postID, "Did not find expected post in search results.")
}
func (th *SearchTestHelper) checkFileInfoInSearchResults(t *testing.T, fileID string, searchResults map[string]*model.FileInfo) {
t.Helper()
fileIDS := make([]string, len(searchResults))
for ID := range searchResults {
fileIDS = append(fileIDS, ID)
}
assert.Contains(t, fileIDS, fileID, "Did not find expected file in search results.")
}
func (th *SearchTestHelper) checkChannelIdsMatch(t *testing.T, expected []string, results model.ChannelList) {
t.Helper()
channelIds := make([]string, len(results))
for i, channel := range results {
channelIds[i] = channel.Id
}
require.ElementsMatch(t, expected, channelIds)
}
func (th *SearchTestHelper) checkChannelIdsMatchWithTeamData(t *testing.T, expected []string, results model.ChannelListWithTeamData) {
t.Helper()
channelIds := make([]string, len(results))
for i, channel := range results {
channelIds[i] = channel.Id
}
require.ElementsMatch(t, expected, channelIds)
}
type ByChannelDisplayName model.ChannelList
func (s ByChannelDisplayName) Len() int { return len(s) }
func (s ByChannelDisplayName) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByChannelDisplayName) Less(i, j int) bool {
if s[i].DisplayName != s[j].DisplayName {
return s[i].DisplayName < s[j].DisplayName
}
return s[i].Id < s[j].Id
}

1845
server/channels/store/searchtest/post_layer.go Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

78
server/channels/store/searchtest/testlib.go Обычный файл
Просмотреть файл

@@ -0,0 +1,78 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package searchtest
import (
"testing"
"github.com/mattermost/mattermost-server/v6/server/channels/store"
"github.com/mattermost/mattermost-server/v6/server/channels/utils"
)
const (
EngineAll = "all"
EngineMySql = "mysql"
EnginePostgres = "postgres"
EngineElasticSearch = "elasticsearch"
EngineBleve = "bleve"
)
type SearchTestEngine struct {
Driver string
BeforeTest func(*testing.T, store.Store)
AfterTest func(*testing.T, store.Store)
}
type searchTest struct {
Name string
Fn func(*testing.T, *SearchTestHelper)
Tags []string
Skip bool
SkipMessage string
}
func filterTestsByTag(tests []searchTest, tags ...string) []searchTest {
filteredTests := []searchTest{}
for _, test := range tests {
if utils.StringInSlice(EngineAll, test.Tags) {
filteredTests = append(filteredTests, test)
continue
}
for _, tag := range tags {
if utils.StringInSlice(tag, test.Tags) {
filteredTests = append(filteredTests, test)
break
}
}
}
return filteredTests
}
func runTestSearch(t *testing.T, testEngine *SearchTestEngine, tests []searchTest, th *SearchTestHelper) {
if testing.Short() {
t.Skip("Skipping advanced search test")
return
}
filteredTests := filterTestsByTag(tests, testEngine.Driver)
for _, test := range filteredTests {
if test.Skip {
t.Log("SKIPPED: " + test.Name + ". Reason: " + test.SkipMessage)
continue
}
if testEngine.BeforeTest != nil {
testEngine.BeforeTest(t, th.Store)
}
testName := test.Name
testFn := test.Fn
t.Run(testName, func(t *testing.T) { testFn(t, th) })
if testEngine.AfterTest != nil {
testEngine.AfterTest(t, th.Store)
}
}
}

Просмотреть файл

@@ -0,0 +1,875 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package searchtest
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/server/channels/store"
)
var searchUserStoreTests = []searchTest{
{
Name: "Should retrieve all users in a channel if the search term is empty",
Fn: testGetAllUsersInChannelWithEmptyTerm,
Tags: []string{EngineAll},
},
{
Name: "Should honor channel restrictions when autocompleting users",
Fn: testHonorChannelRestrictionsAutocompletingUsers,
Tags: []string{EngineAll},
},
{
Name: "Should honor team restrictions when autocompleting users",
Fn: testHonorTeamRestrictionsAutocompletingUsers,
Tags: []string{EngineElasticSearch, EngineBleve},
},
{
Name: "Should return nothing if the user can't access the channels of a given search",
Fn: testShouldReturnNothingWithoutProperAccess,
Tags: []string{EngineAll},
Skip: true,
SkipMessage: "Failing when the ListOfAllowedChannels property is empty",
},
{
Name: "Should autocomplete for user using username",
Fn: testAutocompleteUserByUsername,
Tags: []string{EngineAll},
},
{
Name: "Should autocomplete user searching by first name",
Fn: testAutocompleteUserByFirstName,
Tags: []string{EngineAll},
},
{
Name: "Should autocomplete user searching by last name",
Fn: testAutocompleteUserByLastName,
Tags: []string{EngineAll},
},
{
Name: "Should autocomplete for user using nickname",
Fn: testAutocompleteUserByNickName,
Tags: []string{EngineAll},
},
{
Name: "Should autocomplete for user using email",
Fn: testAutocompleteUserByEmail,
Tags: []string{EngineAll},
Skip: true,
SkipMessage: "Failing for multiple different reasons in the engines",
},
{
Name: "Should be able not to match specific queries with mail",
Fn: testShouldNotMatchSpecificQueriesEmail,
Tags: []string{EngineAll},
},
{
Name: "Should be able to autocomplete a user by part of its username splitted by Dot",
Fn: testAutocompleteUserByUsernameWithDot,
Tags: []string{EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete a user by part of its username splitted by underscore",
Fn: testAutocompleteUserByUsernameWithUnderscore,
Tags: []string{EngineElasticSearch, EngineBleve},
},
{
Name: "Should be able to autocomplete a user by part of its username splitted by hyphen",
Fn: testAutocompleteUserByUsernameWithHyphen,
Tags: []string{EngineElasticSearch, EngineBleve},
},
{
Name: "Should escape the percentage character",
Fn: testShouldEscapePercentageCharacter,
Tags: []string{EngineAll},
},
{
Name: "Should escape the dash character",
Fn: testShouldEscapeUnderscoreCharacter,
Tags: []string{EngineAll},
},
{
Name: "Should be able to search inactive users",
Fn: testShouldBeAbleToSearchInactiveUsers,
Tags: []string{EngineMySql, EnginePostgres, EngineElasticSearch},
},
{
Name: "Should be able to search filtering by role",
Fn: testShouldBeAbleToSearchFilteringByRole,
Tags: []string{EngineMySql, EnginePostgres, EngineElasticSearch},
},
{
Name: "Should ignore leading @ when searching users",
Fn: testShouldIgnoreLeadingAtSymbols,
Tags: []string{EngineAll},
},
{
Name: "Should search users in a case insensitive manner",
Fn: testSearchUsersShouldBeCaseInsensitive,
Tags: []string{EngineAll},
},
{
Name: "Should support one or two character usernames and first/last names in search",
Fn: testSearchOneTwoCharUsernamesAndFirstLastNames,
Tags: []string{EngineAll},
},
{
Name: "Should support Korean characters",
Fn: testShouldSupportKoreanCharacters,
Tags: []string{EngineAll},
},
{
Name: "Should support search with a hyphen at the end of the term",
Fn: testSearchWithHyphenAtTheEndOfTheTerm,
Tags: []string{EngineAll},
},
{
Name: "Should support search all users in a team",
Fn: testSearchUsersInTeam,
Tags: []string{EngineElasticSearch},
},
{
Name: "Should support search users by full name",
Fn: testSearchUsersByFullName,
Tags: []string{EngineAll},
},
{
Name: "Should support search all users in a team with username containing a dot",
Fn: testSearchUsersInTeamUsernameWithDot,
Tags: []string{EngineAll},
},
{
Name: "Should support search all users in a team with username containing a hyphen",
Fn: testSearchUsersInTeamUsernameWithHyphen,
Tags: []string{EngineAll},
},
{
Name: "Should support search all users in a team with username containing a underscore",
Fn: testSearchUsersInTeamUsernameWithUnderscore,
Tags: []string{EngineAll},
},
}
func TestSearchUserStore(t *testing.T, s store.Store, testEngine *SearchTestEngine) {
th := &SearchTestHelper{
Store: s,
}
err := th.SetupBasicFixtures()
require.NoError(t, err)
defer th.CleanFixtures()
runTestSearch(t, testEngine, searchUserStoreTests, th)
}
func testGetAllUsersInChannelWithEmptyTerm(t *testing.T, th *SearchTestHelper) {
options := &model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
t.Run("Should be able to correctly honor limit when autocompleting", func(t *testing.T) {
result, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
require.Len(t, result.InChannel, 1)
require.Len(t, result.OutOfChannel, 1)
})
t.Run("Return all users in team", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
t.Run("Return all users in teams even though some of them don't have a team associated", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
userAlternate, err := th.createUser("user-alternate", "user-alternate", "user", "alternate")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
userGuest, err := th.createGuest("user-guest", "user-guest", "user", "guest")
require.NoError(t, err)
defer th.deleteUser(userGuest)
// In case teamId and channelId are empty our current logic goes through Search
users, err := th.Store.User().Search("", "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, th.UserAnotherTeam,
userAlternate, userGuest}, users)
})
}
func testHonorChannelRestrictionsAutocompletingUsers(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("user-alternate", "user-alternate", "user", "alternate")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
guest, err := th.createGuest("guest", "guest", "guest", "one")
require.NoError(t, err)
err = th.addUserToTeams(guest, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(guest, []string{th.ChannelBasic.Id})
require.NoError(t, err)
defer th.deleteUser(guest)
t.Run("Autocomplete users with channel restrictions", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, userAlternate, guest}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Autocomplete users with term and channel restrictions", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alt", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Autocomplete users with all channels restricted", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Autocomplete users with all channels restricted but with empty team", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
users, err := th.Store.User().AutocompleteUsersInChannel("", th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Autocomplete users with empty team and channels restricted", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
// In case teamId and channelId are empty our current logic goes through Search
users, err := th.Store.User().Search("", "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate, guest, th.User}, users)
})
}
func testHonorTeamRestrictionsAutocompletingUsers(t *testing.T, th *SearchTestHelper) {
t.Run("Should return results for users in the team", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{th.Team.Id}}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
t.Run("Should return empty because we're filtering all the teams", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return empty when searching in one team and filtering by another", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{th.AnotherTeam.Id}}
users, err := th.Store.User().Search(th.Team.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
acusers, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, acusers.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, acusers.OutOfChannel)
})
}
func testShouldReturnNothingWithoutProperAccess(t *testing.T, th *SearchTestHelper) {
t.Run("Should return results users for the defined channel in the list", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ListOfAllowedChannels = []string{th.ChannelBasic.Id}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return empty because we're filtering all the channels", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
options.ListOfAllowedChannels = []string{}
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
}
func testAutocompleteUserByUsername(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternateusername", "alternatenick", "user", "alternate")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
}
func testAutocompleteUserByFirstName(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("user-alternate", "user-alternate", "altfirstname", "lastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should autocomplete users when the first name is unique", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "altfirstname", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should autocomplete users for in the channel and out of the channel with the same first name", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicfirstname", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
}
func testAutocompleteUserByLastName(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("user-alternate", "user-alternate", "firstname", "altlastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should return results when the last name is unique", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "altlastname", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return results for in the channel and out of the channel with the same last name", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basiclastname", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
}
func testAutocompleteUserByNickName(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternateusername", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should return results when the nickname is unique", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternatenickname", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return users that share the same part of the nickname", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicnickname", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
}
func testAutocompleteUserByEmail(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternateusername", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
userAlternate.Email = "useralt@test.email.com"
_, err = th.Store.User().Update(userAlternate, false)
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should autocomplete users when the email is unique", func(t *testing.T) {
options := createDefaultOptions(false, true, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "useralt@test.email.com", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should autocomplete users that share the same email user prefix", func(t *testing.T) {
options := createDefaultOptions(false, true, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "success_", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
t.Run("Should autocomplete users that share the same email domain", func(t *testing.T) {
options := createDefaultOptions(false, true, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "simulator.amazon.com", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
t.Run("Should search users when the email is unique", func(t *testing.T) {
options := createDefaultOptions(false, true, false)
users, err := th.Store.User().Search(th.Team.Id, "useralt@test.email.com", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
})
t.Run("Should search users that share the same email user prefix", func(t *testing.T) {
options := createDefaultOptions(false, true, false)
users, err := th.Store.User().Search(th.Team.Id, "success_", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
})
t.Run("Should search users that share the same email domain", func(t *testing.T) {
options := createDefaultOptions(false, true, false)
users, err := th.Store.User().Search(th.Team.Id, "simulator.amazon.com", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
})
}
func testShouldNotMatchSpecificQueriesEmail(t *testing.T, th *SearchTestHelper) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "success_", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
}
func testAutocompleteUserByUsernameWithDot(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate.username", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should return results when searching for the whole username with Dot", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate.username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return results when searching for part of the username including the Dot", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, ".username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return results when searching for part of the username not including the Dot", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
}
func testAutocompleteUserByUsernameWithUnderscore(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate_username", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should return results when searching for the whole username with underscore", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate_username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return results when searching for part of the username including the underscore", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "_username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return results when searching for part of the username not including the underscore", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
}
func testAutocompleteUserByUsernameWithHyphen(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate-username", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should return results when searching for the whole username with hyphen", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate-username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return results when searching for part of the username including the hyphen", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "-username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should return results when searching for part of the username not including the hyphen", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
}
func testShouldEscapePercentageCharacter(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternateusername", "alternate%nickname", "firstname", "altlastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should autocomplete users escaping percentage symbol", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate%", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should search users escaping percentage symbol", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "alternate%", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
})
}
func testShouldEscapeUnderscoreCharacter(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate_username", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should autocomplete users escaping underscore symbol", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate_", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should search users escaping underscore symbol", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "alternate_", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
})
}
func testShouldBeAbleToSearchInactiveUsers(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("basicusernamealternate", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
userAlternate.DeleteAt = model.GetMillis()
_, err = th.Store.User().Update(userAlternate, true)
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should autocomplete inactive users if we allow it", func(t *testing.T) {
options := createDefaultOptions(false, false, true)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
t.Run("Should search inactive users if we allow it", func(t *testing.T) {
options := createDefaultOptions(false, false, true)
users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, userAlternate}, users)
})
t.Run("Shouldn't autocomplete inactive users if we don't allow it", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
t.Run("Shouldn't search inactive users if we don't allow it", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
})
}
func testShouldBeAbleToSearchFilteringByRole(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("basicusernamealternate", "alternatenickname", "firstname", "altlastname")
require.NoError(t, err)
userAlternate.Roles = "system_admin system_user"
_, err = th.Store.User().Update(userAlternate, true)
require.NoError(t, err)
defer th.deleteUser(userAlternate)
userAlternate2, err := th.createUser("basicusernamealternate2", "alternatenickname2", "firstname2", "altlastname2")
require.NoError(t, err)
userAlternate2.Roles = "system_user"
_, err = th.Store.User().Update(userAlternate2, true)
require.NoError(t, err)
defer th.deleteUser(userAlternate2)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToTeams(userAlternate2, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should autocomplete users filtering by roles", func(t *testing.T) {
options := createDefaultOptions(false, false, true)
options.Role = "system_admin"
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should search users filtering by roles", func(t *testing.T) {
options := createDefaultOptions(false, false, true)
options.Role = "system_admin"
users, err := th.Store.User().Search(th.Team.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
})
}
func testShouldIgnoreLeadingAtSymbols(t *testing.T, th *SearchTestHelper) {
t.Run("Should autocomplete ignoring the @ symbol at the beginning", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "@basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
})
t.Run("Should search ignoring the @ symbol at the beginning", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "@basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
})
}
func testSearchUsersShouldBeCaseInsensitive(t *testing.T, th *SearchTestHelper) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "BaSiCUsErNaMe", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
}
func testSearchOneTwoCharUsernamesAndFirstLastNames(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("ho", "alternatenickname", "zi", "k")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should support two characters in the full name", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "zi", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should support two characters in the username", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "ho", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
}
func testShouldSupportKoreanCharacters(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate-username", "alternate-nickname", "서강준", "안신원")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
t.Run("Should support hanja korean characters", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "서강준", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
t.Run("Should support hangul korean characters", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "안신원", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
})
}
func testSearchWithHyphenAtTheEndOfTheTerm(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate-username", "alternate-nickname", "altfirst", "altlast")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate-", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
}
func testSearchUsersInTeam(t *testing.T, th *SearchTestHelper) {
t.Run("Should return all the team users", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
})
t.Run("Should return all the team users with no team id", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search("", "basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, th.UserAnotherTeam}, users)
})
t.Run("Should return all the team users filtered by username", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "basicusername1", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
})
t.Run("Should not return spurious results", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "falseuser", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
})
t.Run("Should return all the team users filtered by username and with channel restrictions", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
})
t.Run("Should return all the team users filtered by username and with all channel restricted", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{}}
users, err := th.Store.User().Search(th.Team.Id, "basicusername1", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
})
t.Run("Should honor the limit when searching users in team", func(t *testing.T) {
optionsWithLimit := &model.UserSearchOptions{
Limit: 1,
}
users, err := th.Store.User().Search(th.Team.Id, "", optionsWithLimit)
require.NoError(t, err)
require.Len(t, users, 1)
})
}
func testSearchUsersInTeamUsernameWithDot(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate.username", "altnickname", "altfirst", "altlast")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().Search(th.Team.Id, "alternate.", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
}
func testSearchUsersInTeamUsernameWithHyphen(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate-username", "altnickname", "altfirst", "altlast")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().Search(th.Team.Id, "alternate-", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
}
func testSearchUsersInTeamUsernameWithUnderscore(t *testing.T, th *SearchTestHelper) {
userAlternate, err := th.createUser("alternate_username", "altnickname", "altfirst", "altlast")
require.NoError(t, err)
defer th.deleteUser(userAlternate)
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
require.NoError(t, err)
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
require.NoError(t, err)
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().Search(th.Team.Id, "alternate_", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
}
func testSearchUsersByFullName(t *testing.T, th *SearchTestHelper) {
t.Run("Should search users by full name", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().Search(th.Team.Id, "basicfirstname", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
})
t.Run("Should search user by full name", func(t *testing.T) {
options := createDefaultOptions(true, false, false)
users, err := th.Store.User().Search(th.Team.Id, "basicfirstname1", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
})
t.Run("Should return empty when search by full name and is deactivated", func(t *testing.T) {
options := createDefaultOptions(false, false, false)
users, err := th.Store.User().Search(th.Team.Id, "basicfirstname1", options)
require.NoError(t, err)
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
})
}
func createDefaultOptions(allowFullName, allowEmails, allowInactive bool) *model.UserSearchOptions {
return &model.UserSearchOptions{
AllowFullNames: allowFullName,
AllowEmails: allowEmails,
AllowInactive: allowInactive,
Limit: model.UserSearchDefaultLimit,
}
}