Mono repo -> Master (#22553)
Combines the following repositories into one: https://github.com/mattermost/mattermost-server https://github.com/mattermost/mattermost-webapp https://github.com/mattermost/focalboard https://github.com/mattermost/mattermost-plugin-playbooks
Этот коммит содержится в:
233
server/channels/store/searchtest/channel_layer.go
Обычный файл
233
server/channels/store/searchtest/channel_layer.go
Обычный файл
@@ -0,0 +1,233 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package searchtest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/server/channels/store"
|
||||
)
|
||||
|
||||
var searchChannelStoreTests = []searchTest{
|
||||
{
|
||||
Name: "Should be able to autocomplete a channel by name",
|
||||
Fn: testAutocompleteChannelByName,
|
||||
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a channel by name (Postgres)",
|
||||
Fn: testAutocompleteChannelByNamePostgres,
|
||||
Tags: []string{EnginePostgres},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a channel by display name",
|
||||
Fn: testAutocompleteChannelByDisplayName,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by - character",
|
||||
Fn: testAutocompleteChannelByNameSplittedWithDashChar,
|
||||
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by - character (Postgres)",
|
||||
Fn: testAutocompleteChannelByNameSplittedWithDashCharPostgres,
|
||||
Tags: []string{EnginePostgres},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a channel by a part of its name when has parts splitted by _ character",
|
||||
Fn: testAutocompleteChannelByNameSplittedWithUnderscoreChar,
|
||||
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a channel by a part of its display name when has parts splitted by whitespace character",
|
||||
Fn: testAutocompleteChannelByDisplayNameSplittedByWhitespaces,
|
||||
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete retrieving all channels if the term is empty",
|
||||
Fn: testAutocompleteAllChannelsIfTermIsEmpty,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete channels in a case insensitive manner",
|
||||
Fn: testSearchChannelsInCaseInsensitiveManner,
|
||||
Tags: []string{EngineMySql, EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete channels in a case insensitive manner (Postgres)",
|
||||
Fn: testSearchChannelsInCaseInsensitiveMannerPostgres,
|
||||
Tags: []string{EnginePostgres},
|
||||
},
|
||||
{
|
||||
Name: "Should support to autocomplete having a hyphen as the last character",
|
||||
Fn: testSearchShouldSupportHavingHyphenAsLastCharacter,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support to autocomplete with archived channels",
|
||||
Fn: testSearchShouldSupportAutocompleteWithArchivedChannels,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
}
|
||||
|
||||
func TestSearchChannelStore(t *testing.T, s store.Store, testEngine *SearchTestEngine) {
|
||||
th := &SearchTestHelper{
|
||||
Store: s,
|
||||
}
|
||||
err := th.SetupBasicFixtures()
|
||||
require.NoError(t, err)
|
||||
defer th.CleanFixtures()
|
||||
runTestSearch(t, testEngine, searchChannelStoreTests, th)
|
||||
}
|
||||
|
||||
func testAutocompleteChannelByName(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "Channel Alternate", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
|
||||
private, err := th.createChannel(th.Team.Id, "channel-altprivate", "Channel AltPrivate", "Channel Private", model.ChannelTypePrivate, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(private)
|
||||
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id}, res)
|
||||
|
||||
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id, th.ChannelAnotherTeam.Id}, res2)
|
||||
}
|
||||
|
||||
func testAutocompleteChannelByNamePostgres(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "Channel Alternate", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
|
||||
}
|
||||
|
||||
func testAutocompleteChannelByDisplayName(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
|
||||
private, err := th.createChannel(th.Team.Id, "channel-altprivate", "ChannelAltPrivate", "Channel Private", model.ChannelTypePrivate, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(private)
|
||||
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChannelA", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id}, res)
|
||||
|
||||
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "ChannelA", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelBasic.Id, alternate.Id, private.Id, th.ChannelAnotherTeam.Id}, res2)
|
||||
}
|
||||
|
||||
func testAutocompleteChannelByNameSplittedWithDashChar(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
|
||||
}
|
||||
|
||||
func testAutocompleteChannelByNameSplittedWithDashCharPostgres(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
|
||||
}
|
||||
|
||||
func testAutocompleteChannelByNameSplittedWithUnderscoreChar(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel_alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel_a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{alternate.Id}, res)
|
||||
|
||||
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel_a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatchWithTeamData(t, []string{alternate.Id}, res2)
|
||||
}
|
||||
|
||||
func testAutocompleteChannelByDisplayNameSplittedByWhitespaces(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "Channel A", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{alternate.Id}, res)
|
||||
}
|
||||
func testAutocompleteAllChannelsIfTermIsEmpty(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "Channel Alternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
other, err := th.createChannel(th.Team.Id, "other-channel", "Other Channel", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
defer th.deleteChannel(other)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id, other.Id}, res)
|
||||
}
|
||||
|
||||
func testSearchChannelsInCaseInsensitiveManner(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channela", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
|
||||
res, err = th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChAnNeL-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
|
||||
|
||||
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channela", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, alternate.Id}, res2)
|
||||
res2, err = th.Store.Channel().Autocomplete(th.User.Id, "ChAnNeL-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, alternate.Id}, res2)
|
||||
}
|
||||
|
||||
func testSearchChannelsInCaseInsensitiveMannerPostgres(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channela", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, alternate.Id}, res)
|
||||
res, err = th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "ChAnNeL-a", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
|
||||
}
|
||||
|
||||
func testSearchShouldSupportHavingHyphenAsLastCharacter(t *testing.T, th *SearchTestHelper) {
|
||||
alternate, err := th.createChannel(th.Team.Id, "channel-alternate", "ChannelAlternate", "", model.ChannelTypeOpen, th.User, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteChannel(alternate)
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res)
|
||||
|
||||
res2, err := th.Store.Channel().Autocomplete(th.User.Id, "channel-", false, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatchWithTeamData(t, []string{th.ChannelAnotherTeam.Id, th.ChannelBasic.Id, th.ChannelPrivate.Id, alternate.Id}, res2)
|
||||
}
|
||||
|
||||
func testSearchShouldSupportAutocompleteWithArchivedChannels(t *testing.T, th *SearchTestHelper) {
|
||||
res, err := th.Store.Channel().AutocompleteInTeam(th.Team.Id, th.User.Id, "channel-", true, false)
|
||||
require.NoError(t, err)
|
||||
th.checkChannelIdsMatch(t, []string{th.ChannelBasic.Id, th.ChannelPrivate.Id, th.ChannelDeleted.Id}, res)
|
||||
}
|
||||
1646
server/channels/store/searchtest/file_info_layer.go
Обычный файл
1646
server/channels/store/searchtest/file_info_layer.go
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
512
server/channels/store/searchtest/helper.go
Обычный файл
512
server/channels/store/searchtest/helper.go
Обычный файл
@@ -0,0 +1,512 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package searchtest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/server/channels/store"
|
||||
)
|
||||
|
||||
type SearchTestHelper struct {
|
||||
Store store.Store
|
||||
Team *model.Team
|
||||
AnotherTeam *model.Team
|
||||
User *model.User
|
||||
User2 *model.User
|
||||
UserAnotherTeam *model.User
|
||||
ChannelBasic *model.Channel
|
||||
ChannelPrivate *model.Channel
|
||||
ChannelAnotherTeam *model.Channel
|
||||
ChannelDeleted *model.Channel
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) SetupBasicFixtures() error {
|
||||
// Remove users from previous tests
|
||||
err := th.cleanAllUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create teams
|
||||
team, err := th.createTeam("searchtest-team", "Searchtest team", model.TeamOpen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
anotherTeam, err := th.createTeam("another-searchtest-team", "Another Searchtest team", model.TeamOpen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create users
|
||||
user, err := th.createUser("basicusername1", "basicnickname1", "basicfirstname1", "basiclastname1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user2, err := th.createUser("basicusername2", "basicnickname2", "basicfirstname2", "basiclastname2")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
useranother, err := th.createUser("basicusername3", "basicnickname3", "basicfirstname3", "basiclastname3")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create channels
|
||||
channelBasic, err := th.createChannel(team.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
channelPrivate, err := th.createChannel(team.Id, "channel-private", "ChannelPrivate", "", model.ChannelTypePrivate, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
channelDeleted, err := th.createChannel(team.Id, "channel-deleted", "ChannelA (deleted)", "", model.ChannelTypeOpen, nil, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
channelAnotherTeam, err := th.createChannel(anotherTeam.Id, "channel-a", "ChannelA", "", model.ChannelTypeOpen, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.addUserToTeams(user, []string{team.Id, anotherTeam.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.addUserToTeams(user2, []string{team.Id, anotherTeam.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.addUserToTeams(useranother, []string{anotherTeam.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.addUserToChannels(user, []string{channelBasic.Id, channelPrivate.Id, channelDeleted.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.addUserToChannels(user2, []string{channelPrivate.Id, channelDeleted.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.addUserToChannels(useranother, []string{channelAnotherTeam.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
th.Team = team
|
||||
th.AnotherTeam = anotherTeam
|
||||
th.User = user
|
||||
th.User2 = user2
|
||||
th.UserAnotherTeam = useranother
|
||||
th.ChannelBasic = channelBasic
|
||||
th.ChannelPrivate = channelPrivate
|
||||
th.ChannelAnotherTeam = channelAnotherTeam
|
||||
th.ChannelDeleted = channelDeleted
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) CleanFixtures() error {
|
||||
err := th.deleteChannels([]*model.Channel{
|
||||
th.ChannelBasic, th.ChannelPrivate, th.ChannelAnotherTeam, th.ChannelDeleted,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.deleteTeam(th.Team)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.deleteTeam(th.AnotherTeam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.cleanAllUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createTeam(name, displayName, teamType string) (*model.Team, error) {
|
||||
return th.Store.Team().Save(&model.Team{
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Type: teamType,
|
||||
})
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteTeam(team *model.Team) error {
|
||||
err := th.Store.Team().RemoveAllMembersByTeam(team.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return th.Store.Team().PermanentDelete(team.Id)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) makeEmail() string {
|
||||
return "success_" + model.NewId() + "@simulator.amazon.com"
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createUser(username, nickname, firstName, lastName string) (*model.User, error) {
|
||||
return th.Store.User().Save(&model.User{
|
||||
Username: username,
|
||||
Password: username,
|
||||
Nickname: nickname,
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: th.makeEmail(),
|
||||
})
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createGuest(username, nickname, firstName, lastName string) (*model.User, error) {
|
||||
return th.Store.User().Save(&model.User{
|
||||
Username: username,
|
||||
Password: username,
|
||||
Nickname: nickname,
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Email: th.makeEmail(),
|
||||
Roles: model.SystemGuestRoleId,
|
||||
})
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteUser(user *model.User) error {
|
||||
return th.Store.User().PermanentDelete(user.Id)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteBotUser(botID string) error {
|
||||
if err := th.deleteBot(botID); err != nil {
|
||||
return err
|
||||
}
|
||||
return th.Store.User().PermanentDelete(botID)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) cleanAllUsers() error {
|
||||
users, err := th.Store.User().GetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, u := range users {
|
||||
err := th.deleteUser(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createBot(username, displayName, ownerID string) (*model.Bot, error) {
|
||||
botModel := &model.Bot{
|
||||
Username: username,
|
||||
DisplayName: displayName,
|
||||
OwnerId: ownerID,
|
||||
}
|
||||
|
||||
user, err := th.Store.User().Save(model.UserFromBot(botModel))
|
||||
if err != nil {
|
||||
return nil, errors.New(err.Error())
|
||||
}
|
||||
|
||||
botModel.UserId = user.Id
|
||||
bot, err := th.Store.Bot().Save(botModel)
|
||||
if err != nil {
|
||||
th.Store.User().PermanentDelete(bot.UserId)
|
||||
return nil, errors.New(err.Error())
|
||||
}
|
||||
|
||||
return bot, nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteBot(botID string) error {
|
||||
err := th.Store.Bot().PermanentDelete(botID)
|
||||
if err != nil {
|
||||
return errors.New(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createChannel(teamID, name, displayName, purpose string, channelType model.ChannelType, user *model.User, deleted bool) (*model.Channel, error) {
|
||||
channel, err := th.Store.Channel().Save(&model.Channel{
|
||||
TeamId: teamID,
|
||||
DisplayName: displayName,
|
||||
Name: name,
|
||||
Type: channelType,
|
||||
Purpose: purpose,
|
||||
}, 999)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
err = th.addUserToChannels(user, []string{channel.Id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if deleted {
|
||||
err := th.Store.Channel().Delete(channel.Id, model.GetMillis())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createDirectChannel(teamID, name, displayName string, users []*model.User) (*model.Channel, error) {
|
||||
channel := &model.Channel{
|
||||
TeamId: teamID,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Type: model.ChannelTypeDirect,
|
||||
}
|
||||
|
||||
m1 := &model.ChannelMember{}
|
||||
m1.ChannelId = channel.Id
|
||||
m1.UserId = users[0].Id
|
||||
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
|
||||
|
||||
m2 := &model.ChannelMember{}
|
||||
m2.ChannelId = channel.Id
|
||||
m2.UserId = users[0].Id
|
||||
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
|
||||
|
||||
channel, err := th.Store.Channel().SaveDirectChannel(channel, m1, m2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createGroupChannel(teamID, displayName string, users []*model.User) (*model.Channel, error) {
|
||||
userIDS := make([]string, len(users))
|
||||
for _, user := range users {
|
||||
userIDS = append(userIDS, user.Id)
|
||||
}
|
||||
|
||||
group := &model.Channel{
|
||||
TeamId: teamID,
|
||||
Name: model.GetGroupNameFromUserIds(userIDS),
|
||||
DisplayName: displayName,
|
||||
Type: model.ChannelTypeGroup,
|
||||
}
|
||||
|
||||
channel, err := th.Store.Channel().Save(group, 10000)
|
||||
if err != nil {
|
||||
return nil, errors.New(err.Error())
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
err := th.addUserToChannels(user, []string{channel.Id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return channel, nil
|
||||
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteChannel(channel *model.Channel) error {
|
||||
err := th.Store.Channel().PermanentDeleteMembersByChannel(channel.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return th.Store.Channel().PermanentDelete(channel.Id)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteChannels(channels []*model.Channel) error {
|
||||
for _, channel := range channels {
|
||||
err := th.deleteChannel(channel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createPostModel(userID, channelID, message, hashtags, postType string, createAt int64, pinned bool) *model.Post {
|
||||
return &model.Post{
|
||||
Message: message,
|
||||
ChannelId: channelID,
|
||||
PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()),
|
||||
UserId: userID,
|
||||
Hashtags: hashtags,
|
||||
IsPinned: pinned,
|
||||
CreateAt: createAt,
|
||||
Type: postType,
|
||||
}
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createPost(userID, channelID, message, hashtags, postType string, createAt int64, pinned bool) (*model.Post, error) {
|
||||
var creationTime int64 = 1000000
|
||||
if createAt > 0 {
|
||||
creationTime = createAt
|
||||
}
|
||||
postModel := th.createPostModel(userID, channelID, message, hashtags, postType, creationTime, pinned)
|
||||
return th.Store.Post().Save(postModel)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createFileInfoModel(creatorID, postID, name, content, extension, mimeType string, createAt, size int64) *model.FileInfo {
|
||||
return &model.FileInfo{
|
||||
CreatorId: creatorID,
|
||||
PostId: postID,
|
||||
CreateAt: createAt,
|
||||
UpdateAt: createAt,
|
||||
DeleteAt: 0,
|
||||
Name: name,
|
||||
Content: content,
|
||||
Path: name,
|
||||
Extension: extension,
|
||||
Size: size,
|
||||
MimeType: mimeType,
|
||||
}
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createFileInfo(creatorID, postID, name, content, extension, mimeType string, createAt, size int64) (*model.FileInfo, error) {
|
||||
var creationTime int64 = 1000000
|
||||
if createAt > 0 {
|
||||
creationTime = createAt
|
||||
}
|
||||
fileInfoModel := th.createFileInfoModel(creatorID, postID, name, content, extension, mimeType, creationTime, size)
|
||||
return th.Store.FileInfo().Save(fileInfoModel)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) createReply(userID, message, hashtags string, parent *model.Post, createAt int64, pinned bool) (*model.Post, error) {
|
||||
replyModel := th.createPostModel(userID, parent.ChannelId, message, hashtags, parent.Type, createAt, pinned)
|
||||
replyModel.RootId = parent.Id
|
||||
return th.Store.Post().Save(replyModel)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteUserPosts(userID string) error {
|
||||
err := th.Store.Post().PermanentDeleteByUser(userID)
|
||||
if err != nil {
|
||||
return errors.New(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) deleteUserFileInfos(userID string) error {
|
||||
if _, err := th.Store.FileInfo().PermanentDeleteByUser(userID); err != nil {
|
||||
return errors.New(err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) addUserToTeams(user *model.User, teamIDS []string) error {
|
||||
for _, teamID := range teamIDS {
|
||||
_, err := th.Store.Team().SaveMember(&model.TeamMember{TeamId: teamID, UserId: user.Id}, -1)
|
||||
if err != nil {
|
||||
return errors.New(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) addUserToChannels(user *model.User, channelIDS []string) error {
|
||||
for _, channelID := range channelIDS {
|
||||
_, err := th.Store.Channel().SaveMember(&model.ChannelMember{
|
||||
ChannelId: channelID,
|
||||
UserId: user.Id,
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
})
|
||||
if err != nil {
|
||||
return errors.New(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) assertUsersMatchInAnyOrder(t *testing.T, expected, actual []*model.User) {
|
||||
expectedUsernames := make([]string, 0, len(expected))
|
||||
for _, user := range expected {
|
||||
user.Sanitize(map[string]bool{})
|
||||
expectedUsernames = append(expectedUsernames, user.Username)
|
||||
}
|
||||
|
||||
actualUsernames := make([]string, 0, len(actual))
|
||||
for _, user := range actual {
|
||||
user.Sanitize(map[string]bool{})
|
||||
actualUsernames = append(actualUsernames, user.Username)
|
||||
}
|
||||
|
||||
if assert.ElementsMatch(t, expectedUsernames, actualUsernames) {
|
||||
assert.ElementsMatch(t, expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) checkPostInSearchResults(t *testing.T, postID string, searchResults map[string]*model.Post) {
|
||||
t.Helper()
|
||||
postIDS := make([]string, len(searchResults))
|
||||
for ID := range searchResults {
|
||||
postIDS = append(postIDS, ID)
|
||||
}
|
||||
assert.Contains(t, postIDS, postID, "Did not find expected post in search results.")
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) checkFileInfoInSearchResults(t *testing.T, fileID string, searchResults map[string]*model.FileInfo) {
|
||||
t.Helper()
|
||||
fileIDS := make([]string, len(searchResults))
|
||||
for ID := range searchResults {
|
||||
fileIDS = append(fileIDS, ID)
|
||||
}
|
||||
assert.Contains(t, fileIDS, fileID, "Did not find expected file in search results.")
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) checkChannelIdsMatch(t *testing.T, expected []string, results model.ChannelList) {
|
||||
t.Helper()
|
||||
channelIds := make([]string, len(results))
|
||||
for i, channel := range results {
|
||||
channelIds[i] = channel.Id
|
||||
}
|
||||
require.ElementsMatch(t, expected, channelIds)
|
||||
}
|
||||
|
||||
func (th *SearchTestHelper) checkChannelIdsMatchWithTeamData(t *testing.T, expected []string, results model.ChannelListWithTeamData) {
|
||||
t.Helper()
|
||||
channelIds := make([]string, len(results))
|
||||
for i, channel := range results {
|
||||
channelIds[i] = channel.Id
|
||||
}
|
||||
require.ElementsMatch(t, expected, channelIds)
|
||||
}
|
||||
|
||||
type ByChannelDisplayName model.ChannelList
|
||||
|
||||
func (s ByChannelDisplayName) Len() int { return len(s) }
|
||||
func (s ByChannelDisplayName) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
func (s ByChannelDisplayName) Less(i, j int) bool {
|
||||
if s[i].DisplayName != s[j].DisplayName {
|
||||
return s[i].DisplayName < s[j].DisplayName
|
||||
}
|
||||
|
||||
return s[i].Id < s[j].Id
|
||||
}
|
||||
1845
server/channels/store/searchtest/post_layer.go
Обычный файл
1845
server/channels/store/searchtest/post_layer.go
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
78
server/channels/store/searchtest/testlib.go
Обычный файл
78
server/channels/store/searchtest/testlib.go
Обычный файл
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package searchtest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/server/channels/store"
|
||||
"github.com/mattermost/mattermost-server/v6/server/channels/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
EngineAll = "all"
|
||||
EngineMySql = "mysql"
|
||||
EnginePostgres = "postgres"
|
||||
EngineElasticSearch = "elasticsearch"
|
||||
EngineBleve = "bleve"
|
||||
)
|
||||
|
||||
type SearchTestEngine struct {
|
||||
Driver string
|
||||
BeforeTest func(*testing.T, store.Store)
|
||||
AfterTest func(*testing.T, store.Store)
|
||||
}
|
||||
|
||||
type searchTest struct {
|
||||
Name string
|
||||
Fn func(*testing.T, *SearchTestHelper)
|
||||
Tags []string
|
||||
Skip bool
|
||||
SkipMessage string
|
||||
}
|
||||
|
||||
func filterTestsByTag(tests []searchTest, tags ...string) []searchTest {
|
||||
filteredTests := []searchTest{}
|
||||
for _, test := range tests {
|
||||
if utils.StringInSlice(EngineAll, test.Tags) {
|
||||
filteredTests = append(filteredTests, test)
|
||||
continue
|
||||
}
|
||||
for _, tag := range tags {
|
||||
if utils.StringInSlice(tag, test.Tags) {
|
||||
filteredTests = append(filteredTests, test)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredTests
|
||||
}
|
||||
|
||||
func runTestSearch(t *testing.T, testEngine *SearchTestEngine, tests []searchTest, th *SearchTestHelper) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping advanced search test")
|
||||
return
|
||||
}
|
||||
|
||||
filteredTests := filterTestsByTag(tests, testEngine.Driver)
|
||||
|
||||
for _, test := range filteredTests {
|
||||
|
||||
if test.Skip {
|
||||
t.Log("SKIPPED: " + test.Name + ". Reason: " + test.SkipMessage)
|
||||
continue
|
||||
}
|
||||
|
||||
if testEngine.BeforeTest != nil {
|
||||
testEngine.BeforeTest(t, th.Store)
|
||||
}
|
||||
testName := test.Name
|
||||
testFn := test.Fn
|
||||
t.Run(testName, func(t *testing.T) { testFn(t, th) })
|
||||
if testEngine.AfterTest != nil {
|
||||
testEngine.AfterTest(t, th.Store)
|
||||
}
|
||||
}
|
||||
}
|
||||
875
server/channels/store/searchtest/user_layer.go
Обычный файл
875
server/channels/store/searchtest/user_layer.go
Обычный файл
@@ -0,0 +1,875 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package searchtest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/server/channels/store"
|
||||
)
|
||||
|
||||
var searchUserStoreTests = []searchTest{
|
||||
{
|
||||
Name: "Should retrieve all users in a channel if the search term is empty",
|
||||
Fn: testGetAllUsersInChannelWithEmptyTerm,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should honor channel restrictions when autocompleting users",
|
||||
Fn: testHonorChannelRestrictionsAutocompletingUsers,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should honor team restrictions when autocompleting users",
|
||||
Fn: testHonorTeamRestrictionsAutocompletingUsers,
|
||||
Tags: []string{EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should return nothing if the user can't access the channels of a given search",
|
||||
Fn: testShouldReturnNothingWithoutProperAccess,
|
||||
Tags: []string{EngineAll},
|
||||
Skip: true,
|
||||
SkipMessage: "Failing when the ListOfAllowedChannels property is empty",
|
||||
},
|
||||
{
|
||||
Name: "Should autocomplete for user using username",
|
||||
Fn: testAutocompleteUserByUsername,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should autocomplete user searching by first name",
|
||||
Fn: testAutocompleteUserByFirstName,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should autocomplete user searching by last name",
|
||||
Fn: testAutocompleteUserByLastName,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should autocomplete for user using nickname",
|
||||
Fn: testAutocompleteUserByNickName,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should autocomplete for user using email",
|
||||
Fn: testAutocompleteUserByEmail,
|
||||
Tags: []string{EngineAll},
|
||||
Skip: true,
|
||||
SkipMessage: "Failing for multiple different reasons in the engines",
|
||||
},
|
||||
{
|
||||
Name: "Should be able not to match specific queries with mail",
|
||||
Fn: testShouldNotMatchSpecificQueriesEmail,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a user by part of its username splitted by Dot",
|
||||
Fn: testAutocompleteUserByUsernameWithDot,
|
||||
Tags: []string{EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a user by part of its username splitted by underscore",
|
||||
Fn: testAutocompleteUserByUsernameWithUnderscore,
|
||||
Tags: []string{EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to autocomplete a user by part of its username splitted by hyphen",
|
||||
Fn: testAutocompleteUserByUsernameWithHyphen,
|
||||
Tags: []string{EngineElasticSearch, EngineBleve},
|
||||
},
|
||||
{
|
||||
Name: "Should escape the percentage character",
|
||||
Fn: testShouldEscapePercentageCharacter,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should escape the dash character",
|
||||
Fn: testShouldEscapeUnderscoreCharacter,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to search inactive users",
|
||||
Fn: testShouldBeAbleToSearchInactiveUsers,
|
||||
Tags: []string{EngineMySql, EnginePostgres, EngineElasticSearch},
|
||||
},
|
||||
{
|
||||
Name: "Should be able to search filtering by role",
|
||||
Fn: testShouldBeAbleToSearchFilteringByRole,
|
||||
Tags: []string{EngineMySql, EnginePostgres, EngineElasticSearch},
|
||||
},
|
||||
{
|
||||
Name: "Should ignore leading @ when searching users",
|
||||
Fn: testShouldIgnoreLeadingAtSymbols,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should search users in a case insensitive manner",
|
||||
Fn: testSearchUsersShouldBeCaseInsensitive,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support one or two character usernames and first/last names in search",
|
||||
Fn: testSearchOneTwoCharUsernamesAndFirstLastNames,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support Korean characters",
|
||||
Fn: testShouldSupportKoreanCharacters,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support search with a hyphen at the end of the term",
|
||||
Fn: testSearchWithHyphenAtTheEndOfTheTerm,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support search all users in a team",
|
||||
Fn: testSearchUsersInTeam,
|
||||
Tags: []string{EngineElasticSearch},
|
||||
},
|
||||
{
|
||||
Name: "Should support search users by full name",
|
||||
Fn: testSearchUsersByFullName,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support search all users in a team with username containing a dot",
|
||||
Fn: testSearchUsersInTeamUsernameWithDot,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support search all users in a team with username containing a hyphen",
|
||||
Fn: testSearchUsersInTeamUsernameWithHyphen,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
{
|
||||
Name: "Should support search all users in a team with username containing a underscore",
|
||||
Fn: testSearchUsersInTeamUsernameWithUnderscore,
|
||||
Tags: []string{EngineAll},
|
||||
},
|
||||
}
|
||||
|
||||
func TestSearchUserStore(t *testing.T, s store.Store, testEngine *SearchTestEngine) {
|
||||
th := &SearchTestHelper{
|
||||
Store: s,
|
||||
}
|
||||
err := th.SetupBasicFixtures()
|
||||
require.NoError(t, err)
|
||||
defer th.CleanFixtures()
|
||||
runTestSearch(t, testEngine, searchUserStoreTests, th)
|
||||
}
|
||||
|
||||
func testGetAllUsersInChannelWithEmptyTerm(t *testing.T, th *SearchTestHelper) {
|
||||
options := &model.UserSearchOptions{
|
||||
AllowFullNames: true,
|
||||
Limit: model.UserSearchDefaultLimit,
|
||||
}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
|
||||
t.Run("Should be able to correctly honor limit when autocompleting", func(t *testing.T) {
|
||||
result, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, result.InChannel, 1)
|
||||
require.Len(t, result.OutOfChannel, 1)
|
||||
})
|
||||
|
||||
t.Run("Return all users in team", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
|
||||
t.Run("Return all users in teams even though some of them don't have a team associated", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
userAlternate, err := th.createUser("user-alternate", "user-alternate", "user", "alternate")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
userGuest, err := th.createGuest("user-guest", "user-guest", "user", "guest")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userGuest)
|
||||
|
||||
// In case teamId and channelId are empty our current logic goes through Search
|
||||
users, err := th.Store.User().Search("", "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, th.UserAnotherTeam,
|
||||
userAlternate, userGuest}, users)
|
||||
})
|
||||
}
|
||||
|
||||
func testHonorChannelRestrictionsAutocompletingUsers(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("user-alternate", "user-alternate", "user", "alternate")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
guest, err := th.createGuest("guest", "guest", "guest", "one")
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToTeams(guest, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(guest, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(guest)
|
||||
t.Run("Autocomplete users with channel restrictions", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, userAlternate, guest}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Autocomplete users with term and channel restrictions", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alt", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Autocomplete users with all channels restricted", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Autocomplete users with all channels restricted but with empty team", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel("", th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Autocomplete users with empty team and channels restricted", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
|
||||
// In case teamId and channelId are empty our current logic goes through Search
|
||||
users, err := th.Store.User().Search("", "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate, guest, th.User}, users)
|
||||
})
|
||||
}
|
||||
|
||||
func testHonorTeamRestrictionsAutocompletingUsers(t *testing.T, th *SearchTestHelper) {
|
||||
t.Run("Should return results for users in the team", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{th.Team.Id}}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return empty because we're filtering all the teams", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{}, Channels: []string{}}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return empty when searching in one team and filtering by another", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Teams: []string{th.AnotherTeam.Id}}
|
||||
users, err := th.Store.User().Search(th.Team.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
|
||||
|
||||
acusers, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, acusers.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, acusers.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testShouldReturnNothingWithoutProperAccess(t *testing.T, th *SearchTestHelper) {
|
||||
t.Run("Should return results users for the defined channel in the list", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ListOfAllowedChannels = []string{th.ChannelBasic.Id}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return empty because we're filtering all the channels", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
options.ListOfAllowedChannels = []string{}
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testAutocompleteUserByUsername(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternateusername", "alternatenick", "user", "alternate")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
}
|
||||
func testAutocompleteUserByFirstName(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("user-alternate", "user-alternate", "altfirstname", "lastname")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should autocomplete users when the first name is unique", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "altfirstname", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should autocomplete users for in the channel and out of the channel with the same first name", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicfirstname", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testAutocompleteUserByLastName(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("user-alternate", "user-alternate", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should return results when the last name is unique", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "altlastname", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return results for in the channel and out of the channel with the same last name", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basiclastname", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testAutocompleteUserByNickName(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternateusername", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should return results when the nickname is unique", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternatenickname", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return users that share the same part of the nickname", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicnickname", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testAutocompleteUserByEmail(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternateusername", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
userAlternate.Email = "useralt@test.email.com"
|
||||
_, err = th.Store.User().Update(userAlternate, false)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should autocomplete users when the email is unique", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, true, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "useralt@test.email.com", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should autocomplete users that share the same email user prefix", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, true, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "success_", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should autocomplete users that share the same email domain", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, true, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "simulator.amazon.com", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should search users when the email is unique", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, true, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "useralt@test.email.com", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
|
||||
})
|
||||
t.Run("Should search users that share the same email user prefix", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, true, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "success_", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
|
||||
})
|
||||
t.Run("Should search users that share the same email domain", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, true, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "simulator.amazon.com", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
|
||||
})
|
||||
}
|
||||
func testShouldNotMatchSpecificQueriesEmail(t *testing.T, th *SearchTestHelper) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "success_", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
}
|
||||
func testAutocompleteUserByUsernameWithDot(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate.username", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should return results when searching for the whole username with Dot", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate.username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return results when searching for part of the username including the Dot", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, ".username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return results when searching for part of the username not including the Dot", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testAutocompleteUserByUsernameWithUnderscore(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate_username", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should return results when searching for the whole username with underscore", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate_username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return results when searching for part of the username including the underscore", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "_username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return results when searching for part of the username not including the underscore", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testAutocompleteUserByUsernameWithHyphen(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate-username", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should return results when searching for the whole username with hyphen", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate-username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return results when searching for part of the username including the hyphen", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "-username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should return results when searching for part of the username not including the hyphen", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "username", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
func testShouldEscapePercentageCharacter(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternateusername", "alternate%nickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should autocomplete users escaping percentage symbol", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate%", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should search users escaping percentage symbol", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "alternate%", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
|
||||
})
|
||||
}
|
||||
func testShouldEscapeUnderscoreCharacter(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate_username", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should autocomplete users escaping underscore symbol", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate_", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should search users escaping underscore symbol", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "alternate_", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
|
||||
})
|
||||
}
|
||||
|
||||
func testShouldBeAbleToSearchInactiveUsers(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("basicusernamealternate", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
userAlternate.DeleteAt = model.GetMillis()
|
||||
_, err = th.Store.User().Update(userAlternate, true)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should autocomplete inactive users if we allow it", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, true)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should search inactive users if we allow it", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, true)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, userAlternate}, users)
|
||||
})
|
||||
t.Run("Shouldn't autocomplete inactive users if we don't allow it", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Shouldn't search inactive users if we don't allow it", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
|
||||
})
|
||||
}
|
||||
|
||||
func testShouldBeAbleToSearchFilteringByRole(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("basicusernamealternate", "alternatenickname", "firstname", "altlastname")
|
||||
require.NoError(t, err)
|
||||
userAlternate.Roles = "system_admin system_user"
|
||||
_, err = th.Store.User().Update(userAlternate, true)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
userAlternate2, err := th.createUser("basicusernamealternate2", "alternatenickname2", "firstname2", "altlastname2")
|
||||
require.NoError(t, err)
|
||||
userAlternate2.Roles = "system_user"
|
||||
_, err = th.Store.User().Update(userAlternate2, true)
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate2)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToTeams(userAlternate2, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should autocomplete users filtering by roles", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, true)
|
||||
options.Role = "system_admin"
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should search users filtering by roles", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, true)
|
||||
options.Role = "system_admin"
|
||||
users, err := th.Store.User().Search(th.Team.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
|
||||
})
|
||||
}
|
||||
|
||||
func testShouldIgnoreLeadingAtSymbols(t *testing.T, th *SearchTestHelper) {
|
||||
t.Run("Should autocomplete ignoring the @ symbol at the beginning", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "@basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should search ignoring the @ symbol at the beginning", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "@basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
|
||||
})
|
||||
}
|
||||
|
||||
func testSearchUsersShouldBeCaseInsensitive(t *testing.T, th *SearchTestHelper) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "BaSiCUsErNaMe", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User2}, users.OutOfChannel)
|
||||
}
|
||||
|
||||
func testSearchOneTwoCharUsernamesAndFirstLastNames(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("ho", "alternatenickname", "zi", "k")
|
||||
require.NoError(t, err)
|
||||
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should support two characters in the full name", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "zi", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should support two characters in the username", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "ho", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
|
||||
func testShouldSupportKoreanCharacters(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate-username", "alternate-nickname", "서강준", "안신원")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
t.Run("Should support hanja korean characters", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "서강준", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
t.Run("Should support hangul korean characters", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "안신원", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
})
|
||||
}
|
||||
|
||||
func testSearchWithHyphenAtTheEndOfTheTerm(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate-username", "alternate-nickname", "altfirst", "altlast")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().AutocompleteUsersInChannel(th.Team.Id, th.ChannelBasic.Id, "alternate-", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users.InChannel)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users.OutOfChannel)
|
||||
}
|
||||
|
||||
func testSearchUsersInTeam(t *testing.T, th *SearchTestHelper) {
|
||||
t.Run("Should return all the team users", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
|
||||
})
|
||||
t.Run("Should return all the team users with no team id", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search("", "basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2, th.UserAnotherTeam}, users)
|
||||
})
|
||||
t.Run("Should return all the team users filtered by username", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicusername1", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
|
||||
})
|
||||
t.Run("Should not return spurious results", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "falseuser", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
|
||||
})
|
||||
t.Run("Should return all the team users filtered by username and with channel restrictions", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{th.ChannelBasic.Id}}
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicusername", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
|
||||
})
|
||||
t.Run("Should return all the team users filtered by username and with all channel restricted", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
options.ViewRestrictions = &model.ViewUsersRestrictions{Channels: []string{}}
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicusername1", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
|
||||
})
|
||||
t.Run("Should honor the limit when searching users in team", func(t *testing.T) {
|
||||
optionsWithLimit := &model.UserSearchOptions{
|
||||
Limit: 1,
|
||||
}
|
||||
|
||||
users, err := th.Store.User().Search(th.Team.Id, "", optionsWithLimit)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, users, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func testSearchUsersInTeamUsernameWithDot(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate.username", "altnickname", "altfirst", "altlast")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "alternate.", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
|
||||
}
|
||||
|
||||
func testSearchUsersInTeamUsernameWithHyphen(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate-username", "altnickname", "altfirst", "altlast")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "alternate-", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
|
||||
}
|
||||
|
||||
func testSearchUsersInTeamUsernameWithUnderscore(t *testing.T, th *SearchTestHelper) {
|
||||
userAlternate, err := th.createUser("alternate_username", "altnickname", "altfirst", "altlast")
|
||||
require.NoError(t, err)
|
||||
defer th.deleteUser(userAlternate)
|
||||
err = th.addUserToTeams(userAlternate, []string{th.Team.Id})
|
||||
require.NoError(t, err)
|
||||
err = th.addUserToChannels(userAlternate, []string{th.ChannelBasic.Id})
|
||||
require.NoError(t, err)
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "alternate_", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{userAlternate}, users)
|
||||
}
|
||||
|
||||
func testSearchUsersByFullName(t *testing.T, th *SearchTestHelper) {
|
||||
t.Run("Should search users by full name", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicfirstname", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User, th.User2}, users)
|
||||
})
|
||||
t.Run("Should search user by full name", func(t *testing.T) {
|
||||
options := createDefaultOptions(true, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicfirstname1", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{th.User}, users)
|
||||
})
|
||||
t.Run("Should return empty when search by full name and is deactivated", func(t *testing.T) {
|
||||
options := createDefaultOptions(false, false, false)
|
||||
users, err := th.Store.User().Search(th.Team.Id, "basicfirstname1", options)
|
||||
require.NoError(t, err)
|
||||
th.assertUsersMatchInAnyOrder(t, []*model.User{}, users)
|
||||
})
|
||||
}
|
||||
|
||||
func createDefaultOptions(allowFullName, allowEmails, allowInactive bool) *model.UserSearchOptions {
|
||||
return &model.UserSearchOptions{
|
||||
AllowFullNames: allowFullName,
|
||||
AllowEmails: allowEmails,
|
||||
AllowInactive: allowInactive,
|
||||
Limit: model.UserSearchDefaultLimit,
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user