github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/store/searchtest/user_layer.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package searchtest
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/model"
    12  	"github.com/mattermost/mattermost-server/v5/store"
    13  )
    14  
    15  var searchUserStoreTests = []searchTest{
    16  	{
    17  		Name: "Should retrieve all users in a channel if the search term is empty",
    18  		Fn:   testGetAllUsersInChannelWithEmptyTerm,
    19  		Tags: []string{EngineAll},
    20  	},
    21  	{
    22  		Name: "Should honor channel restrictions when autocompleting users",
    23  		Fn:   testHonorChannelRestrictionsAutocompletingUsers,
    24  		Tags: []string{EngineAll},
    25  	},
    26  	{
    27  		Name: "Should honor team restrictions when autocompleting users",
    28  		Fn:   testHonorTeamRestrictionsAutocompletingUsers,
    29  		Tags: []string{EngineElasticSearch, EngineBleve},
    30  	},
    31  	{
    32  		Name:        "Should return nothing if the user can't access the channels of a given search",
    33  		Fn:          testShouldReturnNothingWithoutProperAccess,
    34  		Tags:        []string{EngineAll},
    35  		Skip:        true,
    36  		SkipMessage: "Failing when the ListOfAllowedChannels property is empty",
    37  	},
    38  	{
    39  		Name: "Should autocomplete for user using username",
    40  		Fn:   testAutocompleteUserByUsername,
    41  		Tags: []string{EngineAll},
    42  	},
    43  	{
    44  		Name: "Should autocomplete user searching by first name",
    45  		Fn:   testAutocompleteUserByFirstName,
    46  		Tags: []string{EngineAll},
    47  	},
    48  	{
    49  		Name: "Should autocomplete user searching by last name",
    50  		Fn:   testAutocompleteUserByLastName,
    51  		Tags: []string{EngineAll},
    52  	},
    53  	{
    54  		Name: "Should autocomplete for user using nickname",
    55  		Fn:   testAutocompleteUserByNickName,
    56  		Tags: []string{EngineAll},
    57  	},
    58  	{
    59  		Name:        "Should autocomplete for user using email",
    60  		Fn:          testAutocompleteUserByEmail,
    61  		Tags:        []string{EngineAll},
    62  		Skip:        true,
    63  		SkipMessage: "Failing for multiple different reasons in the engines",
    64  	},
    65  	{
    66  		Name: "Should be able not to match specific queries with mail",
    67  		Fn:   testShouldNotMatchSpecificQueriesEmail,
    68  		Tags: []string{EngineAll},
    69  	},
    70  	{
    71  		Name: "Should be able to autocomplete a user by part of its username splitted by Dot",
    72  		Fn:   testAutocompleteUserByUsernameWithDot,
    73  		Tags: []string{EngineElasticSearch, EngineBleve},
    74  	},
    75  	{
    76  		Name: "Should be able to autocomplete a user by part of its username splitted by underscore",
    77  		Fn:   testAutocompleteUserByUsernameWithUnderscore,
    78  		Tags: []string{EngineElasticSearch, EngineBleve},
    79  	},
    80  	{
    81  		Name: "Should be able to autocomplete a user by part of its username splitted by hyphen",
    82  		Fn:   testAutocompleteUserByUsernameWithHyphen,
    83  		Tags: []string{EngineElasticSearch, EngineBleve},
    84  	},
    85  	{
    86  		Name: "Should escape the percentage character",
    87  		Fn:   testShouldEscapePercentageCharacter,
    88  		Tags: []string{EngineAll},
    89  	},
    90  	{
    91  		Name: "Should escape the dash character",
    92  		Fn:   testShouldEscapeUnderscoreCharacter,
    93  		Tags: []string{EngineAll},
    94  	},
    95  	{
    96  		Name: "Should be able to search inactive users",
    97  		Fn:   testShouldBeAbleToSearchInactiveUsers,
    98  		Tags: []string{EngineMySql, EnginePostgres, EngineElasticSearch},
    99  	},
   100  	{
   101  		Name: "Should be able to search filtering by role",
   102  		Fn:   testShouldBeAbleToSearchFilteringByRole,
   103  		Tags: []string{EngineMySql, EnginePostgres, EngineElasticSearch},
   104  	},
   105  	{
   106  		Name: "Should ignore leading @ when searching users",
   107  		Fn:   testShouldIgnoreLeadingAtSymbols,
   108  		Tags: []string{EngineAll},
   109  	},
   110  	{
   111  		Name: "Should search users in a case insensitive manner",
   112  		Fn:   testSearchUsersShouldBeCaseInsensitive,
   113  		Tags: []string{EngineAll},
   114  	},
   115  	{
   116  		Name: "Should support one or two character usernames and first/last names in search",
   117  		Fn:   testSearchOneTwoCharUsersnameAndFirstLastNames,
   118  		Tags: []string{EngineAll},
   119  	},
   120  	{
   121  		Name: "Should support Korean characters",
   122  		Fn:   testShouldSupportKoreanCharacters,
   123  		Tags: []string{EngineAll},
   124  	},
   125  	{
   126  		Name: "Should support search with a hyphen at the end of the term",
   127  		Fn:   testSearchWithHyphenAtTheEndOfTheTerm,
   128  		Tags: []string{EngineAll},
   129  	},
   130  	{
   131  		Name: "Should support search all users in a team",
   132  		Fn:   testSearchUsersInTeam,
   133  		Tags: []string{EngineElasticSearch},
   134  	},
   135  	{
   136  		Name: "Should support search users by full name",
   137  		Fn:   testSearchUsersByFullName,
   138  		Tags: []string{EngineAll},
   139  	},
   140  	{
   141  		Name: "Should support search all users in a team with username containing a dot",
   142  		Fn:   testSearchUsersInTeamUsernameWithDot,
   143  		Tags: []string{EngineAll},
   144  	},
   145  	{
   146  		Name: "Should support search all users in a team with username containing a hyphen",
   147  		Fn:   testSearchUsersInTeamUsernameWithHyphen,
   148  		Tags: []string{EngineAll},
   149  	},
   150  	{
   151  		Name: "Should support search all users in a team with username containing a underscore",
   152  		Fn:   testSearchUsersInTeamUsernameWithUnderscore,
   153  		Tags: []string{EngineAll},
   154  	},
   155  }
   156  
   157  func TestSearchUserStore(t *testing.T, s store.Store, testEngine *SearchTestEngine) {
   158  	th := &SearchTestHelper{
   159  		Store: s,
   160  	}
   161  	err := th.SetupBasicFixtures()
   162  	require.NoError(t, err)
   163  	defer th.CleanFixtures()
   164  	runTestSearch(t, testEngine, searchUserStoreTests, th)
   165  }
   166  
   167  func testGetAllUsersInChannelWithEmptyTerm(t *testing.T, th *SearchTestHelper) {
   168  	options := &model.UserSearchOptions{
   169  		AllowFullNames: true,
   170  		Limit:          model.USER_SEARCH_DEFAULT_LIMIT,
   171  	}
   172  	users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   173  	require.NoError(t, err)
   174  	th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   175  	th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   176  
   177  	t.Run("Should be able to correctly honor limit when autocompleting", func(t *testing.T) {
   178  		result, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   179  		require.NoError(t, err)
   180  		require.Len(t, result.InChannel, 1)
   181  		require.Len(t, result.OutOfChannel, 1)
   182  	})
   183  
   184  	t.Run("Return all users in team", func(t *testing.T) {
   185  		options := createDefaultOptions(true, false, false)
   186  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   187  		require.NoError(t, err)
   188  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   189  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   190  	})
   191  
   192  	t.Run("Return all users in teams even though some of them don't have a team associated", func(t *testing.T) {
   193  		options := createDefaultOptions(true, false, false)
   194  		userAlternate, err := th.createUser("user-alternate", "user-alternate", "user", "alternate")
   195  		require.NoError(t, err)
   196  		defer th.deleteUser(userAlternate)
   197  		userGuest, err := th.createGuest("user-guest", "user-guest", "user", "guest")
   198  		require.NoError(t, err)
   199  		defer th.deleteUser(userGuest)
   200  
   201  		// In case teamId and channelId are empty our current logic goes through Search
   202  		users, err := th.Store.User().Search("", "", options)
   203  		require.NoError(t, err)
   204  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, th.UserAnotherTeam,
   205  			userAlternate, userGuest}, users)
   206  	})
   207  }
   208  
   209  func testHonorChannelRestrictionsAutocompletingUsers(t *testing.T, th *SearchTestHelper) {
   210  	userAlternate, err := th.createUser("user-alternate", "user-alternate", "user", "alternate")
   211  	require.NoError(t, err)
   212  	defer th.deleteUser(userAlternate)
   213  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   214  	require.NoError(t, err)
   215  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   216  	require.NoError(t, err)
   217  	guest, err := th.createGuest("guest", "guest", "guest", "one")
   218  	require.NoError(t, err)
   219  	err = th.addUserToTeams(guest, []string{th.Team.Id})
   220  	require.NoError(t, err)
   221  	err = th.addUserToChannels(guest, []string{th.ChannelBasic.Id})
   222  	require.NoError(t, err)
   223  	defer th.deleteUser(guest)
   224  	t.Run("Autocomplete users with channel restrictions", func(t *testing.T) {
   225  		options := createDefaultOptions(true, false, false)
   226  		options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
   227  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   228  		require.NoError(t, err)
   229  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, userAlternate, guest}, users.InChannel)
   230  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   231  	})
   232  	t.Run("Autocomplete users with term and channel restrictions", func(t *testing.T) {
   233  		options := createDefaultOptions(true, false, false)
   234  		options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
   235  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alt", options)
   236  		require.NoError(t, err)
   237  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   238  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   239  	})
   240  	t.Run("Autocomplete users with all channels restricted", func(t *testing.T) {
   241  		options := createDefaultOptions(true, false, false)
   242  		options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
   243  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   244  		require.NoError(t, err)
   245  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
   246  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   247  	})
   248  	t.Run("Autocomplete users with all channels restricted but with empty team", func(t *testing.T) {
   249  		options := createDefaultOptions(true, false, false)
   250  		options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
   251  		users, err := th.Store.User().AutocompleteUsersInChannel("", th.ChannelBasic.Id, "", options)
   252  		require.NoError(t, err)
   253  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
   254  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   255  	})
   256  	t.Run("Autocomplete users with empty team and channels restricted", func(t *testing.T) {
   257  		options := createDefaultOptions(true, false, false)
   258  		options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
   259  		// In case teamId and channelId are empty our current logic goes through Search
   260  		users, err := th.Store.User().Search("", "", options)
   261  		require.NoError(t, err)
   262  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate, guest, th.User}, users)
   263  	})
   264  }
   265  
   266  func testHonorTeamRestrictionsAutocompletingUsers(t *testing.T, th *SearchTestHelper) {
   267  	t.Run("Should return results for users in the team", func(t *testing.T) {
   268  		options := createDefaultOptions(true, false, false)
   269  		options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{th.Team.Id}}
   270  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   271  		require.NoError(t, err)
   272  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   273  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   274  	})
   275  	t.Run("Should return empty because we're filtering all the teams", func(t *testing.T) {
   276  		options := createDefaultOptions(true, false, false)
   277  		options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
   278  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   279  		require.NoError(t, err)
   280  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
   281  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   282  	})
   283  	t.Run("Should return empty when searching in one team and filtering by another", func(t *testing.T) {
   284  		options := createDefaultOptions(true, false, false)
   285  		options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{th.AnotherTeam.Id}}
   286  		users, err := th.Store.User().Search(th.Team.Id, "", options)
   287  		require.NoError(t, err)
   288  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
   289  
   290  		acusers, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   291  		require.NoError(t, err)
   292  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, acusers.InChannel)
   293  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, acusers.OutOfChannel)
   294  	})
   295  }
   296  func testShouldReturnNothingWithoutProperAccess(t *testing.T, th *SearchTestHelper) {
   297  	t.Run("Should return results users for the defined channel in the list", func(t *testing.T) {
   298  		options := createDefaultOptions(true, false, false)
   299  		options.ListOfAllowedChannels = []string{th.ChannelBasic.Id}
   300  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   301  		require.NoError(t, err)
   302  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   303  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   304  	})
   305  	t.Run("Should return empty because we're filtering all the channels", func(t *testing.T) {
   306  		options := createDefaultOptions(true, false, false)
   307  		options.ListOfAllowedChannels = []string{}
   308  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   309  		require.NoError(t, err)
   310  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
   311  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   312  	})
   313  }
   314  func testAutocompleteUserByUsername(t *testing.T, th *SearchTestHelper) {
   315  	userAlternate, err := th.createUser("alternateusername", "alternatenick", "user", "alternate")
   316  	require.NoError(t, err)
   317  	defer th.deleteUser(userAlternate)
   318  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   319  	require.NoError(t, err)
   320  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   321  	require.NoError(t, err)
   322  	options := createDefaultOptions(false, false, false)
   323  	users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
   324  	require.NoError(t, err)
   325  	th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   326  	th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   327  }
   328  func testAutocompleteUserByFirstName(t *testing.T, th *SearchTestHelper) {
   329  	userAlternate, err := th.createUser("user-alternate", "user-alternate", "altfirstname", "lastname")
   330  	require.NoError(t, err)
   331  	defer th.deleteUser(userAlternate)
   332  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   333  	require.NoError(t, err)
   334  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   335  	require.NoError(t, err)
   336  	t.Run("Should autocomplete users when the first name is unique", func(t *testing.T) {
   337  		options := createDefaultOptions(true, false, false)
   338  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "altfirstname", options)
   339  		require.NoError(t, err)
   340  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   341  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   342  	})
   343  	t.Run("Should autocomplete users for in the channel and out of the channel with the same first name", func(t *testing.T) {
   344  		options := createDefaultOptions(true, false, false)
   345  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicfirstname", options)
   346  		require.NoError(t, err)
   347  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   348  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   349  	})
   350  }
   351  func testAutocompleteUserByLastName(t *testing.T, th *SearchTestHelper) {
   352  	userAlternate, err := th.createUser("user-alternate", "user-alternate", "firstname", "altlastname")
   353  	require.NoError(t, err)
   354  	defer th.deleteUser(userAlternate)
   355  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   356  	require.NoError(t, err)
   357  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   358  	require.NoError(t, err)
   359  	t.Run("Should return results when the last name is unique", func(t *testing.T) {
   360  		options := createDefaultOptions(true, false, false)
   361  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "altlastname", options)
   362  		require.NoError(t, err)
   363  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   364  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   365  	})
   366  	t.Run("Should return results for in the channel and out of the channel with the same last name", func(t *testing.T) {
   367  		options := createDefaultOptions(true, false, false)
   368  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basiclastname", options)
   369  		require.NoError(t, err)
   370  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   371  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   372  	})
   373  }
   374  func testAutocompleteUserByNickName(t *testing.T, th *SearchTestHelper) {
   375  	userAlternate, err := th.createUser("alternateusername", "alternatenickname", "firstname", "altlastname")
   376  	require.NoError(t, err)
   377  	defer th.deleteUser(userAlternate)
   378  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   379  	require.NoError(t, err)
   380  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   381  	require.NoError(t, err)
   382  	t.Run("Should return results when the nickname is unique", func(t *testing.T) {
   383  		options := createDefaultOptions(true, false, false)
   384  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternatenickname", options)
   385  		require.NoError(t, err)
   386  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   387  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   388  	})
   389  	t.Run("Should return users that share the same part of the nickname", func(t *testing.T) {
   390  		options := createDefaultOptions(true, false, false)
   391  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicnickname", options)
   392  		require.NoError(t, err)
   393  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   394  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   395  	})
   396  }
   397  func testAutocompleteUserByEmail(t *testing.T, th *SearchTestHelper) {
   398  	userAlternate, err := th.createUser("alternateusername", "alternatenickname", "firstname", "altlastname")
   399  	require.NoError(t, err)
   400  	userAlternate.Email = "useralt@test.email.com"
   401  	_, err = th.Store.User().Update(userAlternate, false)
   402  	require.NoError(t, err)
   403  	defer th.deleteUser(userAlternate)
   404  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   405  	require.NoError(t, err)
   406  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   407  	require.NoError(t, err)
   408  	t.Run("Should autocomplete users when the email is unique", func(t *testing.T) {
   409  		options := createDefaultOptions(false, true, false)
   410  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "useralt@test.email.com", options)
   411  		require.NoError(t, err)
   412  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   413  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   414  	})
   415  	t.Run("Should autocomplete users that share the same email user prefix", func(t *testing.T) {
   416  		options := createDefaultOptions(false, true, false)
   417  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "success_", options)
   418  		require.NoError(t, err)
   419  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   420  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   421  	})
   422  	t.Run("Should autocomplete users that share the same email domain", func(t *testing.T) {
   423  		options := createDefaultOptions(false, true, false)
   424  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "simulator.amazon.com", options)
   425  		require.NoError(t, err)
   426  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   427  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   428  	})
   429  	t.Run("Should search users when the email is unique", func(t *testing.T) {
   430  		options := createDefaultOptions(false, true, false)
   431  		users, err := th.Store.User().Search(th.Team.Id, "useralt@test.email.com", options)
   432  		require.NoError(t, err)
   433  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
   434  	})
   435  	t.Run("Should search users that share the same email user prefix", func(t *testing.T) {
   436  		options := createDefaultOptions(false, true, false)
   437  		users, err := th.Store.User().Search(th.Team.Id, "success_", options)
   438  		require.NoError(t, err)
   439  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
   440  	})
   441  	t.Run("Should search users that share the same email domain", func(t *testing.T) {
   442  		options := createDefaultOptions(false, true, false)
   443  		users, err := th.Store.User().Search(th.Team.Id, "simulator.amazon.com", options)
   444  		require.NoError(t, err)
   445  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
   446  	})
   447  }
   448  func testShouldNotMatchSpecificQueriesEmail(t *testing.T, th *SearchTestHelper) {
   449  	options := createDefaultOptions(false, false, false)
   450  	users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "success_", options)
   451  	require.NoError(t, err)
   452  	th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
   453  	th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   454  }
   455  func testAutocompleteUserByUsernameWithDot(t *testing.T, th *SearchTestHelper) {
   456  	userAlternate, err := th.createUser("alternate.username", "alternatenickname", "firstname", "altlastname")
   457  	require.NoError(t, err)
   458  	defer th.deleteUser(userAlternate)
   459  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   460  	require.NoError(t, err)
   461  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   462  	require.NoError(t, err)
   463  	t.Run("Should return results when searching for the whole username with Dot", func(t *testing.T) {
   464  		options := createDefaultOptions(false, false, false)
   465  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate.username", options)
   466  		require.NoError(t, err)
   467  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   468  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   469  	})
   470  	t.Run("Should return results when searching for part of the username including the Dot", func(t *testing.T) {
   471  		options := createDefaultOptions(false, false, false)
   472  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, ".username", options)
   473  		require.NoError(t, err)
   474  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   475  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   476  	})
   477  	t.Run("Should return results when searching for part of the username not including the Dot", func(t *testing.T) {
   478  		options := createDefaultOptions(false, false, false)
   479  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
   480  		require.NoError(t, err)
   481  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   482  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   483  	})
   484  }
   485  func testAutocompleteUserByUsernameWithUnderscore(t *testing.T, th *SearchTestHelper) {
   486  	userAlternate, err := th.createUser("alternate_username", "alternatenickname", "firstname", "altlastname")
   487  	require.NoError(t, err)
   488  	defer th.deleteUser(userAlternate)
   489  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   490  	require.NoError(t, err)
   491  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   492  	require.NoError(t, err)
   493  	t.Run("Should return results when searching for the whole username with underscore", func(t *testing.T) {
   494  		options := createDefaultOptions(false, false, false)
   495  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate_username", options)
   496  		require.NoError(t, err)
   497  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   498  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   499  	})
   500  	t.Run("Should return results when searching for part of the username including the underscore", func(t *testing.T) {
   501  		options := createDefaultOptions(false, false, false)
   502  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "_username", options)
   503  		require.NoError(t, err)
   504  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   505  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   506  	})
   507  	t.Run("Should return results when searching for part of the username not including the underscore", func(t *testing.T) {
   508  		options := createDefaultOptions(false, false, false)
   509  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
   510  		require.NoError(t, err)
   511  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   512  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   513  	})
   514  }
   515  func testAutocompleteUserByUsernameWithHyphen(t *testing.T, th *SearchTestHelper) {
   516  	userAlternate, err := th.createUser("alternate-username", "alternatenickname", "firstname", "altlastname")
   517  	require.NoError(t, err)
   518  	defer th.deleteUser(userAlternate)
   519  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   520  	require.NoError(t, err)
   521  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   522  	require.NoError(t, err)
   523  	t.Run("Should return results when searching for the whole username with hyphen", func(t *testing.T) {
   524  		options := createDefaultOptions(false, false, false)
   525  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate-username", options)
   526  		require.NoError(t, err)
   527  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   528  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   529  	})
   530  	t.Run("Should return results when searching for part of the username including the hyphen", func(t *testing.T) {
   531  		options := createDefaultOptions(false, false, false)
   532  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "-username", options)
   533  		require.NoError(t, err)
   534  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   535  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   536  	})
   537  	t.Run("Should return results when searching for part of the username not including the hyphen", func(t *testing.T) {
   538  		options := createDefaultOptions(false, false, false)
   539  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
   540  		require.NoError(t, err)
   541  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   542  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   543  	})
   544  }
   545  func testShouldEscapePercentageCharacter(t *testing.T, th *SearchTestHelper) {
   546  	userAlternate, err := th.createUser("alternateusername", "alternate%nickname", "firstname", "altlastname")
   547  	require.NoError(t, err)
   548  
   549  	defer th.deleteUser(userAlternate)
   550  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   551  	require.NoError(t, err)
   552  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   553  	require.NoError(t, err)
   554  	t.Run("Should autocomplete users escaping percentage symbol", func(t *testing.T) {
   555  		options := createDefaultOptions(false, false, false)
   556  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate%", options)
   557  		require.NoError(t, err)
   558  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   559  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   560  	})
   561  	t.Run("Should search users escaping percentage symbol", func(t *testing.T) {
   562  		options := createDefaultOptions(false, false, false)
   563  		users, err := th.Store.User().Search(th.Team.Id, "alternate%", options)
   564  		require.NoError(t, err)
   565  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
   566  	})
   567  }
   568  func testShouldEscapeUnderscoreCharacter(t *testing.T, th *SearchTestHelper) {
   569  	userAlternate, err := th.createUser("alternate_username", "alternatenickname", "firstname", "altlastname")
   570  	require.NoError(t, err)
   571  	defer th.deleteUser(userAlternate)
   572  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   573  	require.NoError(t, err)
   574  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   575  	require.NoError(t, err)
   576  	t.Run("Should autocomplete users escaping underscore symbol", func(t *testing.T) {
   577  		options := createDefaultOptions(false, false, false)
   578  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate_", options)
   579  		require.NoError(t, err)
   580  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   581  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   582  	})
   583  	t.Run("Should search users escaping underscore symbol", func(t *testing.T) {
   584  		options := createDefaultOptions(false, false, false)
   585  		users, err := th.Store.User().Search(th.Team.Id, "alternate_", options)
   586  		require.NoError(t, err)
   587  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
   588  	})
   589  }
   590  
   591  func testShouldBeAbleToSearchInactiveUsers(t *testing.T, th *SearchTestHelper) {
   592  	userAlternate, err := th.createUser("basicusernamealternate", "alternatenickname", "firstname", "altlastname")
   593  	require.NoError(t, err)
   594  	userAlternate.DeleteAt = model.GetMillis()
   595  	_, err = th.Store.User().Update(userAlternate, true)
   596  	require.NoError(t, err)
   597  	defer th.deleteUser(userAlternate)
   598  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   599  	require.NoError(t, err)
   600  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   601  	require.NoError(t, err)
   602  	t.Run("Should autocomplete inactive users if we allow it", func(t *testing.T) {
   603  		options := createDefaultOptions(false, false, true)
   604  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
   605  		require.NoError(t, err)
   606  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, userAlternate}, users.InChannel)
   607  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   608  	})
   609  	t.Run("Should search inactive users if we allow it", func(t *testing.T) {
   610  		options := createDefaultOptions(false, false, true)
   611  		users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
   612  		require.NoError(t, err)
   613  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, userAlternate}, users)
   614  	})
   615  	t.Run("Shouldn't autocomplete inactive users if we don't allow it", func(t *testing.T) {
   616  		options := createDefaultOptions(false, false, false)
   617  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
   618  		require.NoError(t, err)
   619  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   620  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   621  	})
   622  	t.Run("Shouldn't search inactive users if we don't allow it", func(t *testing.T) {
   623  		options := createDefaultOptions(false, false, false)
   624  		users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
   625  		require.NoError(t, err)
   626  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
   627  	})
   628  }
   629  
   630  func testShouldBeAbleToSearchFilteringByRole(t *testing.T, th *SearchTestHelper) {
   631  	userAlternate, err := th.createUser("basicusernamealternate", "alternatenickname", "firstname", "altlastname")
   632  	require.NoError(t, err)
   633  	userAlternate.Roles = "system_admin system_user"
   634  	_, err = th.Store.User().Update(userAlternate, true)
   635  	require.NoError(t, err)
   636  	defer th.deleteUser(userAlternate)
   637  	userAlternate2, err := th.createUser("basicusernamealternate2", "alternatenickname2", "firstname2", "altlastname2")
   638  	require.NoError(t, err)
   639  	userAlternate2.Roles = "system_user"
   640  	_, err = th.Store.User().Update(userAlternate2, true)
   641  	require.NoError(t, err)
   642  	defer th.deleteUser(userAlternate2)
   643  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   644  	require.NoError(t, err)
   645  	err = th.addUserToTeams(userAlternate2, []string{th.Team.Id})
   646  	require.NoError(t, err)
   647  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   648  	require.NoError(t, err)
   649  	t.Run("Should autocomplete users filtering by roles", func(t *testing.T) {
   650  		options := createDefaultOptions(false, false, true)
   651  		options.Role = "system_admin"
   652  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
   653  		require.NoError(t, err)
   654  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   655  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   656  	})
   657  	t.Run("Should search users filtering by roles", func(t *testing.T) {
   658  		options := createDefaultOptions(false, false, true)
   659  		options.Role = "system_admin"
   660  		users, err := th.Store.User().Search(th.Team.Id, "", options)
   661  		require.NoError(t, err)
   662  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
   663  	})
   664  }
   665  
   666  func testShouldIgnoreLeadingAtSymbols(t *testing.T, th *SearchTestHelper) {
   667  	t.Run("Should autocomplete ignoring the @ symbol at the beginning", func(t *testing.T) {
   668  		options := createDefaultOptions(false, false, false)
   669  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "@basicusername", options)
   670  		require.NoError(t, err)
   671  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   672  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   673  	})
   674  	t.Run("Should search ignoring the @ symbol at the beginning", func(t *testing.T) {
   675  		options := createDefaultOptions(false, false, false)
   676  		users, err := th.Store.User().Search(th.Team.Id, "@basicusername", options)
   677  		require.NoError(t, err)
   678  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
   679  	})
   680  }
   681  
   682  func testSearchUsersShouldBeCaseInsensitive(t *testing.T, th *SearchTestHelper) {
   683  	options := createDefaultOptions(false, false, false)
   684  	users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "BaSiCUsErNaMe", options)
   685  	require.NoError(t, err)
   686  	th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
   687  	th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
   688  }
   689  
   690  func testSearchOneTwoCharUsersnameAndFirstLastNames(t *testing.T, th *SearchTestHelper) {
   691  	userAlternate, err := th.createUser("ho", "alternatenickname", "zi", "k")
   692  	require.NoError(t, err)
   693  
   694  	defer th.deleteUser(userAlternate)
   695  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   696  	require.NoError(t, err)
   697  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   698  	require.NoError(t, err)
   699  	t.Run("Should support two characters in the full name", func(t *testing.T) {
   700  		options := createDefaultOptions(true, false, false)
   701  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "zi", options)
   702  		require.NoError(t, err)
   703  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   704  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   705  	})
   706  	t.Run("Should support two characters in the username", func(t *testing.T) {
   707  		options := createDefaultOptions(true, false, false)
   708  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "ho", options)
   709  		require.NoError(t, err)
   710  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   711  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   712  	})
   713  }
   714  
   715  func testShouldSupportKoreanCharacters(t *testing.T, th *SearchTestHelper) {
   716  	userAlternate, err := th.createUser("alternate-username", "alternate-nickname", "서강준", "안신원")
   717  	require.NoError(t, err)
   718  	defer th.deleteUser(userAlternate)
   719  
   720  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   721  	require.NoError(t, err)
   722  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   723  	require.NoError(t, err)
   724  	t.Run("Should support hanja korean characters", func(t *testing.T) {
   725  		options := createDefaultOptions(true, false, false)
   726  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "서강준", options)
   727  		require.NoError(t, err)
   728  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   729  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   730  	})
   731  	t.Run("Should support hangul korean characters", func(t *testing.T) {
   732  		options := createDefaultOptions(true, false, false)
   733  		users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "안신원", options)
   734  		require.NoError(t, err)
   735  		th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   736  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   737  	})
   738  }
   739  
   740  func testSearchWithHyphenAtTheEndOfTheTerm(t *testing.T, th *SearchTestHelper) {
   741  	userAlternate, err := th.createUser("alternate-username", "alternate-nickname", "altfirst", "altlast")
   742  	require.NoError(t, err)
   743  	defer th.deleteUser(userAlternate)
   744  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   745  	require.NoError(t, err)
   746  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   747  	require.NoError(t, err)
   748  	options := createDefaultOptions(true, false, false)
   749  	users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate-", options)
   750  	require.NoError(t, err)
   751  	th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
   752  	th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
   753  }
   754  
   755  func testSearchUsersInTeam(t *testing.T, th *SearchTestHelper) {
   756  	t.Run("Should return all the team users", func(t *testing.T) {
   757  		options := createDefaultOptions(false, false, false)
   758  		users, err := th.Store.User().Search(th.Team.Id, "", options)
   759  		require.NoError(t, err)
   760  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
   761  	})
   762  	t.Run("Should return all the team users with no team id", func(t *testing.T) {
   763  		options := createDefaultOptions(false, false, false)
   764  		users, err := th.Store.User().Search("", "basicusername", options)
   765  		require.NoError(t, err)
   766  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, th.UserAnotherTeam}, users)
   767  	})
   768  	t.Run("Should return all the team users filtered by username", func(t *testing.T) {
   769  		options := createDefaultOptions(false, false, false)
   770  		users, err := th.Store.User().Search(th.Team.Id, "basicusername1", options)
   771  		require.NoError(t, err)
   772  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
   773  	})
   774  	t.Run("Should not return spurious results", func(t *testing.T) {
   775  		options := createDefaultOptions(false, false, false)
   776  		users, err := th.Store.User().Search(th.Team.Id, "falseuser", options)
   777  		require.NoError(t, err)
   778  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
   779  	})
   780  	t.Run("Should return all the team users filtered by username and with channel restrictions", func(t *testing.T) {
   781  		options := createDefaultOptions(false, false, false)
   782  		options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
   783  		users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
   784  		require.NoError(t, err)
   785  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
   786  	})
   787  	t.Run("Should return all the team users filtered by username and with all channel restricted", func(t *testing.T) {
   788  		options := createDefaultOptions(false, false, false)
   789  		options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{}}
   790  		users, err := th.Store.User().Search(th.Team.Id, "basicusername1", options)
   791  		require.NoError(t, err)
   792  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
   793  	})
   794  	t.Run("Should honor the limit when searching users in team", func(t *testing.T) {
   795  		optionsWithLimit := &model.UserSearchOptions{
   796  			Limit: 1,
   797  		}
   798  
   799  		users, err := th.Store.User().Search(th.Team.Id, "", optionsWithLimit)
   800  		require.NoError(t, err)
   801  		require.Len(t, users, 1)
   802  	})
   803  }
   804  
   805  func testSearchUsersInTeamUsernameWithDot(t *testing.T, th *SearchTestHelper) {
   806  	userAlternate, err := th.createUser("alternate.username", "altnickname", "altfirst", "altlast")
   807  	require.NoError(t, err)
   808  	defer th.deleteUser(userAlternate)
   809  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   810  	require.NoError(t, err)
   811  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   812  	require.NoError(t, err)
   813  	options := createDefaultOptions(true, false, false)
   814  	users, err := th.Store.User().Search(th.Team.Id, "alternate.", options)
   815  	require.NoError(t, err)
   816  	th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
   817  }
   818  
   819  func testSearchUsersInTeamUsernameWithHyphen(t *testing.T, th *SearchTestHelper) {
   820  	userAlternate, err := th.createUser("alternate-username", "altnickname", "altfirst", "altlast")
   821  	require.NoError(t, err)
   822  	defer th.deleteUser(userAlternate)
   823  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   824  	require.NoError(t, err)
   825  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   826  	require.NoError(t, err)
   827  	options := createDefaultOptions(true, false, false)
   828  	users, err := th.Store.User().Search(th.Team.Id, "alternate-", options)
   829  	require.NoError(t, err)
   830  	th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
   831  }
   832  
   833  func testSearchUsersInTeamUsernameWithUnderscore(t *testing.T, th *SearchTestHelper) {
   834  	userAlternate, err := th.createUser("alternate_username", "altnickname", "altfirst", "altlast")
   835  	require.NoError(t, err)
   836  	defer th.deleteUser(userAlternate)
   837  	err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
   838  	require.NoError(t, err)
   839  	err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
   840  	require.NoError(t, err)
   841  	options := createDefaultOptions(true, false, false)
   842  	users, err := th.Store.User().Search(th.Team.Id, "alternate_", options)
   843  	require.NoError(t, err)
   844  	th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
   845  }
   846  
   847  func testSearchUsersByFullName(t *testing.T, th *SearchTestHelper) {
   848  	t.Run("Should search users by full name", func(t *testing.T) {
   849  		options := createDefaultOptions(true, false, false)
   850  		users, err := th.Store.User().Search(th.Team.Id, "basicfirstname", options)
   851  		require.NoError(t, err)
   852  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
   853  	})
   854  	t.Run("Should search user by full name", func(t *testing.T) {
   855  		options := createDefaultOptions(true, false, false)
   856  		users, err := th.Store.User().Search(th.Team.Id, "basicfirstname1", options)
   857  		require.NoError(t, err)
   858  		th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
   859  	})
   860  	t.Run("Should return empty when search by full name and is deactivated", func(t *testing.T) {
   861  		options := createDefaultOptions(false, false, false)
   862  		users, err := th.Store.User().Search(th.Team.Id, "basicfirstname1", options)
   863  		require.NoError(t, err)
   864  		th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
   865  	})
   866  }
   867  
   868  func createDefaultOptions(allowFullName, allowEmails, allowInactive bool) *model.UserSearchOptions {
   869  	return &model.UserSearchOptions{
   870  		AllowFullNames: allowFullName,
   871  		AllowEmails:    allowEmails,
   872  		AllowInactive:  allowInactive,
   873  		Limit:          model.USER_SEARCH_DEFAULT_LIMIT,
   874  	}
   875  }