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