Full Mattermost server source with integrated Community Enterprise features. Includes vendor directory for offline/air-gapped builds. Structure: - enterprise-impl/: Enterprise feature implementations - enterprise-community/: Init files that register implementations - enterprise/: Bridge imports (community_imports.go) - vendor/: All dependencies for offline builds Build (online): go build ./cmd/mattermost Build (offline/air-gapped): go build -mod=vendor ./cmd/mattermost 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6091 lines
216 KiB
Go
6091 lines
216 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package app
|
|
|
|
import (
|
|
"archive/zip"
|
|
"context"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
"github.com/mattermost/mattermost/server/v8/channels/app/imports"
|
|
"github.com/mattermost/mattermost/server/v8/channels/store"
|
|
"github.com/mattermost/mattermost/server/v8/channels/testlib"
|
|
"github.com/mattermost/mattermost/server/v8/channels/utils"
|
|
"github.com/mattermost/mattermost/server/v8/channels/utils/fileutils"
|
|
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore"
|
|
)
|
|
|
|
func TestImportImportScheme(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Mark the phase 2 permissions migration as completed.
|
|
err := th.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
|
|
require.NoError(t, err, "Failed to save system value.")
|
|
|
|
defer func() {
|
|
_, err = th.App.Srv().Store().System().PermanentDeleteByName(model.MigrationKeyAdvancedPermissionsPhase2)
|
|
require.NoError(t, err, "Failed to delete system value.")
|
|
}()
|
|
|
|
// Try importing an invalid scheme in dryRun mode.
|
|
data := imports.SchemeImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
Scope: model.NewPointer("team"),
|
|
DefaultTeamGuestRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultTeamUserRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultTeamAdminRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelGuestRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelUserRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelAdminRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
Description: model.NewPointer("description"),
|
|
}
|
|
|
|
appErr := th.App.importScheme(th.Context, &data, true)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
_, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.Error(t, err, "Scheme should not have imported.")
|
|
|
|
// Try importing a valid scheme in dryRun mode.
|
|
data.DisplayName = model.NewPointer("display name")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, true)
|
|
require.Nil(t, appErr, "Should have succeeded.")
|
|
|
|
_, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.Error(t, err, "Scheme should not have imported.")
|
|
|
|
// Try importing an invalid scheme.
|
|
data.DisplayName = nil
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
_, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.Error(t, err, "Scheme should not have imported.")
|
|
|
|
// Try importing a valid scheme with all params set.
|
|
data.DisplayName = model.NewPointer("display name")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded.")
|
|
|
|
scheme, nErr := th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.NoError(t, nErr, "Failed to import scheme: %v", err)
|
|
|
|
assert.Equal(t, *data.Name, scheme.Name)
|
|
assert.Equal(t, *data.DisplayName, scheme.DisplayName)
|
|
assert.Equal(t, *data.Description, scheme.Description)
|
|
assert.Equal(t, *data.Scope, scheme.Scope)
|
|
|
|
role, nErr := th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamAdminRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamUserRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamGuestRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelAdminRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelUserRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelGuestRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
// Try modifying all the fields and re-importing.
|
|
data.DisplayName = model.NewPointer("new display name")
|
|
data.Description = model.NewPointer("new description")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded: %v", err)
|
|
|
|
scheme, nErr = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.NoError(t, nErr, "Failed to import scheme: %v", err)
|
|
|
|
assert.Equal(t, *data.Name, scheme.Name)
|
|
assert.Equal(t, *data.DisplayName, scheme.DisplayName)
|
|
assert.Equal(t, *data.Description, scheme.Description)
|
|
assert.Equal(t, *data.Scope, scheme.Scope)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamAdminRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamUserRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamGuestRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelAdminRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelUserRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelGuestRole)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
// Try changing the scope of the scheme and reimporting.
|
|
data.Scope = model.NewPointer("channel")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
scheme, nErr = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.NoError(t, nErr, "Failed to import scheme: %v", err)
|
|
|
|
assert.Equal(t, *data.Name, scheme.Name)
|
|
assert.Equal(t, *data.DisplayName, scheme.DisplayName)
|
|
assert.Equal(t, *data.Description, scheme.Description)
|
|
assert.Equal(t, "team", scheme.Scope)
|
|
}
|
|
|
|
func TestImportImportSchemeWithoutGuestRoles(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Mark the phase 2 permissions migration as completed.
|
|
err := th.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
|
|
require.NoError(t, err, "Failed to save system value.")
|
|
|
|
defer func() {
|
|
_, err = th.App.Srv().Store().System().PermanentDeleteByName(model.MigrationKeyAdvancedPermissionsPhase2)
|
|
require.NoError(t, err, "Failed to delete system value.")
|
|
}()
|
|
|
|
// Try importing an invalid scheme in dryRun mode.
|
|
data := imports.SchemeImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
Scope: model.NewPointer("team"),
|
|
DefaultTeamUserRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultTeamAdminRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelUserRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelAdminRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
Description: model.NewPointer("description"),
|
|
}
|
|
|
|
appErr := th.App.importScheme(th.Context, &data, true)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
_, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.Error(t, err, "Scheme should not have imported.")
|
|
|
|
// Try importing a valid scheme in dryRun mode.
|
|
data.DisplayName = model.NewPointer("display name")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, true)
|
|
require.Nil(t, appErr, "Should have succeeded.")
|
|
|
|
_, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.Error(t, err, "Scheme should not have imported.")
|
|
|
|
// Try importing an invalid scheme.
|
|
data.DisplayName = nil
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
_, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.Error(t, err, "Scheme should not have imported.")
|
|
|
|
// Try importing a valid scheme with all params set.
|
|
data.DisplayName = model.NewPointer("display name")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded.")
|
|
|
|
scheme, err := th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.NoError(t, err, "Failed to import scheme: %v", err)
|
|
|
|
assert.Equal(t, *data.Name, scheme.Name)
|
|
assert.Equal(t, *data.DisplayName, scheme.DisplayName)
|
|
assert.Equal(t, *data.Description, scheme.Description)
|
|
assert.Equal(t, *data.Scope, scheme.Scope)
|
|
|
|
role, err := th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamAdminRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamUserRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamGuestRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelAdminRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelUserRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelGuestRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
// Try modifying all the fields and re-importing.
|
|
data.DisplayName = model.NewPointer("new display name")
|
|
data.Description = model.NewPointer("new description")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded: %v", err)
|
|
|
|
scheme, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.NoError(t, err, "Failed to import scheme: %v", err)
|
|
|
|
assert.Equal(t, *data.Name, scheme.Name)
|
|
assert.Equal(t, *data.DisplayName, scheme.DisplayName)
|
|
assert.Equal(t, *data.Description, scheme.Description)
|
|
assert.Equal(t, *data.Scope, scheme.Scope)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamAdminRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamUserRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultTeamGuestRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultTeamGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelAdminRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelAdminRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelUserRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelUserRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
role, err = th.App.Srv().Store().Role().GetByName(context.Background(), scheme.DefaultChannelGuestRole)
|
|
require.NoError(t, err, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.DefaultChannelGuestRole.DisplayName, role.DisplayName)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
// Try changing the scope of the scheme and reimporting.
|
|
data.Scope = model.NewPointer("channel")
|
|
|
|
appErr = th.App.importScheme(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
scheme, err = th.App.Srv().Store().Scheme().GetByName(*data.Name)
|
|
require.NoError(t, err, "Failed to import scheme: %v", err)
|
|
|
|
assert.Equal(t, *data.Name, scheme.Name)
|
|
assert.Equal(t, *data.DisplayName, scheme.DisplayName)
|
|
assert.Equal(t, *data.Description, scheme.Description)
|
|
assert.Equal(t, "team", scheme.Scope)
|
|
}
|
|
|
|
func TestImportImportRole(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Try importing an invalid role in dryRun mode.
|
|
rid1 := model.NewId()
|
|
data := imports.RoleImportData{
|
|
Name: &rid1,
|
|
}
|
|
|
|
appErr := th.App.importRole(th.Context, &data, true)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
_, nErr := th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
|
|
require.Error(t, nErr, "Should have failed to import.")
|
|
|
|
// Try importing the valid role in dryRun mode.
|
|
data.DisplayName = model.NewPointer("display name")
|
|
|
|
appErr = th.App.importRole(th.Context, &data, true)
|
|
require.Nil(t, appErr, "Should have succeeded.")
|
|
|
|
_, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
|
|
require.Error(t, nErr, "Role should not have imported as we are in dry run mode.")
|
|
|
|
// Try importing an invalid role.
|
|
data.DisplayName = nil
|
|
|
|
appErr = th.App.importRole(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import.")
|
|
|
|
_, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
|
|
require.Error(t, nErr, "Role should not have imported.")
|
|
|
|
// Try importing a valid role with all params set.
|
|
data.DisplayName = model.NewPointer("display name")
|
|
data.Description = model.NewPointer("description")
|
|
data.Permissions = &[]string{"invite_user", "add_user_to_team"}
|
|
|
|
appErr = th.App.importRole(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded.")
|
|
|
|
role, nErr := th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.Name, role.Name)
|
|
assert.Equal(t, *data.DisplayName, role.DisplayName)
|
|
assert.Equal(t, *data.Description, role.Description)
|
|
assert.Equal(t, *data.Permissions, role.Permissions)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.False(t, role.SchemeManaged)
|
|
|
|
// Try changing all the params and reimporting.
|
|
data.DisplayName = model.NewPointer("new display name")
|
|
data.Description = model.NewPointer("description")
|
|
data.Permissions = &[]string{"manage_slash_commands"}
|
|
data.SchemeManaged = model.NewPointer(true)
|
|
|
|
appErr = th.App.importRole(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded. %v", appErr)
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data.Name, role.Name)
|
|
assert.Equal(t, *data.DisplayName, role.DisplayName)
|
|
assert.Equal(t, *data.Description, role.Description)
|
|
assert.Equal(t, *data.Permissions, role.Permissions)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
|
|
// Check that re-importing with only required fields doesn't update the others.
|
|
data2 := imports.RoleImportData{
|
|
Name: &rid1,
|
|
DisplayName: model.NewPointer("new display name again"),
|
|
}
|
|
|
|
appErr = th.App.importRole(th.Context, &data2, false)
|
|
require.Nil(t, appErr, "Should have succeeded.")
|
|
|
|
role, nErr = th.App.Srv().Store().Role().GetByName(context.Background(), rid1)
|
|
require.NoError(t, nErr, "Should have found the imported role.")
|
|
|
|
assert.Equal(t, *data2.Name, role.Name)
|
|
assert.Equal(t, *data2.DisplayName, role.DisplayName)
|
|
assert.Equal(t, *data.Description, role.Description)
|
|
assert.Equal(t, *data.Permissions, role.Permissions)
|
|
assert.False(t, role.BuiltIn)
|
|
assert.True(t, role.SchemeManaged)
|
|
}
|
|
|
|
func TestImportImportTeam(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Mark the phase 2 permissions migration as completed.
|
|
err := th.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
|
|
require.NoError(t, err, "Failed to save system value.")
|
|
|
|
defer func() {
|
|
_, err = th.App.Srv().Store().System().PermanentDeleteByName(model.MigrationKeyAdvancedPermissionsPhase2)
|
|
require.NoError(t, err, "Failed to delete system value.")
|
|
}()
|
|
|
|
scheme1 := th.SetupTeamScheme()
|
|
scheme2 := th.SetupTeamScheme()
|
|
|
|
// Check how many teams are in the database.
|
|
teamsCount, err := th.App.Srv().Store().Team().AnalyticsTeamCount(nil)
|
|
require.NoError(t, err, "Failed to get team count.")
|
|
|
|
// we also assert that the team name can be upper case
|
|
// Note there are no reserved team names starting with `Z`, making this flake-free.
|
|
teamName := "Z" + model.NewId()
|
|
sanitizedTeamName := strings.ToLower(teamName)
|
|
|
|
data := imports.TeamImportData{
|
|
Name: model.NewPointer(teamName),
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("XYZ"),
|
|
Description: model.NewPointer("The team description."),
|
|
AllowOpenInvite: model.NewPointer(true),
|
|
Scheme: &scheme1.Name,
|
|
}
|
|
|
|
// Try importing an invalid team in dryRun mode.
|
|
err = th.App.importTeam(th.Context, &data, true)
|
|
require.Error(t, err, "Should have received an error importing an invalid team.")
|
|
|
|
// Do a valid team in dry-run mode.
|
|
data.Type = model.NewPointer("O")
|
|
appErr := th.App.importTeam(th.Context, &data, true)
|
|
require.Nil(t, appErr, "Received an error validating valid team.")
|
|
|
|
// Check that no more teams are in the DB.
|
|
th.CheckTeamCount(t, teamsCount)
|
|
|
|
// Do an invalid team in apply mode, check db changes.
|
|
data.Type = model.NewPointer("XYZ")
|
|
err = th.App.importTeam(th.Context, &data, false)
|
|
require.Error(t, err, "Import should have failed on invalid team.")
|
|
|
|
// Check that no more teams are in the DB.
|
|
th.CheckTeamCount(t, teamsCount)
|
|
|
|
// Do a valid team in apply mode, check db changes.
|
|
data.Type = model.NewPointer("O")
|
|
appErr = th.App.importTeam(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Received an error importing valid team: %v", err)
|
|
|
|
// Check that one more team is in the DB.
|
|
th.CheckTeamCount(t, teamsCount+1)
|
|
|
|
// Get the team and check that all the fields are correct.
|
|
team, appErr := th.App.GetTeamByName(sanitizedTeamName)
|
|
require.Nil(t, appErr, "Failed to get team from database.")
|
|
|
|
assert.Equal(t, *data.DisplayName, team.DisplayName)
|
|
assert.Equal(t, *data.Type, team.Type)
|
|
assert.Equal(t, *data.Description, team.Description)
|
|
assert.Equal(t, *data.AllowOpenInvite, team.AllowOpenInvite)
|
|
assert.Equal(t, scheme1.Id, *team.SchemeId)
|
|
|
|
// Alter all the fields of that team (apart from unique identifier) and import again.
|
|
data.DisplayName = model.NewPointer("Display Name 2")
|
|
data.Type = model.NewPointer("P")
|
|
data.Description = model.NewPointer("The new description")
|
|
data.AllowOpenInvite = model.NewPointer(false)
|
|
data.Scheme = &scheme2.Name
|
|
|
|
// Check that the original number of teams are again in the DB (because this query doesn't include deleted).
|
|
data.Type = model.NewPointer("O")
|
|
appErr = th.App.importTeam(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Received an error importing updated valid team.")
|
|
|
|
th.CheckTeamCount(t, teamsCount+1)
|
|
|
|
// Get the team and check that all fields are correct.
|
|
team, appErr = th.App.GetTeamByName(sanitizedTeamName)
|
|
require.Nil(t, appErr, "Failed to get team from database.")
|
|
|
|
assert.Equal(t, *data.DisplayName, team.DisplayName)
|
|
assert.Equal(t, *data.Type, team.Type)
|
|
assert.Equal(t, *data.Description, team.Description)
|
|
assert.Equal(t, *data.AllowOpenInvite, team.AllowOpenInvite)
|
|
assert.Equal(t, scheme2.Id, *team.SchemeId)
|
|
}
|
|
|
|
func TestImportImportChannel(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Mark the phase 2 permissions migration as completed.
|
|
err := th.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
|
|
require.NoError(t, err, "Failed to save system value.")
|
|
|
|
defer func() {
|
|
_, err = th.App.Srv().Store().System().PermanentDeleteByName(model.MigrationKeyAdvancedPermissionsPhase2)
|
|
require.NoError(t, err, "Failed to delete system value.")
|
|
}()
|
|
|
|
scheme1 := th.SetupChannelScheme()
|
|
scheme2 := th.SetupChannelScheme()
|
|
|
|
// Import a Team.
|
|
teamName := model.NewRandomTeamName()
|
|
appErr := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import team.")
|
|
team, appErr := th.App.GetTeamByName(teamName)
|
|
require.Nil(t, appErr, "Failed to get team from database.")
|
|
|
|
// Check how many channels are in the database.
|
|
channelCount, nErr := th.App.Srv().Store().Channel().AnalyticsTypeCount("", model.ChannelTypeOpen)
|
|
require.NoError(t, nErr, "Failed to get team count.")
|
|
|
|
// Do an invalid channel in dry-run mode.
|
|
chanOpen := model.ChannelTypeOpen
|
|
data := imports.ChannelImportData{
|
|
Team: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanOpen,
|
|
Header: model.NewPointer("Channel Header"),
|
|
Purpose: model.NewPointer("Channel Purpose"),
|
|
Scheme: &scheme1.Name,
|
|
}
|
|
appErr = th.App.importChannel(th.Context, &data, true)
|
|
require.NotNil(t, appErr, "Expected error due to invalid name.")
|
|
|
|
// Check that no more channels are in the DB.
|
|
th.CheckChannelsCount(t, channelCount)
|
|
|
|
// Do a valid channel with a nonexistent team in dry-run mode.
|
|
data.Name = model.NewPointer("channelname")
|
|
data.Team = model.NewPointer(model.NewId())
|
|
appErr = th.App.importChannel(th.Context, &data, true)
|
|
require.Nil(t, appErr, "Expected success as cannot validate channel name in dry run mode.")
|
|
|
|
// Check that no more channels are in the DB.
|
|
th.CheckChannelsCount(t, channelCount)
|
|
|
|
// Do a valid channel in dry-run mode.
|
|
data.Team = &teamName
|
|
appErr = th.App.importChannel(th.Context, &data, true)
|
|
require.Nil(t, appErr, "Expected success as valid team.")
|
|
|
|
// Check that no more channels are in the DB.
|
|
th.CheckChannelsCount(t, channelCount)
|
|
|
|
// Do an invalid channel in apply mode.
|
|
data.Name = nil
|
|
appErr = th.App.importChannel(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Expected error due to invalid name (apply mode).")
|
|
|
|
// Check that no more channels are in the DB.
|
|
th.CheckChannelsCount(t, channelCount)
|
|
|
|
// Do a valid channel in apply mode with a non-existent team.
|
|
data.Name = model.NewPointer("channelname")
|
|
data.Team = model.NewPointer(model.NewId())
|
|
appErr = th.App.importChannel(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Expected error due to non-existent team (apply mode).")
|
|
|
|
// Check that no more channels are in the DB.
|
|
th.CheckChannelsCount(t, channelCount)
|
|
|
|
// Do a valid channel in apply mode.
|
|
data.Team = &teamName
|
|
|
|
// we also assert that the channel name can be upper case
|
|
// for the import workflow
|
|
data.Name = model.NewPointer("channelName")
|
|
sanitizedChannelName := strings.ToLower(*data.Name)
|
|
|
|
appErr = th.App.importChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Expected success in apply mode")
|
|
|
|
// Check that 1 more channel is in the DB.
|
|
th.CheckChannelsCount(t, channelCount+1)
|
|
|
|
// Get the Channel and check all the fields are correct.
|
|
channel, appErr := th.App.GetChannelByName(th.Context, sanitizedChannelName, team.Id, false)
|
|
require.Nil(t, appErr, "Failed to get channel from database.")
|
|
|
|
assert.Equal(t, sanitizedChannelName, channel.Name)
|
|
assert.Equal(t, *data.DisplayName, channel.DisplayName)
|
|
assert.Equal(t, *data.Type, channel.Type)
|
|
assert.Equal(t, *data.Header, channel.Header)
|
|
assert.Equal(t, *data.Purpose, channel.Purpose)
|
|
assert.Equal(t, scheme1.Id, *channel.SchemeId)
|
|
|
|
// Alter all the fields of that channel.
|
|
cTypePr := model.ChannelTypePrivate
|
|
data.DisplayName = model.NewPointer("Changed Disp Name")
|
|
data.Type = &cTypePr
|
|
data.Header = model.NewPointer("New Header")
|
|
data.Purpose = model.NewPointer("New Purpose")
|
|
data.Scheme = &scheme2.Name
|
|
appErr = th.App.importChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Expected success in apply mode")
|
|
|
|
// Check channel count the same.
|
|
th.CheckChannelsCount(t, channelCount)
|
|
|
|
// Get the Channel and check all the fields are correct.
|
|
channel, appErr = th.App.GetChannelByName(th.Context, sanitizedChannelName, team.Id, false)
|
|
require.Nil(t, appErr, "Failed to get channel from database.")
|
|
|
|
assert.Equal(t, sanitizedChannelName, channel.Name)
|
|
assert.Equal(t, *data.DisplayName, channel.DisplayName)
|
|
assert.Equal(t, *data.Type, channel.Type)
|
|
assert.Equal(t, *data.Header, channel.Header)
|
|
assert.Equal(t, *data.Purpose, channel.Purpose)
|
|
assert.Equal(t, scheme2.Id, *channel.SchemeId)
|
|
|
|
// Do a valid archived channel.
|
|
now := model.GetMillis()
|
|
data.Name = model.NewPointer("archivedchannel")
|
|
data.DisplayName = model.NewPointer("Archived Channel")
|
|
data.Type = &chanOpen
|
|
data.Header = model.NewPointer("Archived Channel Header")
|
|
data.Purpose = model.NewPointer("Archived Channel Purpose")
|
|
data.Scheme = &scheme1.Name
|
|
data.DeletedAt = &now
|
|
appErr = th.App.importChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Expected success in apply mode")
|
|
aChan, appErr := th.App.GetChannelByName(th.Context, sanitizedChannelName, team.Id, true)
|
|
require.Nil(t, appErr, "Failed to get channel from database.")
|
|
assert.Equal(t, sanitizedChannelName, aChan.Name)
|
|
}
|
|
|
|
func TestImportImportUser(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Check how many users are in the database.
|
|
userCount, cErr := th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, cErr, "Failed to get user count.")
|
|
|
|
t.Run("import an invalid user in dry-run", func(t *testing.T) {
|
|
data := imports.UserImportData{
|
|
Username: model.NewPointer(model.NewUsername()),
|
|
}
|
|
appErr := th.App.importUser(th.Context, &data, true)
|
|
require.NotNil(t, appErr, "Should have failed to import invalid user.")
|
|
|
|
// Check that no more users are in the DB.
|
|
userCountCurrent, err := th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
})
|
|
|
|
t.Run("import a valid user in dry-run", func(t *testing.T) {
|
|
data := imports.UserImportData{
|
|
Username: model.NewPointer(model.NewUsername()),
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}
|
|
appErr := th.App.importUser(th.Context, &data, true)
|
|
require.Nil(t, appErr, "Should have succeeded to import valid user.")
|
|
|
|
// Check that no more users are in the DB.
|
|
userCountCurrent, err := th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
})
|
|
|
|
t.Run("import an invalid user in apply mode", func(t *testing.T) {
|
|
data := imports.UserImportData{
|
|
Username: model.NewPointer(model.NewUsername()),
|
|
}
|
|
appErr := th.App.importUser(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import invalid user.")
|
|
|
|
// Check that no more users are in the DB.
|
|
userCountCurrent, err := th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
})
|
|
|
|
t.Run("import a valid user in apply mode", func(t *testing.T) {
|
|
username := "A" + model.NewUsername()[1:]
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
data := imports.UserImportData{
|
|
Avatar: imports.Avatar{
|
|
ProfileImage: model.NewPointer(filepath.Join(testsDir, "test.png")),
|
|
},
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Nickname: model.NewPointer(model.NewId()),
|
|
FirstName: model.NewPointer(model.NewId()),
|
|
LastName: model.NewPointer(model.NewId()),
|
|
Position: model.NewPointer(model.NewId()),
|
|
}
|
|
appErr := th.App.importUser(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded to import valid user.")
|
|
|
|
// Check that one more user is in the DB.
|
|
userCountCurrent, err := th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
userCount++ // Increment the user count.
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
|
|
// Get the user and check all the fields are correct.
|
|
user, err2 := th.App.GetUserByUsername(username)
|
|
require.Nil(t, err2, "Failed to get user from database.")
|
|
|
|
assert.Equal(t, *data.Email, user.Email)
|
|
assert.Equal(t, *data.Nickname, user.Nickname)
|
|
assert.Equal(t, *data.FirstName, user.FirstName)
|
|
assert.Equal(t, *data.LastName, user.LastName)
|
|
assert.Equal(t, *data.Position, user.Position)
|
|
|
|
// Check calculated properties.
|
|
require.Equal(t, strings.ToLower(username), user.Username, "Expected Username to be lower case.")
|
|
require.Empty(t, user.AuthService, "Expected Auth Service to be empty.")
|
|
require.Empty(t, user.AuthData, "Expected AuthData to be empty.")
|
|
require.NotEmpty(t, user.Password, "Expected password to be set.")
|
|
require.True(t, user.EmailVerified, "Expected EmailVerified to be true.")
|
|
require.Equal(t, user.Locale, *th.App.Config().LocalizationSettings.DefaultClientLocale, "Expected Locale to be the default.")
|
|
require.Equal(t, user.Roles, "system_user", "Expected roles to be system_user")
|
|
})
|
|
|
|
t.Run("import a valid user where there is an existing user", func(t *testing.T) {
|
|
username := model.NewUsername()
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
data := imports.UserImportData{
|
|
Avatar: imports.Avatar{
|
|
ProfileImage: model.NewPointer(filepath.Join(testsDir, "test.png")),
|
|
},
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Nickname: model.NewPointer(model.NewId()),
|
|
FirstName: model.NewPointer(model.NewId()),
|
|
LastName: model.NewPointer(model.NewId()),
|
|
Position: model.NewPointer(model.NewId()),
|
|
}
|
|
appErr := th.App.importUser(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded to import valid user.")
|
|
|
|
// Check that one more user is in the DB.
|
|
userCountCurrent, err := th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
userCount++ // Increment the user count.
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
|
|
// Alter all the fields of that user.
|
|
data.Email = model.NewPointer(model.NewId() + "@example.com")
|
|
data.ProfileImage = model.NewPointer(filepath.Join(testsDir, "testgif.gif"))
|
|
data.AuthService = model.NewPointer("ldap")
|
|
data.AuthData = &username
|
|
data.Nickname = model.NewPointer(model.NewId())
|
|
data.FirstName = model.NewPointer(model.NewId())
|
|
data.LastName = model.NewPointer(model.NewId())
|
|
data.Position = model.NewPointer(model.NewId())
|
|
data.Roles = model.NewPointer("system_admin system_user")
|
|
data.Locale = model.NewPointer("zh_CN")
|
|
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded to update valid user %v", err)
|
|
|
|
// Check user count the same.
|
|
userCountCurrent, err = th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
|
|
// Get the user and check all the fields are correct.
|
|
user, err2 := th.App.GetUserByUsername(username)
|
|
require.Nil(t, err2, "Failed to get user from database.")
|
|
|
|
assert.Equal(t, *data.Email, user.Email)
|
|
assert.Equal(t, *data.Nickname, user.Nickname)
|
|
assert.Equal(t, *data.FirstName, user.FirstName)
|
|
assert.Equal(t, *data.LastName, user.LastName)
|
|
assert.Equal(t, *data.Position, user.Position)
|
|
|
|
require.Equal(t, "ldap", user.AuthService, "Expected Auth Service to be ldap \"%v\"", user.AuthService)
|
|
require.Equal(t, user.AuthData, data.AuthData, "Expected AuthData to be set.")
|
|
require.Empty(t, user.Password, "Expected password to be empty.")
|
|
require.True(t, user.EmailVerified, "Expected EmailVerified to be true.")
|
|
require.Equal(t, *data.Locale, user.Locale, "Expected Locale to be the set.")
|
|
require.Equal(t, *data.Roles, user.Roles, "Expected roles to be set: %v", user.Roles)
|
|
})
|
|
|
|
t.Run("import invalid fields", func(t *testing.T) {
|
|
username := model.NewUsername()
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
data := imports.UserImportData{
|
|
Avatar: imports.Avatar{
|
|
ProfileImage: model.NewPointer(filepath.Join(testsDir, "test.png")),
|
|
},
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Nickname: model.NewPointer(model.NewId()),
|
|
FirstName: model.NewPointer(model.NewId()),
|
|
LastName: model.NewPointer(model.NewId()),
|
|
Position: model.NewPointer(model.NewId()),
|
|
AuthData: &username,
|
|
AuthService: model.NewPointer("ldap"),
|
|
}
|
|
appErr := th.App.importUser(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded to import valid user.")
|
|
|
|
// Check that one more user is in the DB.
|
|
userCountCurrent, err := th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
userCount++ // Increment the user count.
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
|
|
// Check Password and AuthData together.
|
|
data.Password = model.NewPointer("PasswordTest")
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import invalid user.")
|
|
|
|
data.AuthData = nil
|
|
data.AuthService = nil
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
require.Nil(t, appErr, "Should have succeeded to update valid user %v", err)
|
|
|
|
data.Password = model.NewPointer("")
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import invalid user.")
|
|
|
|
data.Password = model.NewPointer(strings.Repeat("0123456789", 10))
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
require.NotNil(t, appErr, "Should have failed to import invalid user.")
|
|
|
|
// Check that no more user is in the DB.
|
|
userCountCurrent, err = th.App.Srv().Store().User().Count(model.UserCountOptions{
|
|
IncludeDeleted: true,
|
|
IncludeBotAccounts: false,
|
|
})
|
|
require.NoError(t, err, "Failed to get user count.")
|
|
assert.Equal(t, userCount, userCountCurrent, "Unexpected number of users")
|
|
})
|
|
|
|
t.Run("import with team and channel memberships", func(t *testing.T) {
|
|
teamName := model.NewRandomTeamName()
|
|
tAppErr := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, tAppErr, "Failed to import team.")
|
|
team, appErr := th.App.GetTeamByName(teamName)
|
|
require.Nil(t, appErr, "Failed to get team from database.")
|
|
|
|
channelName := model.NewId()
|
|
chanTypeOpen := model.ChannelTypeOpen
|
|
appErr = th.App.importChannel(th.Context, &imports.ChannelImportData{
|
|
Team: &teamName,
|
|
Name: &channelName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import channel.")
|
|
channel, appErr := th.App.GetChannelByName(th.Context, channelName, team.Id, false)
|
|
require.Nil(t, appErr, "Failed to get channel from database.")
|
|
|
|
username := model.NewUsername()
|
|
data := imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Nickname: model.NewPointer(model.NewId()),
|
|
FirstName: model.NewPointer(model.NewId()),
|
|
LastName: model.NewPointer(model.NewId()),
|
|
Position: model.NewPointer(model.NewId()),
|
|
}
|
|
|
|
teamMembers, appErr := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
|
|
require.Nil(t, appErr, "Failed to get team member count")
|
|
teamMemberCount := len(teamMembers)
|
|
|
|
channelMemberCount, appErr := th.App.GetChannelMemberCount(th.Context, channel.Id)
|
|
require.Nil(t, appErr, "Failed to get channel member count")
|
|
|
|
t.Run("invalid team and channel memberships in dry-run mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, true)
|
|
assert.NotNil(t, appErr)
|
|
})
|
|
|
|
t.Run("unknown team name & invalid channel membership in dry-run mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: model.NewPointer(model.NewId()),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, true)
|
|
assert.NotNil(t, appErr)
|
|
})
|
|
|
|
t.Run("valid team & invalid channel membership in dry-run mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &teamName,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, true)
|
|
assert.NotNil(t, appErr)
|
|
})
|
|
|
|
t.Run("valid team & unknown channel name in dry-run mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &teamName,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: model.NewPointer(model.NewId()),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, true)
|
|
assert.Nil(t, appErr)
|
|
})
|
|
|
|
t.Run("valid team & valid channel name in dry-run mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &teamName,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &channelName,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, true)
|
|
assert.Nil(t, appErr)
|
|
|
|
// Check no new member objects were created because dry run mode.
|
|
tmc, appErr2 := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
|
|
require.Nil(t, appErr2, "Failed to get Team Member Count")
|
|
require.Len(t, tmc, teamMemberCount, "Number of team members not as expected")
|
|
|
|
cmc, appErr2 := th.App.GetChannelMemberCount(th.Context, channel.Id)
|
|
require.Nil(t, appErr2, "Failed to get Channel Member Count")
|
|
require.Equal(t, channelMemberCount, cmc, "Number of channel members not as expected")
|
|
})
|
|
|
|
t.Run("invalid team & channel membership in apply mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
assert.NotNil(t, appErr)
|
|
})
|
|
|
|
t.Run("unknown team name & invalid channel membership in apply mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: model.NewPointer(model.NewId()),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
assert.NotNil(t, appErr)
|
|
})
|
|
|
|
t.Run("import with valid team and invalid channel memberships in apply mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &teamName,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Roles: model.NewPointer("invalid"),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
assert.NotNil(t, appErr)
|
|
|
|
// Check no new member objects were created because all tests should have failed so far.
|
|
tmc, appErr2 := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
|
|
require.Nil(t, appErr2, "Failed to get Team Member Count")
|
|
require.Len(t, tmc, teamMemberCount)
|
|
|
|
cmc, appErr2 := th.App.GetChannelMemberCount(th.Context, channel.Id)
|
|
require.Nil(t, appErr2, "Failed to get Channel Member Count")
|
|
require.Equal(t, channelMemberCount, cmc)
|
|
})
|
|
|
|
t.Run("valid team & unknown channel name in apply mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &teamName,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: model.NewPointer(model.NewId()),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importUser(th.Context, &data, false)
|
|
assert.NotNil(t, appErr)
|
|
|
|
// Check only new team member object created because dry run mode.
|
|
tmc, appErr2 := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
|
|
require.Nil(t, appErr2, "Failed to get Team Member Count")
|
|
teamMemberCount++
|
|
require.Len(t, tmc, teamMemberCount)
|
|
|
|
cmc, appErr2 := th.App.GetChannelMemberCount(th.Context, channel.Id)
|
|
require.Nil(t, appErr2, "Failed to get Channel Member Count")
|
|
require.Equal(t, channelMemberCount, cmc)
|
|
|
|
// Check team member properties.
|
|
user, appErr2 := th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
teamMember, appErr2 := th.App.GetTeamMember(th.Context, team.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get team member from database.")
|
|
require.Equal(t, "team_user", teamMember.Roles)
|
|
})
|
|
|
|
t.Run("valid team & valid channel name in apply mode", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &teamName,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &channelName,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
// convert to a new user
|
|
username = model.NewUsername()
|
|
data.Username = &username
|
|
data.Email = model.NewPointer(model.NewId() + "@example.com")
|
|
appErr2 := th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
// Check only new channel member object created because dry run mode.
|
|
tmc, appErr2 := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
|
|
require.Nil(t, appErr2, "Failed to get Team Member Count")
|
|
teamMemberCount++
|
|
require.Len(t, tmc, teamMemberCount, "Number of team members not as expected")
|
|
|
|
cmc, appErr2 := th.App.GetChannelMemberCount(th.Context, channel.Id)
|
|
require.Nil(t, appErr2, "Failed to get Channel Member Count")
|
|
channelMemberCount++
|
|
require.Equal(t, channelMemberCount, cmc, "Number of channel members not as expected")
|
|
|
|
user, err2 := th.App.GetUserByUsername(username)
|
|
require.Nil(t, err2, "Failed to get user from database.")
|
|
|
|
// Check channel member properties.
|
|
channelMember, appErr2 := th.App.GetChannelMember(th.Context, channel.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get channel member from database.")
|
|
assert.Equal(t, "channel_user", channelMember.Roles)
|
|
assert.Equal(t, "default", channelMember.NotifyProps[model.DesktopNotifyProp])
|
|
assert.Equal(t, "default", channelMember.NotifyProps[model.PushNotifyProp])
|
|
assert.Equal(t, "all", channelMember.NotifyProps[model.MarkUnreadNotifyProp])
|
|
})
|
|
|
|
t.Run("test with the properties of the team and channel membership changed", func(t *testing.T) {
|
|
data.Teams = &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &teamName,
|
|
Theme: model.NewPointer(`{"awayIndicator":"#DBBD4E","buttonBg":"#23A1FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBg":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
|
|
Roles: model.NewPointer("team_user team_admin"),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &channelName,
|
|
Roles: model.NewPointer("channel_user channel_admin"),
|
|
NotifyProps: &imports.UserChannelNotifyPropsImportData{
|
|
Desktop: model.NewPointer(model.UserNotifyMention),
|
|
Mobile: model.NewPointer(model.UserNotifyMention),
|
|
MarkUnread: model.NewPointer(model.UserNotifyMention),
|
|
},
|
|
Favorite: model.NewPointer(true),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
// convert to a new user
|
|
username = model.NewUsername()
|
|
data.Username = &username
|
|
data.Email = model.NewPointer(model.NewId() + "@example.com")
|
|
|
|
appErr2 := th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, err2 := th.App.GetUserByUsername(username)
|
|
require.Nil(t, err2, "Failed to get user from database.")
|
|
|
|
// Check both member properties.
|
|
teamMember, appErr2 := th.App.GetTeamMember(th.Context, team.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get team member from database.")
|
|
require.Equal(t, "team_user team_admin", teamMember.Roles)
|
|
|
|
channelMember, appErr2 := th.App.GetChannelMember(th.Context, channel.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get channel member Desktop from database.")
|
|
assert.Equal(t, "channel_user channel_admin", channelMember.Roles)
|
|
assert.Equal(t, model.UserNotifyMention, channelMember.NotifyProps[model.DesktopNotifyProp])
|
|
assert.Equal(t, model.UserNotifyMention, channelMember.NotifyProps[model.PushNotifyProp])
|
|
assert.Equal(t, model.UserNotifyMention, channelMember.NotifyProps[model.MarkUnreadNotifyProp])
|
|
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryFavoriteChannel, channel.Id, "true")
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryTheme, team.Id, *(*data.Teams)[0].Theme)
|
|
|
|
// No more new member objects.
|
|
tmc, appErr2 := th.App.GetTeamMembers(team.Id, 0, 1000, nil)
|
|
require.Nil(t, appErr2, "Failed to get Team Member Count")
|
|
require.Len(t, tmc, teamMemberCount+1, "Number of team members not as expected")
|
|
|
|
cmc, appErr2 := th.App.GetChannelMemberCount(th.Context, channel.Id)
|
|
require.Nil(t, appErr2, "Failed to get Channel Member Count")
|
|
require.Equal(t, channelMemberCount+1, cmc, "Number of channel members not as expected")
|
|
})
|
|
})
|
|
|
|
t.Run("add a user with some preferences.", func(t *testing.T) {
|
|
teamName := model.NewRandomTeamName()
|
|
appErr2 := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, appErr2, "Failed to import team.")
|
|
|
|
channelName := model.NewId()
|
|
chanTypeOpen := model.ChannelTypeOpen
|
|
appErr2 = th.App.importChannel(th.Context, &imports.ChannelImportData{
|
|
Team: &teamName,
|
|
Name: &channelName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
}, false)
|
|
require.Nil(t, appErr2, "Failed to import channel.")
|
|
|
|
username := model.NewUsername()
|
|
data := imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Theme: model.NewPointer(`{"awayIndicator":"#DCBD4E","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBg":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
|
|
UseMilitaryTime: model.NewPointer("true"),
|
|
CollapsePreviews: model.NewPointer("true"),
|
|
MessageDisplay: model.NewPointer("compact"),
|
|
ColorizeUsernames: model.NewPointer("true"),
|
|
ChannelDisplayMode: model.NewPointer("centered"),
|
|
TutorialStep: model.NewPointer("3"),
|
|
UseMarkdownPreview: model.NewPointer("true"),
|
|
UseFormatting: model.NewPointer("true"),
|
|
ShowUnreadSection: model.NewPointer("true"),
|
|
EmailInterval: model.NewPointer("immediately"),
|
|
NameFormat: model.NewPointer("full_name"),
|
|
SendOnCtrlEnter: model.NewPointer("true"),
|
|
CodeBlockCtrlEnter: model.NewPointer("true"),
|
|
ShowJoinLeave: model.NewPointer("false"),
|
|
SyncDrafts: model.NewPointer("false"),
|
|
ShowUnreadScrollPosition: model.NewPointer("start_from_newest"),
|
|
LimitVisibleDmsGms: model.NewPointer("20"),
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
// Check their values.
|
|
user, appErr2 := th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryTheme, "", *data.Theme)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameUseMilitaryTime, *data.UseMilitaryTime)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameCollapseSetting, *data.CollapsePreviews)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameMessageDisplay, *data.MessageDisplay)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameColorizeUsernames, *data.ColorizeUsernames)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameChannelDisplayMode, *data.ChannelDisplayMode)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryTutorialSteps, user.Id, *data.TutorialStep)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryAdvancedSettings, "feature_enabled_markdown_preview", *data.UseMarkdownPreview)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryAdvancedSettings, "formatting", *data.UseFormatting)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategorySidebarSettings, "show_unread_section", *data.ShowUnreadSection)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameNameFormat, "full_name")
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryAdvancedSettings, "send_on_ctrl_enter", "true")
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryAdvancedSettings, "code_block_ctrl_enter", "true")
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryAdvancedSettings, "join_leave", "false")
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryAdvancedSettings, "sync_drafts", "false")
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryAdvancedSettings, "unread_scroll_position", "start_from_newest")
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategorySidebarSettings, model.PreferenceLimitVisibleDmsGms, "20")
|
|
|
|
// Change those preferences.
|
|
data = imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Theme: model.NewPointer(`{"awayIndicator":"#123456","buttonBg":"#23A2FF","buttonColor":"#FFFFFF","centerChannelBg":"#ffffff","centerChannelColor":"#333333","codeTheme":"github","image":"/static/files/a4a388b38b32678e83823ef1b3e17766.png","linkColor":"#2389d7","mentionBg":"#2389d7","mentionColor":"#ffffff","mentionHighlightBg":"#fff2bb","mentionHighlightLink":"#2f81b7","newMessageSeparator":"#FF8800","onlineIndicator":"#7DBE00","sidebarBg":"#fafafa","sidebarHeaderBg":"#3481B9","sidebarHeaderTextColor":"#ffffff","sidebarText":"#333333","sidebarTextActiveBorder":"#378FD2","sidebarTextActiveColor":"#111111","sidebarTextHoverBg":"#e6f2fa","sidebarUnreadText":"#333333","type":"Mattermost"}`),
|
|
UseMilitaryTime: model.NewPointer("false"),
|
|
CollapsePreviews: model.NewPointer("false"),
|
|
MessageDisplay: model.NewPointer("clean"),
|
|
ColorizeUsernames: model.NewPointer("false"),
|
|
ChannelDisplayMode: model.NewPointer("full"),
|
|
TutorialStep: model.NewPointer("2"),
|
|
EmailInterval: model.NewPointer("hour"),
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
// Check their values again.
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryTheme, "", *data.Theme)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameUseMilitaryTime, *data.UseMilitaryTime)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameCollapseSetting, *data.CollapsePreviews)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameMessageDisplay, *data.MessageDisplay)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameColorizeUsernames, *data.ColorizeUsernames)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryDisplaySettings, model.PreferenceNameChannelDisplayMode, *data.ChannelDisplayMode)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryTutorialSteps, user.Id, *data.TutorialStep)
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryNotifications, model.PreferenceNameEmailInterval, "3600")
|
|
|
|
// Set Notify Without mention keys
|
|
data.NotifyProps = &imports.UserNotifyPropsImportData{
|
|
Desktop: model.NewPointer(model.UserNotifyAll),
|
|
DesktopSound: model.NewPointer("true"),
|
|
Email: model.NewPointer("true"),
|
|
Mobile: model.NewPointer(model.UserNotifyAll),
|
|
MobilePushStatus: model.NewPointer(model.StatusOnline),
|
|
ChannelTrigger: model.NewPointer("true"),
|
|
CommentsTrigger: model.NewPointer(model.CommentsNotifyRoot),
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, appErr2 = th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
checkNotifyProp(t, user, model.DesktopNotifyProp, model.UserNotifyAll)
|
|
checkNotifyProp(t, user, model.DesktopSoundNotifyProp, "true")
|
|
checkNotifyProp(t, user, model.EmailNotifyProp, "true")
|
|
checkNotifyProp(t, user, model.PushNotifyProp, model.UserNotifyAll)
|
|
checkNotifyProp(t, user, model.PushStatusNotifyProp, model.StatusOnline)
|
|
checkNotifyProp(t, user, model.ChannelMentionsNotifyProp, "true")
|
|
checkNotifyProp(t, user, model.CommentsNotifyProp, model.CommentsNotifyRoot)
|
|
checkNotifyProp(t, user, model.MentionKeysNotifyProp, "")
|
|
|
|
// Set Notify Props with Mention keys
|
|
data.NotifyProps = &imports.UserNotifyPropsImportData{
|
|
Desktop: model.NewPointer(model.UserNotifyAll),
|
|
DesktopSound: model.NewPointer("true"),
|
|
Email: model.NewPointer("true"),
|
|
Mobile: model.NewPointer(model.UserNotifyAll),
|
|
MobilePushStatus: model.NewPointer(model.StatusOnline),
|
|
ChannelTrigger: model.NewPointer("true"),
|
|
CommentsTrigger: model.NewPointer(model.CommentsNotifyRoot),
|
|
MentionKeys: model.NewPointer("valid,misc"),
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, appErr2 = th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
checkNotifyProp(t, user, model.DesktopNotifyProp, model.UserNotifyAll)
|
|
checkNotifyProp(t, user, model.DesktopSoundNotifyProp, "true")
|
|
checkNotifyProp(t, user, model.EmailNotifyProp, "true")
|
|
checkNotifyProp(t, user, model.PushNotifyProp, model.UserNotifyAll)
|
|
checkNotifyProp(t, user, model.PushStatusNotifyProp, model.StatusOnline)
|
|
checkNotifyProp(t, user, model.ChannelMentionsNotifyProp, "true")
|
|
checkNotifyProp(t, user, model.CommentsNotifyProp, model.CommentsNotifyRoot)
|
|
checkNotifyProp(t, user, model.MentionKeysNotifyProp, "valid,misc")
|
|
|
|
// Change Notify Props with mention keys
|
|
data.NotifyProps = &imports.UserNotifyPropsImportData{
|
|
Desktop: model.NewPointer(model.UserNotifyMention),
|
|
DesktopSound: model.NewPointer("false"),
|
|
Email: model.NewPointer("false"),
|
|
Mobile: model.NewPointer(model.UserNotifyNone),
|
|
MobilePushStatus: model.NewPointer(model.StatusAway),
|
|
ChannelTrigger: model.NewPointer("false"),
|
|
CommentsTrigger: model.NewPointer(model.CommentsNotifyAny),
|
|
MentionKeys: model.NewPointer("misc"),
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, appErr2 = th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
checkNotifyProp(t, user, model.DesktopNotifyProp, model.UserNotifyMention)
|
|
checkNotifyProp(t, user, model.DesktopSoundNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.EmailNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.PushNotifyProp, model.UserNotifyNone)
|
|
checkNotifyProp(t, user, model.PushStatusNotifyProp, model.StatusAway)
|
|
checkNotifyProp(t, user, model.ChannelMentionsNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.CommentsNotifyProp, model.CommentsNotifyAny)
|
|
checkNotifyProp(t, user, model.MentionKeysNotifyProp, "misc")
|
|
|
|
// Change Notify Props without mention keys
|
|
data.NotifyProps = &imports.UserNotifyPropsImportData{
|
|
Desktop: model.NewPointer(model.UserNotifyMention),
|
|
DesktopSound: model.NewPointer("false"),
|
|
Email: model.NewPointer("false"),
|
|
Mobile: model.NewPointer(model.UserNotifyNone),
|
|
MobilePushStatus: model.NewPointer(model.StatusAway),
|
|
ChannelTrigger: model.NewPointer("false"),
|
|
CommentsTrigger: model.NewPointer(model.CommentsNotifyAny),
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, appErr2 = th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
checkNotifyProp(t, user, model.DesktopNotifyProp, model.UserNotifyMention)
|
|
checkNotifyProp(t, user, model.DesktopSoundNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.EmailNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.PushNotifyProp, model.UserNotifyNone)
|
|
checkNotifyProp(t, user, model.PushStatusNotifyProp, model.StatusAway)
|
|
checkNotifyProp(t, user, model.ChannelMentionsNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.CommentsNotifyProp, model.CommentsNotifyAny)
|
|
checkNotifyProp(t, user, model.MentionKeysNotifyProp, "misc")
|
|
|
|
// Check Notify Props get set on *create* user.
|
|
username = model.NewUsername()
|
|
data = imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}
|
|
data.NotifyProps = &imports.UserNotifyPropsImportData{
|
|
Desktop: model.NewPointer(model.UserNotifyMention),
|
|
DesktopSound: model.NewPointer("false"),
|
|
Email: model.NewPointer("false"),
|
|
Mobile: model.NewPointer(model.UserNotifyNone),
|
|
MobilePushStatus: model.NewPointer(model.StatusAway),
|
|
ChannelTrigger: model.NewPointer("false"),
|
|
CommentsTrigger: model.NewPointer(model.CommentsNotifyAny),
|
|
MentionKeys: model.NewPointer("misc"),
|
|
}
|
|
|
|
appErr2 = th.App.importUser(th.Context, &data, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, appErr2 = th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
checkNotifyProp(t, user, model.DesktopNotifyProp, model.UserNotifyMention)
|
|
checkNotifyProp(t, user, model.DesktopSoundNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.EmailNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.PushNotifyProp, model.UserNotifyNone)
|
|
checkNotifyProp(t, user, model.PushStatusNotifyProp, model.StatusAway)
|
|
checkNotifyProp(t, user, model.ChannelMentionsNotifyProp, "false")
|
|
checkNotifyProp(t, user, model.CommentsNotifyProp, model.CommentsNotifyAny)
|
|
checkNotifyProp(t, user, model.MentionKeysNotifyProp, "misc")
|
|
|
|
// Test importing a user with roles set to a team and a channel which are affected by an override scheme.
|
|
// The import subsystem should translate `channel_admin/channel_user/team_admin/team_user`
|
|
// to the appropriate scheme-managed-role booleans.
|
|
|
|
// Mark the phase 2 permissions migration as completed.
|
|
err := th.App.Srv().Store().System().Save(&model.System{Name: model.MigrationKeyAdvancedPermissionsPhase2, Value: "true"})
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
_, err = th.App.Srv().Store().System().PermanentDeleteByName(model.MigrationKeyAdvancedPermissionsPhase2)
|
|
require.NoError(t, err)
|
|
}()
|
|
|
|
teamSchemeData := &imports.SchemeImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
Scope: model.NewPointer("team"),
|
|
DefaultTeamGuestRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultTeamUserRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultTeamAdminRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelGuestRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelUserRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
DefaultChannelAdminRole: &imports.RoleImportData{
|
|
Name: model.NewPointer(model.NewId()),
|
|
DisplayName: model.NewPointer(model.NewId()),
|
|
},
|
|
Description: model.NewPointer("description"),
|
|
}
|
|
|
|
appErr2 = th.App.importScheme(th.Context, teamSchemeData, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
teamScheme, nErr := th.App.Srv().Store().Scheme().GetByName(*teamSchemeData.Name)
|
|
require.NoError(t, nErr, "Failed to import scheme")
|
|
|
|
teamData := &imports.TeamImportData{
|
|
Name: model.NewPointer(NewTestId()),
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
Description: model.NewPointer("The team description."),
|
|
AllowOpenInvite: model.NewPointer(true),
|
|
Scheme: &teamScheme.Name,
|
|
}
|
|
appErr2 = th.App.importTeam(th.Context, teamData, false)
|
|
assert.Nil(t, appErr2)
|
|
team, appErr2 := th.App.GetTeamByName(teamName)
|
|
require.Nil(t, appErr2, "Failed to get team from database.")
|
|
|
|
channelData := &imports.ChannelImportData{
|
|
Team: &teamName,
|
|
Name: model.NewPointer(NewTestId()),
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
Header: model.NewPointer("Channel Header"),
|
|
Purpose: model.NewPointer("Channel Purpose"),
|
|
}
|
|
appErr2 = th.App.importChannel(th.Context, channelData, false)
|
|
assert.Nil(t, appErr2)
|
|
channel, appErr2 := th.App.GetChannelByName(th.Context, *channelData.Name, team.Id, false)
|
|
require.Nil(t, appErr2, "Failed to get channel from database")
|
|
|
|
// Test with a valid team & valid channel name in apply mode.
|
|
userData := &imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Teams: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &team.Name,
|
|
Roles: model.NewPointer("team_user team_admin"),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &channel.Name,
|
|
Roles: model.NewPointer("channel_admin channel_user"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, userData, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, appErr2 = th.App.GetUserByUsername(*userData.Username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
teamMember, appErr2 := th.App.GetTeamMember(th.Context, team.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get the team member")
|
|
|
|
assert.True(t, teamMember.SchemeAdmin)
|
|
assert.True(t, teamMember.SchemeUser)
|
|
assert.False(t, teamMember.SchemeGuest)
|
|
assert.Equal(t, "", teamMember.ExplicitRoles)
|
|
|
|
channelMember, appErr2 := th.App.GetChannelMember(th.Context, channel.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get the channel member")
|
|
|
|
assert.True(t, channelMember.SchemeAdmin)
|
|
assert.True(t, channelMember.SchemeUser)
|
|
assert.False(t, channelMember.SchemeGuest)
|
|
assert.Equal(t, "", channelMember.ExplicitRoles)
|
|
|
|
// Test importing deleted user with a valid team & valid channel name in apply mode.
|
|
username = model.NewUsername()
|
|
deleteAt := model.GetMillis()
|
|
deletedUserData := &imports.UserImportData{
|
|
Username: &username,
|
|
DeleteAt: &deleteAt,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Teams: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &team.Name,
|
|
Roles: model.NewPointer("team_user"),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &channel.Name,
|
|
Roles: model.NewPointer("channel_user"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
appErr2 = th.App.importUser(th.Context, deletedUserData, false)
|
|
assert.Nil(t, appErr2)
|
|
|
|
user, appErr2 = th.App.GetUserByUsername(*deletedUserData.Username)
|
|
require.Nil(t, appErr2, "Failed to get user from database.")
|
|
|
|
teamMember, appErr2 = th.App.GetTeamMember(th.Context, team.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get the team member")
|
|
|
|
assert.False(t, teamMember.SchemeAdmin)
|
|
assert.True(t, teamMember.SchemeUser)
|
|
assert.False(t, teamMember.SchemeGuest)
|
|
assert.Equal(t, "", teamMember.ExplicitRoles)
|
|
|
|
channelMember, appErr2 = th.App.GetChannelMember(th.Context, channel.Id, user.Id)
|
|
require.Nil(t, appErr2, "Failed to get the channel member")
|
|
|
|
assert.False(t, channelMember.SchemeAdmin)
|
|
assert.True(t, channelMember.SchemeUser)
|
|
assert.False(t, channelMember.SchemeGuest)
|
|
assert.Equal(t, "", channelMember.ExplicitRoles)
|
|
})
|
|
|
|
t.Run("import deleted guest with a valid team & valid channel name in apply mode", func(t *testing.T) {
|
|
teamData := &imports.TeamImportData{
|
|
Name: model.NewPointer(model.NewRandomTeamName()),
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
Description: model.NewPointer("The team description."),
|
|
AllowOpenInvite: model.NewPointer(true),
|
|
}
|
|
appErr := th.App.importTeam(th.Context, teamData, false)
|
|
assert.Nil(t, appErr)
|
|
|
|
team, appErr2 := th.App.GetTeamByName(*teamData.Name)
|
|
require.Nil(t, appErr2, "Failed to get team from database.")
|
|
|
|
channelData := &imports.ChannelImportData{
|
|
Team: teamData.Name,
|
|
Name: model.NewPointer(NewTestId()),
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer(model.ChannelTypeOpen),
|
|
Header: model.NewPointer("Channel Header"),
|
|
Purpose: model.NewPointer("Channel Purpose"),
|
|
}
|
|
appErr2 = th.App.importChannel(th.Context, channelData, false)
|
|
assert.Nil(t, appErr2)
|
|
channel, appErr2 := th.App.GetChannelByName(th.Context, *channelData.Name, team.Id, false)
|
|
require.Nil(t, appErr2, "Failed to get channel from database")
|
|
|
|
username := model.NewUsername()
|
|
deleteAt := model.GetMillis()
|
|
deletedGuestData := &imports.UserImportData{
|
|
Username: &username,
|
|
DeleteAt: &deleteAt,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
Roles: model.NewPointer("system_guest"),
|
|
Teams: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &team.Name,
|
|
Roles: model.NewPointer("team_guest"),
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &channel.Name,
|
|
Roles: model.NewPointer("channel_guest"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
appErr = th.App.importUser(th.Context, deletedGuestData, false)
|
|
assert.Nil(t, appErr)
|
|
|
|
user, appErr := th.App.GetUserByUsername(*deletedGuestData.Username)
|
|
require.Nil(t, appErr, "Failed to get user from database.")
|
|
|
|
teamMember, appErr := th.App.GetTeamMember(th.Context, team.Id, user.Id)
|
|
require.Nil(t, appErr, "Failed to get the team member")
|
|
|
|
assert.False(t, teamMember.SchemeAdmin)
|
|
assert.False(t, teamMember.SchemeUser)
|
|
assert.True(t, teamMember.SchemeGuest)
|
|
assert.Equal(t, "", teamMember.ExplicitRoles)
|
|
|
|
channelMember, appErr := th.App.GetChannelMember(th.Context, channel.Id, user.Id)
|
|
require.Nil(t, appErr, "Failed to get the channel member")
|
|
|
|
assert.False(t, teamMember.SchemeAdmin)
|
|
assert.False(t, channelMember.SchemeUser)
|
|
assert.True(t, teamMember.SchemeGuest)
|
|
assert.Equal(t, "", channelMember.ExplicitRoles)
|
|
})
|
|
}
|
|
|
|
func TestImportUserTeams(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic()
|
|
defer th.TearDown()
|
|
team2 := th.CreateTeam()
|
|
channel2 := th.CreateChannel(th.Context, th.BasicTeam)
|
|
channel3 := th.CreateChannel(th.Context, team2)
|
|
customRole := th.CreateRole("test_custom_role")
|
|
sampleTheme := "{\"test\":\"#abcdef\"}"
|
|
|
|
tt := []struct {
|
|
name string
|
|
data *[]imports.UserTeamImportData
|
|
expectedError bool
|
|
expectedUserTeams int
|
|
expectedUserChannels int
|
|
expectedExplicitRoles string
|
|
expectedRoles string
|
|
expectedTheme string
|
|
}{
|
|
{
|
|
name: "Not existing team should fail",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: model.NewPointer("not-existing-team-name"),
|
|
},
|
|
},
|
|
expectedError: true,
|
|
},
|
|
{
|
|
name: "nil data shouldn't do anything",
|
|
expectedError: false,
|
|
expectedUserTeams: 0,
|
|
expectedUserChannels: 0,
|
|
},
|
|
{
|
|
name: "Should fail if one of the roles doesn't exist",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
Roles: model.NewPointer("not-existing-role"),
|
|
},
|
|
},
|
|
expectedError: true,
|
|
expectedUserTeams: 1,
|
|
expectedUserChannels: 0,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "team_user",
|
|
},
|
|
{
|
|
name: "Should success to import explicit role",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
Roles: &customRole.Name,
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserTeams: 1,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: customRole.Name,
|
|
expectedRoles: customRole.Name + " team_user",
|
|
},
|
|
{
|
|
name: "Should success to import admin role",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
Roles: model.NewPointer(model.TeamAdminRoleId),
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserTeams: 1,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "team_user team_admin",
|
|
},
|
|
{
|
|
name: "Should success to import with theme",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
Theme: &sampleTheme,
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserTeams: 1,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "team_user",
|
|
expectedTheme: sampleTheme,
|
|
},
|
|
{
|
|
name: "Team without channels must add the default channel",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserTeams: 1,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "team_user",
|
|
},
|
|
{
|
|
name: "Team with default channel must add only the default channel",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: model.NewPointer(model.DefaultChannelName),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserTeams: 1,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "team_user",
|
|
},
|
|
{
|
|
name: "Team with non default channel must add default channel and the other channel",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &th.BasicChannel.Name,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserTeams: 1,
|
|
expectedUserChannels: 2,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "team_user",
|
|
},
|
|
{
|
|
name: "Multiple teams with multiple channels each",
|
|
data: &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &th.BasicChannel.Name,
|
|
},
|
|
{
|
|
Name: &channel2.Name,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: &team2.Name,
|
|
Channels: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &channel3.Name,
|
|
},
|
|
{
|
|
Name: model.NewPointer("town-square"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserTeams: 2,
|
|
expectedUserChannels: 5,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
user := th.CreateUser()
|
|
|
|
// Two times import must end with the same results
|
|
for range 2 {
|
|
appErr := th.App.importUserTeams(th.Context, user, tc.data)
|
|
if tc.expectedError {
|
|
require.NotNil(t, appErr)
|
|
} else {
|
|
require.Nil(t, appErr)
|
|
}
|
|
teamMembers, nErr := th.App.Srv().Store().Team().GetTeamsForUser(th.Context, user.Id, "", true)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, teamMembers, tc.expectedUserTeams)
|
|
if tc.expectedUserTeams == 1 {
|
|
require.Equal(t, tc.expectedExplicitRoles, teamMembers[0].ExplicitRoles, "Not matching expected explicit roles")
|
|
require.Equal(t, tc.expectedRoles, teamMembers[0].Roles, "not matching expected roles")
|
|
if tc.expectedTheme != "" {
|
|
pref, prefErr := th.App.Srv().Store().Preference().Get(user.Id, model.PreferenceCategoryTheme, teamMembers[0].TeamId)
|
|
require.NoError(t, prefErr)
|
|
require.Equal(t, tc.expectedTheme, pref.Value)
|
|
}
|
|
}
|
|
|
|
totalMembers := 0
|
|
for _, teamMember := range teamMembers {
|
|
channelMembers, err := th.App.Srv().Store().Channel().GetMembersForUser(teamMember.TeamId, user.Id)
|
|
require.NoError(t, err)
|
|
totalMembers += len(channelMembers)
|
|
}
|
|
require.Equal(t, tc.expectedUserChannels, totalMembers)
|
|
}
|
|
})
|
|
}
|
|
|
|
t.Run("Should fail if the MaxUserPerTeam is reached", func(t *testing.T) {
|
|
user := th.CreateUser()
|
|
data := &[]imports.UserTeamImportData{
|
|
{
|
|
Name: &th.BasicTeam.Name,
|
|
},
|
|
}
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 1 })
|
|
defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 100 })
|
|
appErr := th.App.importUserTeams(th.Context, user, data)
|
|
require.NotNil(t, appErr)
|
|
})
|
|
}
|
|
|
|
func TestImportUserChannels(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic()
|
|
defer th.TearDown()
|
|
channel2 := th.CreateChannel(th.Context, th.BasicTeam)
|
|
customRole := th.CreateRole("test_custom_role")
|
|
sampleNotifyProps := imports.UserChannelNotifyPropsImportData{
|
|
Desktop: model.NewPointer("all"),
|
|
Mobile: model.NewPointer("none"),
|
|
MarkUnread: model.NewPointer("all"),
|
|
}
|
|
|
|
tt := []struct {
|
|
name string
|
|
data *[]imports.UserChannelImportData
|
|
expectedError bool
|
|
expectedUserChannels int
|
|
expectedExplicitRoles string
|
|
expectedRoles string
|
|
expectedNotifyProps *imports.UserChannelNotifyPropsImportData
|
|
}{
|
|
{
|
|
name: "Not existing channel should fail",
|
|
data: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: model.NewPointer("not-existing-channel-name"),
|
|
},
|
|
},
|
|
expectedError: true,
|
|
},
|
|
{
|
|
name: "nil data shouldn't do anything",
|
|
expectedError: false,
|
|
expectedUserChannels: 0,
|
|
},
|
|
{
|
|
name: "Should fail if one of the roles doesn't exist",
|
|
data: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &th.BasicChannel.Name,
|
|
Roles: model.NewPointer("not-existing-role"),
|
|
},
|
|
},
|
|
expectedError: true,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "channel_user",
|
|
},
|
|
{
|
|
name: "Should success to import explicit role",
|
|
data: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &th.BasicChannel.Name,
|
|
Roles: &customRole.Name,
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: customRole.Name,
|
|
expectedRoles: customRole.Name + " channel_user",
|
|
},
|
|
{
|
|
name: "Should success to import admin role",
|
|
data: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &th.BasicChannel.Name,
|
|
Roles: model.NewPointer(model.ChannelAdminRoleId),
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "channel_user channel_admin",
|
|
},
|
|
{
|
|
name: "Should success to import with notifyProps",
|
|
data: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &th.BasicChannel.Name,
|
|
NotifyProps: &sampleNotifyProps,
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserChannels: 1,
|
|
expectedExplicitRoles: "",
|
|
expectedRoles: "channel_user",
|
|
expectedNotifyProps: &sampleNotifyProps,
|
|
},
|
|
{
|
|
name: "Should import properly multiple channels",
|
|
data: &[]imports.UserChannelImportData{
|
|
{
|
|
Name: &th.BasicChannel.Name,
|
|
},
|
|
{
|
|
Name: &channel2.Name,
|
|
},
|
|
},
|
|
expectedError: false,
|
|
expectedUserChannels: 2,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
user := th.CreateUser()
|
|
_, _, err := th.App.ch.srv.teamService.JoinUserToTeam(th.Context, th.BasicTeam, user)
|
|
require.NoError(t, err)
|
|
|
|
// Two times import must end with the same results
|
|
for range 2 {
|
|
appErr := th.App.importUserChannels(th.Context, user, th.BasicTeam, tc.data)
|
|
if tc.expectedError {
|
|
require.NotNil(t, appErr)
|
|
} else {
|
|
require.Nil(t, appErr)
|
|
}
|
|
channelMembers, err := th.App.Srv().Store().Channel().GetMembersForUser(th.BasicTeam.Id, user.Id)
|
|
require.NoError(t, err)
|
|
require.Len(t, channelMembers, tc.expectedUserChannels)
|
|
if tc.expectedUserChannels == 1 {
|
|
channelMember := channelMembers[0]
|
|
require.Equal(t, tc.expectedExplicitRoles, channelMember.ExplicitRoles, "Not matching expected explicit roles")
|
|
require.Equal(t, tc.expectedRoles, channelMember.Roles, "not matching expected roles")
|
|
if tc.expectedNotifyProps != nil {
|
|
require.Equal(t, *tc.expectedNotifyProps.Desktop, channelMember.NotifyProps[model.DesktopNotifyProp])
|
|
require.Equal(t, *tc.expectedNotifyProps.Mobile, channelMember.NotifyProps[model.PushNotifyProp])
|
|
require.Equal(t, *tc.expectedNotifyProps.MarkUnread, channelMember.NotifyProps[model.MarkUnreadNotifyProp])
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestImportUserDefaultNotifyProps(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Create a valid new user with some, but not all, notify props populated.
|
|
username := model.NewUsername()
|
|
data := imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
NotifyProps: &imports.UserNotifyPropsImportData{
|
|
Email: model.NewPointer("false"),
|
|
MentionKeys: model.NewPointer(""),
|
|
},
|
|
}
|
|
require.Nil(t, th.App.importUser(th.Context, &data, false))
|
|
|
|
user, err := th.App.GetUserByUsername(username)
|
|
require.Nil(t, err)
|
|
|
|
// Check the value of the notify prop we specified explicitly in the import data.
|
|
val, ok := user.NotifyProps[model.EmailNotifyProp]
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "false", val)
|
|
|
|
// Check all the other notify props are set to their default values.
|
|
comparisonUser := model.User{Username: user.Username}
|
|
comparisonUser.SetDefaultNotifications()
|
|
|
|
for key, expectedValue := range comparisonUser.NotifyProps {
|
|
if key == model.EmailNotifyProp {
|
|
continue
|
|
}
|
|
|
|
val, ok := user.NotifyProps[key]
|
|
assert.True(t, ok)
|
|
assert.Equal(t, expectedValue, val)
|
|
}
|
|
}
|
|
|
|
func TestImportimportMultiplePostLines(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Create a Team.
|
|
teamName := model.NewRandomTeamName()
|
|
appErr := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import team.")
|
|
team, err := th.App.GetTeamByName(teamName)
|
|
require.Nil(t, err, "Failed to get team from database.")
|
|
|
|
// Create a Channel.
|
|
channelName := NewTestId()
|
|
chanTypeOpen := model.ChannelTypeOpen
|
|
appErr = th.App.importChannel(th.Context, &imports.ChannelImportData{
|
|
Team: &teamName,
|
|
Name: &channelName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import channel.")
|
|
channel, err := th.App.GetChannelByName(th.Context, channelName, team.Id, false)
|
|
require.Nil(t, err, "Failed to get channel from database.")
|
|
|
|
// Create a user.
|
|
username := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user.")
|
|
user, err := th.App.GetUserByUsername(username)
|
|
require.Nil(t, err, "Failed to get user from database.")
|
|
|
|
username2 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username2,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user.")
|
|
user2, err := th.App.GetUserByUsername(username2)
|
|
require.Nil(t, err, "Failed to get user from database.")
|
|
|
|
// Count the number of posts in the testing team.
|
|
require.NoError(t, th.App.Srv().Store().Post().RefreshPostStats())
|
|
initialPostCount, nErr := th.App.Srv().Store().Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: team.Id})
|
|
require.NoError(t, nErr)
|
|
|
|
createAt := model.GetMillis()
|
|
hashtagTime := createAt + 2
|
|
replyPostTime := hashtagTime + 4
|
|
replyTime := hashtagTime + 5
|
|
|
|
var assertionCount int64
|
|
|
|
t.Run("invalid post in dry run mode", func(t *testing.T) {
|
|
// Try adding an invalid post in dry run mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
},
|
|
},
|
|
LineNumber: 25,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
assert.NotNil(t, err2)
|
|
assert.Equal(t, data.LineNumber, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("valid post in dry run mode", func(t *testing.T) {
|
|
// Try adding a valid post in dry run mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Hello"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
assert.Nil(t, err2)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("invalid post in apply mode", func(t *testing.T) {
|
|
// Try adding an invalid post in apply mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 35,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err2)
|
|
assert.Equal(t, data.LineNumber, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("valid post with invalid team in apply mode", func(t *testing.T) {
|
|
// Try adding a valid post with invalid team in apply mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: model.NewPointer(NewTestId()),
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 10,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err2)
|
|
// Batch will fail when searching for teams, so no specific line
|
|
// is associated with the error
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("valid post with invalid channel in apply mode", func(t *testing.T) {
|
|
// Try adding a valid post with invalid channel in apply mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: model.NewPointer(NewTestId()),
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 7,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err2)
|
|
// Batch will fail when searching for channels, so no specific
|
|
// line is associated with the error
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("valid post with invalid user in apply mode", func(t *testing.T) {
|
|
// Try adding a valid post with invalid user in apply mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: model.NewPointer(model.NewId()),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 2,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err2)
|
|
// Batch will fail when searching for users, so no specific line
|
|
// is associated with the error
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("valid post in apply mode", func(t *testing.T) {
|
|
// Try adding a valid post in apply mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: &createAt,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2)
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, createAt)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
// Update the post.
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: &createAt,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr = th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, createAt)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post = posts[0]
|
|
postBool = post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
})
|
|
|
|
t.Run("import the post with a different time", func(t *testing.T) {
|
|
// Save the post with a different time.
|
|
newTime := createAt + 1
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: &newTime,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2)
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
})
|
|
|
|
t.Run("import the post with a different message", func(t *testing.T) {
|
|
// Save the post with a different message.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message 2"),
|
|
CreateAt: &createAt,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2)
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
})
|
|
|
|
t.Run("import post with hashtags", func(t *testing.T) {
|
|
// Test with hashtags
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message 2 #hashtagmashupcity"),
|
|
CreateAt: &hashtagTime,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2)
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, hashtagTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
require.Equal(t, "#hashtagmashupcity", post.Hashtags, "Hashtags not as expected: %s", post.Hashtags)
|
|
})
|
|
|
|
t.Run("import post with flags", func(t *testing.T) {
|
|
// Post with flags.
|
|
flagsTime := hashtagTime + 1
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with Favorites"),
|
|
CreateAt: &flagsTime,
|
|
FlaggedBy: &[]string{
|
|
username,
|
|
username2,
|
|
},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, flagsTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
checkPreference(t, th.App, user2.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
})
|
|
|
|
t.Run("import new post with reactions", func(t *testing.T) {
|
|
// Post with reaction.
|
|
reactionPostTime := hashtagTime + 2
|
|
reactionTime := hashtagTime + 3
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with reactions"),
|
|
CreateAt: &reactionPostTime,
|
|
Reactions: &[]imports.ReactionImportData{{
|
|
User: &user2.Username,
|
|
EmojiName: model.NewPointer("+1"),
|
|
CreateAt: &reactionTime,
|
|
}, {
|
|
User: &user.Username,
|
|
EmojiName: model.NewPointer("+1"),
|
|
CreateAt: &reactionTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, reactionPostTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id || !post.HasReactions
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
reactions, nErr := th.App.Srv().Store().Reaction().GetForPost(post.Id, false)
|
|
require.NoError(t, nErr, "Can't get reaction")
|
|
|
|
require.Len(t, reactions, 2, "Invalid number of reactions")
|
|
|
|
// Update post with replies with reactions.
|
|
newReactionTime := reactionTime + 1
|
|
newReplyTime := reactionPostTime + 1
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with reactions"),
|
|
CreateAt: &reactionPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &newReplyTime,
|
|
Reactions: &[]imports.ReactionImportData{{
|
|
User: &user2.Username,
|
|
EmojiName: model.NewPointer("+1"),
|
|
CreateAt: &newReactionTime,
|
|
}},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
// No new post created, only the reply is added.
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr = th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, newReplyTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post = posts[0]
|
|
|
|
reactions, nErr = th.App.Srv().Store().Reaction().GetForPost(post.Id, false)
|
|
require.NoError(t, nErr, "Can't get reaction")
|
|
|
|
require.Len(t, reactions, 1, "Invalid number of reactions")
|
|
})
|
|
|
|
t.Run("import post with reactions with new replies", func(t *testing.T) {
|
|
// Post with reaction.
|
|
reactionPostTime := hashtagTime + 11
|
|
reactionTime := hashtagTime + 12
|
|
newReplyTime := reactionPostTime + 1
|
|
newReactionTime := reactionTime + 1
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with reaction"),
|
|
CreateAt: &reactionPostTime,
|
|
Reactions: &[]imports.ReactionImportData{{
|
|
User: &user2.Username,
|
|
EmojiName: model.NewPointer("+1"),
|
|
CreateAt: &reactionTime,
|
|
}},
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &newReplyTime,
|
|
Reactions: &[]imports.ReactionImportData{{
|
|
User: &user2.Username,
|
|
EmojiName: model.NewPointer("+1"),
|
|
CreateAt: &newReactionTime,
|
|
}},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount += 2
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, reactionPostTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id || !post.HasReactions
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
reactions, nErr := th.App.Srv().Store().Reaction().GetForPost(post.Id, false)
|
|
require.NoError(t, nErr, "Can't get reaction")
|
|
|
|
require.Len(t, reactions, 1, "Invalid number of reactions")
|
|
|
|
// Check the post values.
|
|
posts, nErr = th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, newReplyTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post = posts[0]
|
|
|
|
reactions, nErr = th.App.Srv().Store().Reaction().GetForPost(post.Id, false)
|
|
require.NoError(t, nErr, "Can't get reaction")
|
|
|
|
require.Len(t, reactions, 1, "Invalid number of reactions")
|
|
})
|
|
|
|
t.Run("import post with replies", func(t *testing.T) {
|
|
// Post with reply.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &replyTime,
|
|
Props: &model.StringInterface{"key": "value"},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount += 2
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, replyPostTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
// Check the reply values.
|
|
replies, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, replyTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, replies, 1, "Unexpected number of posts found.")
|
|
|
|
reply := replies[0]
|
|
replyBool := reply.Message != *(*data.Post.Replies)[0].Message || reply.CreateAt != *(*data.Post.Replies)[0].CreateAt || reply.UserId != user2.Id
|
|
require.False(t, replyBool, "Post properties not as expected")
|
|
|
|
v := reply.GetProp("key")
|
|
require.NotNil(t, v, "Post prop should exist")
|
|
require.Equal(t, "value", v, "Post props not as expected")
|
|
|
|
require.Equal(t, post.Id, reply.RootId, "Unexpected reply RootId")
|
|
})
|
|
|
|
t.Run("update post with replies", func(t *testing.T) {
|
|
replyPostTime2 := replyPostTime + 1
|
|
// Create post without replies.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &replyPostTime2,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err2, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Update post with replies.
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &replyPostTime2,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
// No new post created, only the reply is added.
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Create new post with replies based on the previous one.
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply 2"),
|
|
CreateAt: &replyPostTime2,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount += 2
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Create new reply for existing post with replies.
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &replyPostTime2,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply 2"),
|
|
CreateAt: &replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount++
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Create new reply with type and edit_at for existing post with replies.
|
|
editedReplyPostTime := hashtagTime + 6
|
|
editedReplyTime := hashtagTime + 7
|
|
editedReplyEditTime := hashtagTime + 8
|
|
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &editedReplyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Type: model.NewPointer(model.PostTypeSystemGeneric),
|
|
Message: model.NewPointer("Message reply 3"),
|
|
CreateAt: &editedReplyTime,
|
|
EditAt: &editedReplyEditTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err, "Expected success.")
|
|
assert.Equal(t, 0, errLine)
|
|
assertionCount += 2
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
|
|
// Check the reply values.
|
|
replies, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, editedReplyTime)
|
|
assert.NoError(t, nErr, "Expected success.")
|
|
reply := replies[0]
|
|
importReply := (*data.Post.Replies)[0]
|
|
replyBool := reply.Type != *importReply.Type || reply.Message != *importReply.Message || reply.CreateAt != *importReply.CreateAt || reply.EditAt != *importReply.EditAt || reply.UserId != user.Id
|
|
require.False(t, replyBool, "Post properties not as expected")
|
|
})
|
|
|
|
t.Run("import post with pinned message", func(t *testing.T) {
|
|
// Create another Team.
|
|
teamName2 := model.NewRandomTeamName()
|
|
appErr := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName2,
|
|
DisplayName: model.NewPointer("Display Name 2"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import team.")
|
|
team2, err2 := th.App.GetTeamByName(teamName2)
|
|
require.Nil(t, err2, "Failed to get team from database.")
|
|
|
|
// Create another Channel for the another team.
|
|
appErr = th.App.importChannel(th.Context, &imports.ChannelImportData{
|
|
Team: &teamName2,
|
|
Name: &channelName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import channel.")
|
|
_, err = th.App.GetChannelByName(th.Context, channelName, team2.Id, false)
|
|
require.Nil(t, err, "Failed to get channel from database.")
|
|
|
|
// Count the number of posts in the team2.
|
|
require.NoError(t, th.App.Srv().Store().Post().RefreshPostStats())
|
|
initialPostCountForTeam2, nErr := th.App.Srv().Store().Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: team2.Id})
|
|
require.NoError(t, nErr)
|
|
|
|
// Try adding two valid posts in apply mode.
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("another message"),
|
|
CreateAt: &createAt,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
data2 := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName2,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("another message"),
|
|
CreateAt: &createAt,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data, data2}, false, true)
|
|
assert.Nil(t, err2)
|
|
assert.Equal(t, 0, errLine)
|
|
|
|
// Create a pinned message.
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Pinned Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
IsPinned: model.NewPointer(true),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, *data.Post.CreateAt)
|
|
require.NoError(t, nErr, "Expected success.")
|
|
// Should be one post only created at this time.
|
|
require.Equal(t, 1, len(resultPosts))
|
|
resultPost := resultPosts[0]
|
|
require.True(t, resultPost.IsPinned, "This post should be pinned.")
|
|
|
|
// Posts should be added to the right team
|
|
AssertAllPostsCount(t, th.App, initialPostCountForTeam2, 1, team2.Id)
|
|
assertionCount += 2
|
|
AssertAllPostsCount(t, th.App, initialPostCount, assertionCount, team.Id)
|
|
})
|
|
|
|
t.Run("Importing a post with a reply both pinned", func(t *testing.T) {
|
|
// Create a thread.
|
|
importCreate := time.Now().Add(-1 * time.Minute).UnixMilli()
|
|
replyCreate := time.Now().Add(-30 * time.Second).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Thread Message"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
IsPinned: model.NewPointer(true),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(replyCreate),
|
|
IsPinned: model.NewPointer(true),
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
_, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, importCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
require.True(t, resultPosts[0].IsPinned)
|
|
|
|
resultPosts, nErr = th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, replyCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
require.True(t, resultPosts[0].IsPinned)
|
|
})
|
|
|
|
t.Run("Importing a post with a thread", func(t *testing.T) {
|
|
// Create a thread.
|
|
importCreate := time.Now().Add(-1 * time.Minute).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Thread Message"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
ThreadFollowers: &[]imports.ThreadFollowerImportData{{
|
|
User: &user.Username,
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}, {
|
|
User: &user2.Username,
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err2 := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err2)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, importCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
|
|
followers, nErr := th.App.Srv().Store().Thread().GetThreadFollowers(resultPosts[0].Id, true)
|
|
require.NoError(t, nErr)
|
|
|
|
assert.ElementsMatch(t, []string{user.Id, user2.Id}, followers)
|
|
})
|
|
|
|
t.Run("Importing a post with a non existent follower", func(t *testing.T) {
|
|
// Create a thread.
|
|
importCreate := time.Now().Add(-1 * time.Minute).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Thread Message"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
ThreadFollowers: &[]imports.ThreadFollowerImportData{{
|
|
User: &user.Username,
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}, {
|
|
User: model.NewPointer("invalid.user"),
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.NotNil(t, err)
|
|
require.Equal(t, 1, errLine)
|
|
})
|
|
|
|
t.Run("Importing a post with a non existent follower", func(t *testing.T) {
|
|
importCreate := time.Now().Add(-1 * time.Minute).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Thread Message"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
ThreadFollowers: &[]imports.ThreadFollowerImportData{{
|
|
User: &user.Username,
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}, {
|
|
User: model.NewPointer("invalid.user"),
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.NotNil(t, err)
|
|
require.Equal(t, 1, errLine)
|
|
})
|
|
|
|
t.Run("Importing a post with new followers", func(t *testing.T) {
|
|
importCreate := time.Now().Add(-5 * time.Minute).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Hello"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, importCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Hello"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
ThreadFollowers: &[]imports.ThreadFollowerImportData{{
|
|
User: &user.Username,
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
followers, nErr := th.App.Srv().Store().Thread().GetThreadFollowers(resultPosts[0].Id, true)
|
|
require.NoError(t, nErr)
|
|
|
|
assert.ElementsMatch(t, []string{user.Id}, followers)
|
|
})
|
|
|
|
t.Run("Importing a post that someone flagged", func(t *testing.T) {
|
|
// Create a thread.
|
|
importCreate := time.Now().Add(-1 * time.Minute).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Flagged Message"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
FlaggedBy: &[]string{user.Username},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, importCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
|
|
pref, nErr := th.App.ch.srv.Store().Preference().GetCategoryAndName(model.PreferenceCategoryFlaggedPost, resultPosts[0].Id)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, pref, 1)
|
|
assert.Equal(t, user.Id, pref[0].UserId)
|
|
})
|
|
|
|
t.Run("Importing a post that someone flagged its replies", func(t *testing.T) {
|
|
// Create a thread.
|
|
importCreate := time.Now().Add(-1 * time.Minute).UnixMilli()
|
|
replyCreate := time.Now().Add(-30 * time.Second).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Flagged Message"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user.Username,
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(replyCreate),
|
|
FlaggedBy: &[]string{user2.Username},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, replyCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
|
|
pref, nErr := th.App.ch.srv.Store().Preference().GetCategoryAndName(model.PreferenceCategoryFlaggedPost, resultPosts[0].Id)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, pref, 1)
|
|
assert.Equal(t, user2.Id, pref[0].UserId)
|
|
})
|
|
}
|
|
|
|
func TestImportImportPost(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Create a Team.
|
|
teamName := model.NewRandomTeamName()
|
|
appErr := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import team.")
|
|
team, appErr := th.App.GetTeamByName(teamName)
|
|
require.Nil(t, appErr, "Failed to get team from database.")
|
|
|
|
// Create a Channel.
|
|
channelName := NewTestId()
|
|
chanTypeOpen := model.ChannelTypeOpen
|
|
appErr = th.App.importChannel(th.Context, &imports.ChannelImportData{
|
|
Team: &teamName,
|
|
Name: &channelName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import channel.")
|
|
channel, appErr := th.App.GetChannelByName(th.Context, channelName, team.Id, false)
|
|
require.Nil(t, appErr, "Failed to get channel from database.")
|
|
|
|
// Create a user.
|
|
username := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user.")
|
|
user, appErr := th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr, "Failed to get user from database.")
|
|
|
|
username2 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username2,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user.")
|
|
user2, appErr := th.App.GetUserByUsername(username2)
|
|
require.Nil(t, appErr, "Failed to get user from database.")
|
|
|
|
// Count the number of posts in the testing team.
|
|
require.NoError(t, th.App.Srv().Store().Post().RefreshPostStats())
|
|
initialPostCount, nErr := th.App.Srv().Store().Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: team.Id})
|
|
require.NoError(t, nErr)
|
|
|
|
time := model.GetMillis()
|
|
hashtagTime := time + 2
|
|
replyPostTime := hashtagTime + 4
|
|
replyTime := hashtagTime + 5
|
|
posttypeTime := hashtagTime + 6
|
|
editatCreateTime := hashtagTime + 7
|
|
editatEditTime := hashtagTime + 8
|
|
|
|
t.Run("Try adding an invalid post in dry run mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
},
|
|
},
|
|
LineNumber: 12,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
assert.NotNil(t, err)
|
|
assert.Equal(t, data.LineNumber, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("Try adding a valid post in dry run mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Hello"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("Try adding an invalid post in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 2,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err)
|
|
assert.Equal(t, data.LineNumber, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("Try adding a valid post with invalid team in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: model.NewPointer(NewTestId()),
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 7,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("Try adding a valid post with invalid channel in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: model.NewPointer(NewTestId()),
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 8,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("Try adding a valid post with invalid user in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: model.NewPointer(model.NewId()),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 9,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.NotNil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, team.Id)
|
|
})
|
|
|
|
t.Run("Try adding a valid post in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: &time,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, time)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
})
|
|
|
|
t.Run("Update the post", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username2,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: &time,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 1, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, time)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user2.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
})
|
|
|
|
t.Run("Save the post with a different time", func(t *testing.T) {
|
|
newTime := time + 1
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: &newTime,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 2, team.Id)
|
|
})
|
|
|
|
t.Run("Save the post with a different message", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message 2"),
|
|
CreateAt: &time,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 3, team.Id)
|
|
})
|
|
|
|
t.Run("Test with hashtag", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message 2 #hashtagmashupcity"),
|
|
CreateAt: &hashtagTime,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 4, team.Id)
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, hashtagTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
require.Equal(t, "#hashtagmashupcity", post.Hashtags, "Hashtags not as expected: %s", post.Hashtags)
|
|
})
|
|
|
|
t.Run("Post with flags", func(t *testing.T) {
|
|
flagsTime := hashtagTime + 1
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with Favorites"),
|
|
CreateAt: &flagsTime,
|
|
FlaggedBy: &[]string{
|
|
username,
|
|
username2,
|
|
},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 5, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, flagsTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
checkPreference(t, th.App, user.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
checkPreference(t, th.App, user2.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
})
|
|
|
|
t.Run("Post with reaction", func(t *testing.T) {
|
|
reactionPostTime := hashtagTime + 2
|
|
reactionTime := hashtagTime + 3
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with reaction"),
|
|
CreateAt: &reactionPostTime,
|
|
Reactions: &[]imports.ReactionImportData{{
|
|
User: &user2.Username,
|
|
EmojiName: model.NewPointer("+1"),
|
|
CreateAt: &reactionTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 6, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, reactionPostTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id || !post.HasReactions
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
reactions, nErr := th.App.Srv().Store().Reaction().GetForPost(post.Id, false)
|
|
require.NoError(t, nErr, "Can't get reaction")
|
|
|
|
require.Len(t, reactions, 1, "Invalid number of reactions")
|
|
})
|
|
|
|
t.Run("Post with reply", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 8, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, replyPostTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
// Check the reply values.
|
|
replies, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, replyTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, replies, 1, "Unexpected number of posts found.")
|
|
|
|
reply := replies[0]
|
|
replyBool := reply.Message != *(*data.Post.Replies)[0].Message || reply.CreateAt != *(*data.Post.Replies)[0].CreateAt || reply.UserId != user2.Id
|
|
require.False(t, replyBool, "Post properties not as expected")
|
|
|
|
require.Equal(t, post.Id, reply.RootId, "Unexpected reply RootId")
|
|
})
|
|
|
|
t.Run("Update post with replies", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 8, team.Id)
|
|
})
|
|
|
|
t.Run("Create new post with replies based on the previous one", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply 2"),
|
|
CreateAt: &replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 10, team.Id)
|
|
})
|
|
|
|
t.Run("Create new reply for existing post with replies", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply 2"),
|
|
CreateAt: &replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 11, team.Id)
|
|
})
|
|
|
|
t.Run("Post with Type", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Type: model.NewPointer(model.PostTypeSystemGeneric),
|
|
Message: model.NewPointer("Message with Type"),
|
|
CreateAt: &posttypeTime,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 12, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, posttypeTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id || post.Type != *data.Post.Type
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
})
|
|
|
|
t.Run("Post with EditAt", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username,
|
|
Message: model.NewPointer("Message with Type"),
|
|
CreateAt: &editatCreateTime,
|
|
EditAt: &editatEditTime,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 13, team.Id)
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, editatCreateTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.Post.Message || post.CreateAt != *data.Post.CreateAt || post.UserId != user.Id || post.EditAt != *data.Post.EditAt
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
})
|
|
|
|
t.Run("Reply CreateAt before parent post CreateAt", func(t *testing.T) {
|
|
now := model.GetMillis()
|
|
before := now - 10
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &now,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &username,
|
|
Message: model.NewPointer("Message reply 2"),
|
|
CreateAt: &before,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, now)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 2, "Unexpected number of posts found.")
|
|
require.NoError(t, th.TestLogger.Flush())
|
|
testlib.AssertLog(t, th.LogBuffer, mlog.LvlWarn.Name, "Reply CreateAt is before parent post CreateAt, setting it to parent post CreateAt")
|
|
|
|
rootPost := posts[0]
|
|
replyPost := posts[1]
|
|
if rootPost.RootId != "" {
|
|
replyPost = posts[0]
|
|
rootPost = posts[1]
|
|
}
|
|
require.Equal(t, rootPost.Id, replyPost.RootId)
|
|
require.Equal(t, now, replyPost.CreateAt)
|
|
})
|
|
}
|
|
|
|
func TestImportImportDirectChannel(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic()
|
|
defer th.TearDown()
|
|
user3 := th.CreateUser()
|
|
|
|
// Check how many channels are in the database.
|
|
directChannelCount, err := th.App.Srv().Store().Channel().AnalyticsTypeCount("", model.ChannelTypeDirect)
|
|
require.NoError(t, err, "Failed to get direct channel count.")
|
|
|
|
groupChannelCount, err := th.App.Srv().Store().Channel().AnalyticsTypeCount("", model.ChannelTypeGroup)
|
|
require.NoError(t, err, "Failed to get group channel count.")
|
|
|
|
// We need to generate the dataset twice to test the same data with different formats.
|
|
generateDataset := func(data imports.DirectChannelImportData) map[string]imports.DirectChannelImportData {
|
|
members := make([]string, len(data.Participants))
|
|
for i, member := range data.Participants {
|
|
members[i] = *member.Username
|
|
}
|
|
|
|
return map[string]imports.DirectChannelImportData{
|
|
"Participants": data,
|
|
"Members": {
|
|
Members: &members,
|
|
},
|
|
}
|
|
}
|
|
|
|
t.Run("Invalid channel in dry-run mode", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
},
|
|
Header: model.NewPointer("Channel Header"),
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
err = th.App.importDirectChannel(th.Context, &data, true)
|
|
require.Error(t, err)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Valid DIRECT channel with a nonexistent member in dry-run mode", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
},
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
appErr := th.App.importDirectChannel(th.Context, &data, true)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Valid GROUP channel with a nonexistent member in dry-run mode", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
},
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
appErr := th.App.importDirectChannel(th.Context, &data, true)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Invalid channel in apply mode", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
},
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
err = th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Error(t, err)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Valid DIRECT channel ", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
},
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
appErr := th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that one more DIRECT channel is in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount+1)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
|
|
// Do the same DIRECT channel again.
|
|
appErr = th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount+1)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
|
|
// Update the channel's HEADER
|
|
data.Header = model.NewPointer("New Channel Header 2")
|
|
appErr = th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount+1)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
|
|
// Get the channel to check that the header was updated.
|
|
channel, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
|
|
require.Nil(t, appErr)
|
|
require.Equal(t, channel.Header, *data.Header)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("GROUP channel with an extra invalid member", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(user3.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(model.NewId()),
|
|
},
|
|
},
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
appErr := th.App.importDirectChannel(th.Context, &data, false)
|
|
require.NotNil(t, appErr)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount+1)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Valid GROUP channel", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(user3.Username),
|
|
},
|
|
},
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
appErr := th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that one more GROUP channel is in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount+1)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount+1)
|
|
|
|
// Do the same DIRECT channel again.
|
|
appErr = th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount+1)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount+1)
|
|
|
|
// Update the channel's HEADER
|
|
data.Header = model.NewPointer("New Channel Header 3")
|
|
appErr = th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Check that no more channels are in the DB.
|
|
AssertChannelCount(t, th.App, model.ChannelTypeDirect, directChannelCount+1)
|
|
AssertChannelCount(t, th.App, model.ChannelTypeGroup, groupChannelCount+1)
|
|
|
|
// Get the channel to check that the header was updated.
|
|
userIDs := []string{
|
|
th.BasicUser.Id,
|
|
th.BasicUser2.Id,
|
|
user3.Id,
|
|
}
|
|
channel, appErr := th.App.createGroupChannel(th.Context, userIDs, th.BasicUser.Id)
|
|
require.Equal(t, appErr.Id, store.ChannelExistsError)
|
|
require.Equal(t, channel.Header, *data.Header)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Import a channel with some favorites", func(t *testing.T) {
|
|
dataset := generateDataset(imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
},
|
|
})
|
|
for name, data := range dataset {
|
|
t.Run(name, func(t *testing.T) {
|
|
data.FavoritedBy = &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
}
|
|
appErr := th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
channel, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
|
|
require.Nil(t, appErr)
|
|
checkPreference(t, th.App, th.BasicUser.Id, model.PreferenceCategoryFavoriteChannel, channel.Id, "true")
|
|
checkPreference(t, th.App, th.BasicUser2.Id, model.PreferenceCategoryFavoriteChannel, channel.Id, "true")
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Import a DM channel and user last view should be imported", func(t *testing.T) {
|
|
lastView := model.GetMillis()
|
|
data := imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
LastViewedAt: model.NewPointer(lastView),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
},
|
|
}
|
|
|
|
appErr := th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
channel, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
|
|
require.Nil(t, appErr)
|
|
|
|
members, appErr := th.App.GetChannelMembersPage(th.Context, channel.Id, 0, 100)
|
|
require.Nil(t, appErr)
|
|
require.Len(t, members, 2)
|
|
|
|
for _, member := range members {
|
|
if member.UserId == th.BasicUser.Id {
|
|
require.Equal(t, member.LastViewedAt, lastView)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("Import a DM channel and preserve if the channel was shown to users", func(t *testing.T) {
|
|
data := imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
},
|
|
ShownBy: &[]string{
|
|
th.BasicUser.Username,
|
|
},
|
|
}
|
|
|
|
appErr := th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
channel, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
|
|
require.Nil(t, appErr)
|
|
|
|
members, appErr := th.App.GetChannelMembersPage(th.Context, channel.Id, 0, 100)
|
|
require.Nil(t, appErr)
|
|
require.Len(t, members, 2)
|
|
|
|
for _, member := range members {
|
|
if member.UserId == th.BasicUser.Id {
|
|
checkPreference(t, th.App, th.BasicUser.Id, model.PreferenceCategoryDirectChannelShow, th.BasicUser2.Id, "true")
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("Import a GM channel and preserve if the channel was shown to users", func(t *testing.T) {
|
|
data := imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(user3.Username),
|
|
},
|
|
},
|
|
ShownBy: &[]string{
|
|
th.BasicUser.Username,
|
|
},
|
|
}
|
|
|
|
appErr := th.App.importDirectChannel(th.Context, &data, false)
|
|
require.Nil(t, appErr)
|
|
|
|
channel, appErr := th.App.GetGroupChannel(th.Context, []string{th.BasicUser.Id, th.BasicUser2.Id, user3.Id})
|
|
require.Nil(t, appErr)
|
|
|
|
members, appErr := th.App.GetChannelMembersPage(th.Context, channel.Id, 0, 100)
|
|
require.Nil(t, appErr)
|
|
require.Len(t, members, 3)
|
|
|
|
for _, member := range members {
|
|
if member.UserId == th.BasicUser.Id {
|
|
checkPreference(t, th.App, th.BasicUser.Id, model.PreferenceCategoryGroupChannelShow, channel.Id, "true")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestImportImportDirectPost(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t).InitBasic()
|
|
defer th.TearDown()
|
|
|
|
// Create the DIRECT channel.
|
|
channelData := imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
},
|
|
}
|
|
appErr := th.App.importDirectChannel(th.Context, &channelData, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Get the channel.
|
|
var directChannel *model.Channel
|
|
channel, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
|
|
require.Nil(t, appErr)
|
|
require.NotEmpty(t, channel)
|
|
directChannel = channel
|
|
|
|
// Get the number of posts in the system.
|
|
require.NoError(t, th.App.Srv().Store().Post().RefreshPostStats())
|
|
result, err := th.App.Srv().Store().Post().AnalyticsPostCount(&model.PostCountOptions{})
|
|
require.NoError(t, err)
|
|
initialPostCount := result
|
|
initialDate := model.GetMillis()
|
|
posttypeDate := initialDate + 3
|
|
editatCreateDate := initialDate + 4
|
|
editatEditDate := initialDate + 5
|
|
|
|
t.Run("Try adding an invalid post in dry run mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 7,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
require.NotNil(t, err)
|
|
require.Equal(t, data.LineNumber, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
|
|
})
|
|
|
|
t.Run("Try adding a valid post in dry run mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
|
|
})
|
|
|
|
t.Run("Try adding an invalid post in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
model.NewId(),
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 9,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.NotNil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
|
|
})
|
|
|
|
t.Run("Try adding a valid post in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(initialDate),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(directChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
require.Equal(t, post.Message, *data.DirectPost.Message)
|
|
require.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
require.Equal(t, post.UserId, th.BasicUser.Id)
|
|
})
|
|
|
|
t.Run("Import the post again", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(initialDate),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(directChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
require.Equal(t, post.Message, *data.DirectPost.Message)
|
|
require.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
require.Equal(t, post.UserId, th.BasicUser.Id)
|
|
})
|
|
|
|
t.Run("Save the post with a different time", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(initialDate + 1),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
|
|
})
|
|
|
|
t.Run("Save the post with a different message", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message 2"),
|
|
CreateAt: model.NewPointer(initialDate + 1),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
|
|
})
|
|
|
|
t.Run("Test with hashtag", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message 2 #hashtagmashupcity"),
|
|
CreateAt: model.NewPointer(initialDate + 2),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(directChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
require.Equal(t, post.Message, *data.DirectPost.Message)
|
|
require.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
require.Equal(t, post.UserId, th.BasicUser.Id)
|
|
require.Equal(t, post.Hashtags, "#hashtagmashupcity")
|
|
})
|
|
|
|
t.Run("Test with some flags", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
FlaggedBy: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 5, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(directChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
checkPreference(t, th.App, th.BasicUser.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
checkPreference(t, th.App, th.BasicUser2.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
})
|
|
|
|
t.Run("Test with Type", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Type: model.NewPointer(model.PostTypeSystemGeneric),
|
|
Message: model.NewPointer("Message with Type"),
|
|
CreateAt: model.NewPointer(posttypeDate),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 6, "")
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(directChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
assert.Equal(t, post.Type, *data.DirectPost.Type)
|
|
assert.Equal(t, post.Message, *data.DirectPost.Message)
|
|
assert.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
assert.Equal(t, post.UserId, th.BasicUser.Id)
|
|
})
|
|
|
|
t.Run("Test with EditAt", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message with EditAt"),
|
|
CreateAt: model.NewPointer(editatCreateDate),
|
|
EditAt: model.NewPointer(editatEditDate),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 7, "")
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(directChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
assert.Equal(t, post.Message, *data.DirectPost.Message)
|
|
assert.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
assert.Equal(t, post.EditAt, *data.DirectPost.EditAt)
|
|
assert.Equal(t, post.UserId, th.BasicUser.Id)
|
|
})
|
|
|
|
t.Run("Test with IsPinned", func(t *testing.T) {
|
|
pinnedValue := true
|
|
creationTime := model.GetMillis()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message with EditAt"),
|
|
CreateAt: &creationTime,
|
|
IsPinned: &pinnedValue,
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 8, "")
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(directChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
require.True(t, post.IsPinned)
|
|
})
|
|
|
|
t.Run("Importing a direct post with a thread", func(t *testing.T) {
|
|
// Create a thread.
|
|
importCreate := time.Now().Add(-1 * time.Minute).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Thread Message"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
ThreadFollowers: &[]imports.ThreadFollowerImportData{{
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}, {
|
|
User: model.NewPointer(th.BasicUser2.Username),
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, importCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
|
|
followers, nErr := th.App.Srv().Store().Thread().GetThreadFollowers(resultPosts[0].Id, true)
|
|
require.NoError(t, nErr)
|
|
|
|
assert.ElementsMatch(t, []string{th.BasicUser.Id, th.BasicUser2.Id}, followers)
|
|
})
|
|
|
|
t.Run("Importing a direct post with new followers", func(t *testing.T) {
|
|
importCreate := time.Now().Add(-5 * time.Minute).UnixMilli()
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Hello"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
resultPosts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, importCreate)
|
|
require.NoError(t, nErr)
|
|
require.Equal(t, 1, len(resultPosts))
|
|
|
|
data = imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Hello"),
|
|
CreateAt: model.NewPointer(importCreate),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Reply"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
ThreadFollowers: &[]imports.ThreadFollowerImportData{{
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
LastViewed: model.NewPointer(model.GetMillis()),
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err = th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
followers, nErr := th.App.Srv().Store().Thread().GetThreadFollowers(resultPosts[0].Id, true)
|
|
require.NoError(t, nErr)
|
|
|
|
assert.ElementsMatch(t, []string{th.BasicUser.Id}, followers)
|
|
})
|
|
|
|
// ------------------ Group Channel -------------------------
|
|
|
|
// Create the GROUP channel.
|
|
user3 := th.CreateUser()
|
|
channelData = imports.DirectChannelImportData{
|
|
Participants: []*imports.DirectChannelMemberImportData{
|
|
{
|
|
Username: model.NewPointer(th.BasicUser.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(th.BasicUser2.Username),
|
|
},
|
|
{
|
|
Username: model.NewPointer(user3.Username),
|
|
},
|
|
},
|
|
}
|
|
appErr = th.App.importDirectChannel(th.Context, &channelData, false)
|
|
require.Nil(t, appErr)
|
|
|
|
// Get the channel.
|
|
var groupChannel *model.Channel
|
|
userIDs := []string{
|
|
th.BasicUser.Id,
|
|
th.BasicUser2.Id,
|
|
user3.Id,
|
|
}
|
|
channel, appErr = th.App.createGroupChannel(th.Context, userIDs, th.BasicUser.Id)
|
|
require.Equal(t, appErr.Id, store.ChannelExistsError)
|
|
groupChannel = channel
|
|
|
|
// Get the number of posts in the system.
|
|
require.NoError(t, th.App.Srv().Store().Post().RefreshPostStats())
|
|
result, nErr := th.App.Srv().Store().Post().AnalyticsPostCount(&model.PostCountOptions{})
|
|
require.NoError(t, nErr)
|
|
initialPostCount = result
|
|
|
|
t.Run("Try adding an invalid post in dry run mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 4,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
require.NotNil(t, err)
|
|
require.Equal(t, data.LineNumber, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
|
|
})
|
|
|
|
t.Run("Try adding a valid post in dry run mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, true, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
|
|
})
|
|
|
|
t.Run("Try adding an invalid post in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
model.NewId(),
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 8,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.NotNil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 0, "")
|
|
})
|
|
|
|
t.Run("Try adding a valid post in apply mode", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(initialDate + 10),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(groupChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
require.Equal(t, post.Message, *data.DirectPost.Message)
|
|
require.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
require.Equal(t, post.UserId, th.BasicUser.Id)
|
|
})
|
|
|
|
t.Run("Import the post again", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(initialDate + 10),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 1, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(groupChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
require.Equal(t, post.Message, *data.DirectPost.Message)
|
|
require.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
require.Equal(t, post.UserId, th.BasicUser.Id)
|
|
})
|
|
|
|
t.Run("Save the post with a different time", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(initialDate + 11),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 2, "")
|
|
})
|
|
|
|
t.Run("Save the post with a different message", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message 2"),
|
|
CreateAt: model.NewPointer(initialDate + 11),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 3, "")
|
|
})
|
|
|
|
t.Run("Test with hashtag", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message 2 #hashtagmashupcity"),
|
|
CreateAt: model.NewPointer(initialDate + 12),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 4, "")
|
|
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(groupChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
require.Equal(t, post.Message, *data.DirectPost.Message)
|
|
require.Equal(t, post.CreateAt, *data.DirectPost.CreateAt)
|
|
require.Equal(t, post.UserId, th.BasicUser.Id)
|
|
require.Equal(t, post.Hashtags, "#hashtagmashupcity")
|
|
})
|
|
|
|
t.Run("Test with some flags", func(t *testing.T) {
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
FlaggedBy: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 5, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(groupChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
require.Len(t, posts, 1)
|
|
|
|
post := posts[0]
|
|
checkPreference(t, th.App, th.BasicUser.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
checkPreference(t, th.App, th.BasicUser2.Id, model.PreferenceCategoryFlaggedPost, post.Id, "true")
|
|
})
|
|
|
|
t.Run("Post with reaction", func(t *testing.T) {
|
|
reactionPostTime := model.NewPointer(initialDate + 22)
|
|
reactionTime := model.NewPointer(initialDate + 23)
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message with reaction"),
|
|
CreateAt: reactionPostTime,
|
|
Reactions: &[]imports.ReactionImportData{{
|
|
User: model.NewPointer(th.BasicUser2.Username),
|
|
EmojiName: model.NewPointer("+1"),
|
|
CreateAt: reactionTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 6, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(groupChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.DirectPost.Message || post.CreateAt != *data.DirectPost.CreateAt || post.UserId != th.BasicUser.Id || !post.HasReactions
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
reactions, nErr := th.App.Srv().Store().Reaction().GetForPost(post.Id, false)
|
|
require.NoError(t, nErr, "Can't get reaction")
|
|
|
|
require.Len(t, reactions, 1, "Invalid number of reactions")
|
|
})
|
|
|
|
t.Run("Post with reply", func(t *testing.T) {
|
|
replyPostTime := model.NewPointer(initialDate + 25)
|
|
replyTime := model.NewPointer(initialDate + 26)
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: model.NewPointer(th.BasicUser2.Username),
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 8, "")
|
|
|
|
// Check the post values.
|
|
posts, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(groupChannel.Id, *data.DirectPost.CreateAt)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, posts, 1, "Unexpected number of posts found.")
|
|
|
|
post := posts[0]
|
|
postBool := post.Message != *data.DirectPost.Message || post.CreateAt != *data.DirectPost.CreateAt || post.UserId != th.BasicUser.Id
|
|
require.False(t, postBool, "Post properties not as expected")
|
|
|
|
// Check the reply values.
|
|
replies, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, *replyTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, replies, 1, "Unexpected number of posts found.")
|
|
|
|
reply := replies[0]
|
|
replyBool := reply.Message != *(*data.DirectPost.Replies)[0].Message || reply.CreateAt != *(*data.DirectPost.Replies)[0].CreateAt || reply.UserId != th.BasicUser2.Id
|
|
require.False(t, replyBool, "Post properties not as expected")
|
|
|
|
require.Equal(t, post.Id, reply.RootId, "Unexpected reply RootId")
|
|
})
|
|
|
|
t.Run("Update post with replies", func(t *testing.T) {
|
|
replyPostTime := model.NewPointer(initialDate + 25)
|
|
replyTime := model.NewPointer(initialDate + 26)
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser2.Username),
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 8, "")
|
|
})
|
|
|
|
t.Run("Create new post with replies based on the previous one", func(t *testing.T) {
|
|
replyPostTime := model.NewPointer(initialDate + 27)
|
|
replyTime := model.NewPointer(initialDate + 28)
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser2.Username),
|
|
Message: model.NewPointer("Message with reply 2"),
|
|
CreateAt: replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: replyTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 10, "")
|
|
})
|
|
|
|
t.Run("Post with reply having non-empty type and edit_at", func(t *testing.T) {
|
|
replyPostTime := model.NewPointer(initialDate + 29)
|
|
replyTime := model.NewPointer(initialDate + 30)
|
|
replyEditTime := model.NewPointer(initialDate + 31)
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
th.BasicUser.Username,
|
|
th.BasicUser2.Username,
|
|
user3.Username,
|
|
},
|
|
User: model.NewPointer(th.BasicUser2.Username),
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: replyPostTime,
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: model.NewPointer(th.BasicUser.Username),
|
|
Type: model.NewPointer(model.PostTypeSystemGeneric),
|
|
Message: model.NewPointer("Message reply 2"),
|
|
CreateAt: replyTime,
|
|
EditAt: replyEditTime,
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 1,
|
|
}
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
AssertAllPostsCount(t, th.App, initialPostCount, 12, "")
|
|
|
|
// Check the reply values.
|
|
replies, nErr := th.App.Srv().Store().Post().GetPostsCreatedAt(channel.Id, *replyTime)
|
|
require.NoError(t, nErr)
|
|
|
|
require.Len(t, replies, 1, "Unexpected number of posts found.")
|
|
|
|
reply := replies[0]
|
|
importReply := (*data.DirectPost.Replies)[0]
|
|
replyBool := reply.Type != *importReply.Type || reply.Message != *importReply.Message || reply.CreateAt != *importReply.CreateAt || reply.EditAt != *importReply.EditAt || reply.UserId != th.BasicUser.Id
|
|
require.False(t, replyBool, "Post properties not as expected")
|
|
})
|
|
}
|
|
|
|
func TestImportImportEmoji(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true })
|
|
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
testImage := filepath.Join(testsDir, "test.png")
|
|
|
|
data := imports.EmojiImportData{Name: model.NewPointer(model.NewId())}
|
|
appErr := th.App.importEmoji(th.Context, &data, true)
|
|
assert.NotNil(t, appErr, "Invalid emoji should have failed dry run")
|
|
|
|
emoji, nErr := th.App.Srv().Store().Emoji().GetByName(th.Context, *data.Name, true)
|
|
assert.Nil(t, emoji, "Emoji should not have been imported")
|
|
assert.Error(t, nErr)
|
|
|
|
data.Image = model.NewPointer(testImage)
|
|
appErr = th.App.importEmoji(th.Context, &data, true)
|
|
assert.Nil(t, appErr, "Valid emoji should have passed dry run")
|
|
|
|
data = imports.EmojiImportData{Name: model.NewPointer(model.NewId())}
|
|
appErr = th.App.importEmoji(th.Context, &data, false)
|
|
assert.NotNil(t, appErr, "Invalid emoji should have failed apply mode")
|
|
|
|
data.Image = model.NewPointer("non-existent-file")
|
|
appErr = th.App.importEmoji(th.Context, &data, false)
|
|
assert.NotNil(t, appErr, "Emoji with bad image file should have failed apply mode")
|
|
|
|
data.Image = model.NewPointer(testImage)
|
|
appErr = th.App.importEmoji(th.Context, &data, false)
|
|
assert.Nil(t, appErr, "Valid emoji should have succeeded apply mode")
|
|
|
|
emoji, nErr = th.App.Srv().Store().Emoji().GetByName(th.Context, *data.Name, true)
|
|
assert.NotNil(t, emoji, "Emoji should have been imported")
|
|
assert.NoError(t, nErr, "Emoji should have been imported without any error")
|
|
|
|
appErr = th.App.importEmoji(th.Context, &data, false)
|
|
assert.Nil(t, appErr, "Second run should have succeeded apply mode")
|
|
|
|
data = imports.EmojiImportData{Name: model.NewPointer("smiley"), Image: model.NewPointer(testImage)}
|
|
appErr = th.App.importEmoji(th.Context, &data, false)
|
|
assert.Nil(t, appErr, "System emoji should not fail")
|
|
|
|
largeImage := filepath.Join(testsDir, "large_image_file.jpg")
|
|
data = imports.EmojiImportData{Name: model.NewPointer(model.NewId()), Image: model.NewPointer(largeImage)}
|
|
appErr = th.App.importEmoji(th.Context, &data, false)
|
|
require.NotNil(t, appErr)
|
|
require.ErrorIs(t, appErr.Unwrap(), utils.ErrSizeLimitExceeded)
|
|
}
|
|
|
|
func TestImportAttachment(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
testImage := filepath.Join(testsDir, "test.png")
|
|
invalidPath := "some-invalid-path"
|
|
|
|
userID := model.NewId()
|
|
data := imports.AttachmentImportData{Path: &testImage}
|
|
_, err := th.App.importAttachment(th.Context, &data, &model.Post{UserId: userID, ChannelId: "some-channel"}, "some-team", true)
|
|
assert.Nil(t, err, "sample run without errors")
|
|
|
|
attachments := GetAttachments(userID, th, t)
|
|
assert.Len(t, attachments, 1)
|
|
|
|
data = imports.AttachmentImportData{Path: &invalidPath}
|
|
_, err = th.App.importAttachment(th.Context, &data, &model.Post{UserId: model.NewId(), ChannelId: "some-channel"}, "some-team", true)
|
|
assert.NotNil(t, err, "should have failed when opening the file")
|
|
assert.Equal(t, err.Id, "app.import.attachment.bad_file.error")
|
|
}
|
|
|
|
func TestImportPostAndRepliesWithAttachments(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Create a Team.
|
|
teamName := model.NewRandomTeamName()
|
|
appErr := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import team.")
|
|
team, appErr := th.App.GetTeamByName(teamName)
|
|
require.Nil(t, appErr, "Failed to get team from database.")
|
|
|
|
// Create a Channel.
|
|
channelName := NewTestId()
|
|
chanTypeOpen := model.ChannelTypeOpen
|
|
appErr = th.App.importChannel(th.Context, &imports.ChannelImportData{
|
|
Team: &teamName,
|
|
Name: &channelName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import channel.")
|
|
_, appErr = th.App.GetChannelByName(th.Context, channelName, team.Id, false)
|
|
require.Nil(t, appErr, "Failed to get channel from database.")
|
|
|
|
// Create a user3.
|
|
username := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user.")
|
|
user3, appErr := th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr, "Failed to get user3 from database.")
|
|
require.NotNil(t, user3)
|
|
|
|
username2 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username2,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user2.")
|
|
user2, appErr := th.App.GetUserByUsername(username2)
|
|
require.Nil(t, appErr, "Failed to get user2 from database.")
|
|
|
|
// Create direct post users.
|
|
username3 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username3,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user3.")
|
|
user3, appErr = th.App.GetUserByUsername(username3)
|
|
require.Nil(t, appErr, "Failed to get user3 from database.")
|
|
|
|
username4 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username4,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user4.")
|
|
|
|
user4, appErr := th.App.GetUserByUsername(username4)
|
|
require.Nil(t, appErr, "Failed to get user4 from database.")
|
|
|
|
// Post with attachments
|
|
time := model.GetMillis()
|
|
attachmentsPostTime := time
|
|
attachmentsReplyTime := time + 1
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
testImage := filepath.Join(testsDir, "test.png")
|
|
testMarkDown := filepath.Join(testsDir, "test-attachments.md")
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username3,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &attachmentsPostTime,
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage}, {Path: &testMarkDown}},
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user4.Username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &attachmentsReplyTime,
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage}},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 19,
|
|
}
|
|
|
|
t.Run("import with attachment", func(t *testing.T) {
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 2)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
assert.Contains(t, attachments[1].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
|
|
attachments = GetAttachments(user4.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
})
|
|
|
|
t.Run("import existing post with new attachment", func(t *testing.T) {
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &testImage}}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
|
|
attachments = GetAttachments(user4.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
})
|
|
|
|
t.Run("Reply with Attachments in Direct Post", func(t *testing.T) {
|
|
directImportData := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
user3.Username,
|
|
user2.Username,
|
|
},
|
|
User: &user3.Username,
|
|
Message: model.NewPointer("Message with Replies"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message reply with attachment"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage}},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 7,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{directImportData}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user2.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, "noteam")
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
})
|
|
|
|
t.Run("import existing post with different attachment's content", func(t *testing.T) {
|
|
tmpDir := os.TempDir()
|
|
filePath := filepath.Join(tmpDir, "test_diff.png")
|
|
|
|
t.Run("different size", func(t *testing.T) {
|
|
testImage := filepath.Join(testsDir, "test.png")
|
|
imageData, err := os.ReadFile(testImage)
|
|
require.NoError(t, err)
|
|
err = os.WriteFile(filePath, imageData, 0644)
|
|
require.NoError(t, err)
|
|
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &filePath}}
|
|
data.Post.Replies = nil
|
|
data.Post.Message = model.NewPointer("new post")
|
|
errLine, appErr := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, appErr)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 2)
|
|
assert.Contains(t, attachments[1].Path, team.Id)
|
|
AssertFileIdsInPost(attachments[1:], th, t)
|
|
|
|
testImage = filepath.Join(testsDir, "test-data-graph.png")
|
|
imageData, err = os.ReadFile(testImage)
|
|
require.NoError(t, err)
|
|
err = os.WriteFile(filePath, imageData, 0644)
|
|
require.NoError(t, err)
|
|
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &filePath}}
|
|
data.Post.Replies = nil
|
|
errLine, appErr = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, appErr)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments2 := GetAttachments(user3.Id, th, t)
|
|
require.NotEqual(t, attachments, attachments2)
|
|
require.Len(t, attachments2, 2)
|
|
assert.Contains(t, attachments2[1].Path, team.Id)
|
|
AssertFileIdsInPost(attachments2[1:], th, t)
|
|
})
|
|
|
|
t.Run("same size", func(t *testing.T) {
|
|
imageData, err := os.ReadFile(filepath.Join(testsDir, "test_img_diff_A.png"))
|
|
require.NoError(t, err)
|
|
err = os.WriteFile(filePath, imageData, 0644)
|
|
require.NoError(t, err)
|
|
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &filePath}}
|
|
data.Post.Replies = nil
|
|
data.Post.Message = model.NewPointer("new post2")
|
|
errLine, appErr := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, appErr)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 3)
|
|
assert.Contains(t, attachments[2].Path, team.Id)
|
|
AssertFileIdsInPost(attachments[2:], th, t)
|
|
|
|
imageData, err = os.ReadFile(filepath.Join(testsDir, "test_img_diff_B.png"))
|
|
require.NoError(t, err)
|
|
err = os.WriteFile(filePath, imageData, 0644)
|
|
require.NoError(t, err)
|
|
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &filePath}}
|
|
data.Post.Replies = nil
|
|
errLine, appErr = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, appErr)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments2 := GetAttachments(user3.Id, th, t)
|
|
require.NotEqual(t, attachments, attachments2)
|
|
require.Len(t, attachments2, 3)
|
|
assert.Contains(t, attachments2[2].Path, team.Id)
|
|
AssertFileIdsInPost(attachments2[2:], th, t)
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestImportDirectPostWithAttachments(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
testImage := filepath.Join(testsDir, "test.png")
|
|
testImage2 := filepath.Join(testsDir, "test.svg")
|
|
// create a temp file with same name as original but with a different first byte
|
|
tmpFolder, err := os.MkdirTemp("", "imgFake")
|
|
require.NoError(t, err)
|
|
testImageFake := filepath.Join(tmpFolder, "test.png")
|
|
fakeFileData, err := os.ReadFile(testImage)
|
|
require.NoError(t, err)
|
|
fakeFileData[0] = 0
|
|
err = os.WriteFile(testImageFake, fakeFileData, 0644)
|
|
require.NoError(t, err)
|
|
defer func() {
|
|
err := os.RemoveAll(tmpFolder)
|
|
require.NoError(t, err)
|
|
}()
|
|
|
|
// Create a user.
|
|
username := model.NewUsername()
|
|
appErr := th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user.")
|
|
user1, appErr := th.App.GetUserByUsername(username)
|
|
require.Nil(t, appErr, "Failed to get user1 from database.")
|
|
|
|
username2 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username2,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user2.")
|
|
user2, appErr := th.App.GetUserByUsername(username2)
|
|
require.Nil(t, appErr, "Failed to get user2 from database.")
|
|
|
|
directImportData := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
user1.Username,
|
|
user2.Username,
|
|
},
|
|
User: &user1.Username,
|
|
Message: model.NewPointer("Direct message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage}},
|
|
},
|
|
},
|
|
LineNumber: 3,
|
|
}
|
|
|
|
t.Run("Regular import of attachment", func(t *testing.T) {
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{directImportData}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user1.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, "noteam")
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
})
|
|
|
|
t.Run("Attempt to import again with same file entirely, should NOT add an attachment", func(t *testing.T) {
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{directImportData}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user1.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
})
|
|
|
|
t.Run("Attempt to import again with same name and size but different content, SHOULD add an attachment", func(t *testing.T) {
|
|
directImportDataFake := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
user1.Username,
|
|
user2.Username,
|
|
},
|
|
User: &user1.Username,
|
|
Message: model.NewPointer("Direct message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImageFake}},
|
|
},
|
|
},
|
|
LineNumber: 2,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{directImportDataFake}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user1.Id, th, t)
|
|
require.Len(t, attachments, 2)
|
|
})
|
|
|
|
t.Run("Attempt to import again with same data, SHOULD add an attachment, since it's different name", func(t *testing.T) {
|
|
directImportData2 := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
user1.Username,
|
|
user2.Username,
|
|
},
|
|
User: &user1.Username,
|
|
Message: model.NewPointer("Direct message"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage2}},
|
|
},
|
|
},
|
|
LineNumber: 2,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{directImportData2}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user1.Id, th, t)
|
|
require.Len(t, attachments, 3)
|
|
})
|
|
}
|
|
|
|
func TestZippedImportPostAndRepliesWithAttachments(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
th := Setup(t)
|
|
defer th.TearDown()
|
|
|
|
// Create a Team.
|
|
teamName := model.NewRandomTeamName()
|
|
appErr := th.App.importTeam(th.Context, &imports.TeamImportData{
|
|
Name: &teamName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: model.NewPointer("O"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import team.")
|
|
team, appErr := th.App.GetTeamByName(teamName)
|
|
require.Nil(t, appErr, "Failed to get team from database.")
|
|
|
|
// Create a Channel.
|
|
channelName := NewTestId()
|
|
chanTypeOpen := model.ChannelTypeOpen
|
|
appErr = th.App.importChannel(th.Context, &imports.ChannelImportData{
|
|
Team: &teamName,
|
|
Name: &channelName,
|
|
DisplayName: model.NewPointer("Display Name"),
|
|
Type: &chanTypeOpen,
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import channel.")
|
|
_, appErr = th.App.GetChannelByName(th.Context, channelName, team.Id, false)
|
|
require.Nil(t, appErr, "Failed to get channel from database.")
|
|
|
|
// Create users
|
|
username2 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username2,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user2.")
|
|
user2, appErr := th.App.GetUserByUsername(username2)
|
|
require.Nil(t, appErr, "Failed to get user2 from database.")
|
|
|
|
// Create direct post users.
|
|
username3 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username3,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user3.")
|
|
user3, appErr := th.App.GetUserByUsername(username3)
|
|
require.Nil(t, appErr, "Failed to get user3 from database.")
|
|
|
|
username4 := model.NewUsername()
|
|
appErr = th.App.importUser(th.Context, &imports.UserImportData{
|
|
Username: &username4,
|
|
Email: model.NewPointer(model.NewId() + "@example.com"),
|
|
}, false)
|
|
require.Nil(t, appErr, "Failed to import user4.")
|
|
|
|
user4, appErr := th.App.GetUserByUsername(username4)
|
|
require.Nil(t, appErr, "Failed to get user4 from database.")
|
|
|
|
// Post with attachments
|
|
time := model.GetMillis()
|
|
attachmentsPostTime := time
|
|
attachmentsReplyTime := time + 1
|
|
testsDir, _ := fileutils.FindDir("tests")
|
|
testImage := filepath.Join(testsDir, "test.png")
|
|
testZipFileName := filepath.Join(testsDir, "import_test.zip")
|
|
testZip, err := os.Open(testZipFileName)
|
|
require.NoError(t, err, "failed to open test zip")
|
|
|
|
fi, err := testZip.Stat()
|
|
require.NoError(t, err, "failed to get file info")
|
|
testZipReader, err := zip.NewReader(testZip, fi.Size())
|
|
require.NoError(t, err, "failed to read test zip")
|
|
|
|
require.NotEmpty(t, testZipReader.File)
|
|
imageData := testZipReader.File[0]
|
|
|
|
testMarkDown := filepath.Join(testsDir, "test-attachments.md")
|
|
data := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
Post: &imports.PostImportData{
|
|
Team: &teamName,
|
|
Channel: &channelName,
|
|
User: &username3,
|
|
Message: model.NewPointer("Message with reply"),
|
|
CreateAt: &attachmentsPostTime,
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage}, {Path: &testMarkDown}},
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user4.Username,
|
|
Message: model.NewPointer("Message reply"),
|
|
CreateAt: &attachmentsReplyTime,
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage, Data: imageData}},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 19,
|
|
}
|
|
|
|
t.Run("import with attachment", func(t *testing.T) {
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 2)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
assert.Contains(t, attachments[1].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
|
|
attachments = GetAttachments(user4.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
})
|
|
|
|
t.Run("import existing post with new attachment", func(t *testing.T) {
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &testImage}}
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
|
|
attachments = GetAttachments(user4.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, team.Id)
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
})
|
|
|
|
t.Run("Reply with Attachments in Direct Post", func(t *testing.T) {
|
|
directImportData := imports.LineImportWorkerData{
|
|
LineImportData: imports.LineImportData{
|
|
DirectPost: &imports.DirectPostImportData{
|
|
ChannelMembers: &[]string{
|
|
user3.Username,
|
|
user2.Username,
|
|
},
|
|
User: &user3.Username,
|
|
Message: model.NewPointer("Message with Replies"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
Replies: &[]imports.ReplyImportData{{
|
|
User: &user2.Username,
|
|
Message: model.NewPointer("Message reply with attachment"),
|
|
CreateAt: model.NewPointer(model.GetMillis()),
|
|
Attachments: &[]imports.AttachmentImportData{{Path: &testImage}},
|
|
}},
|
|
},
|
|
},
|
|
LineNumber: 7,
|
|
}
|
|
|
|
errLine, err := th.App.importMultipleDirectPostLines(th.Context, []imports.LineImportWorkerData{directImportData}, false, true)
|
|
require.Nil(t, err, "Expected success.")
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user2.Id, th, t)
|
|
require.Len(t, attachments, 1)
|
|
assert.Contains(t, attachments[0].Path, "noteam")
|
|
AssertFileIdsInPost(attachments, th, t)
|
|
})
|
|
|
|
t.Run("import existing post with different attachment's content", func(t *testing.T) {
|
|
var fileA, fileB *zip.File
|
|
for _, f := range testZipReader.File {
|
|
if f.Name == "data/test_img_diff_A.png" {
|
|
fileA = f
|
|
} else if f.Name == "data/test_img_diff_B.png" {
|
|
fileB = f
|
|
}
|
|
}
|
|
|
|
require.NotNil(t, fileA)
|
|
require.NotNil(t, fileB)
|
|
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &fileA.Name, Data: fileA}}
|
|
data.Post.Message = model.NewPointer("new post")
|
|
data.Post.Replies = nil
|
|
errLine, err := th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments := GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 2)
|
|
assert.Contains(t, attachments[1].Path, team.Id)
|
|
AssertFileIdsInPost(attachments[1:], th, t)
|
|
|
|
fileB.Name = fileA.Name
|
|
data.Post.Attachments = &[]imports.AttachmentImportData{{Path: &fileA.Name, Data: fileB}}
|
|
errLine, err = th.App.importMultiplePostLines(th.Context, []imports.LineImportWorkerData{data}, false, true)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 0, errLine)
|
|
|
|
attachments = GetAttachments(user3.Id, th, t)
|
|
require.Len(t, attachments, 2)
|
|
assert.Contains(t, attachments[1].Path, team.Id)
|
|
AssertFileIdsInPost(attachments[1:], th, t)
|
|
})
|
|
}
|
|
|
|
func TestCompareFilesContent(t *testing.T) {
|
|
mainHelper.Parallel(t)
|
|
t.Run("empty", func(t *testing.T) {
|
|
ok, err := compareFilesContent(strings.NewReader(""), strings.NewReader(""), 0)
|
|
require.NoError(t, err)
|
|
require.True(t, ok)
|
|
})
|
|
|
|
t.Run("no match", func(t *testing.T) {
|
|
ok, err := compareFilesContent(strings.NewReader("fileA"), strings.NewReader("fileB"), 0)
|
|
require.NoError(t, err)
|
|
require.False(t, ok)
|
|
})
|
|
|
|
t.Run("match", func(t *testing.T) {
|
|
ok, err := compareFilesContent(strings.NewReader("fileA"), strings.NewReader("fileA"), 0)
|
|
require.NoError(t, err)
|
|
require.True(t, ok)
|
|
})
|
|
}
|
|
|
|
func BenchmarkCompareFilesContent(b *testing.B) {
|
|
tmpDir := os.TempDir()
|
|
fileAPath := filepath.Join(tmpDir, "fileA")
|
|
fileBPath := filepath.Join(tmpDir, "fileB")
|
|
|
|
fileA, err := os.Create(fileAPath)
|
|
require.NoError(b, err)
|
|
defer func() {
|
|
err = fileA.Close()
|
|
require.NoError(b, err)
|
|
|
|
err = os.Remove(fileAPath)
|
|
require.NoError(b, err)
|
|
}()
|
|
|
|
fileB, err := os.Create(fileBPath)
|
|
require.NoError(b, err)
|
|
defer func() {
|
|
err = fileB.Close()
|
|
require.NoError(b, err)
|
|
|
|
err = os.Remove(fileBPath)
|
|
require.NoError(b, err)
|
|
}()
|
|
|
|
fileSize := int64(1024 * 1024 * 1024) // 1GB
|
|
|
|
err = fileA.Truncate(fileSize)
|
|
require.NoError(b, err)
|
|
err = fileB.Truncate(fileSize)
|
|
require.NoError(b, err)
|
|
|
|
bufSizesMap := map[string]int64{
|
|
"32KB": 1024 * 32, // current default of io.Copy
|
|
"128KB": 1024 * 128,
|
|
"1MB": 1024 * 1024,
|
|
"2MB": 1024 * 1024 * 2,
|
|
"4MB": 1024 * 1024 * 4,
|
|
"8MB": 1024 * 1024 * 8,
|
|
}
|
|
|
|
fileSizesMap := map[string]int64{
|
|
"512KB": 1024 * 512,
|
|
"1MB": 1024 * 1024,
|
|
"10MB": 1024 * 1024 * 10,
|
|
"100MB": 1024 * 1024 * 100,
|
|
"1GB": 1024 * 1024 * 1000,
|
|
}
|
|
|
|
// To force order
|
|
bufSizeLabels := []string{"32KB", "128KB", "1MB", "2MB", "4MB", "8MB"}
|
|
fileSizeLabels := []string{"512KB", "1MB", "10MB", "100MB", "1GB"}
|
|
|
|
b.Run("plain", func(b *testing.B) {
|
|
b.Run("local", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
for b.Loop() {
|
|
b.StopTimer()
|
|
_, err := fileA.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
_, err = fileB.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
|
|
b.StartTimer()
|
|
ok, err := compareFilesContent(fileA, fileB, 0)
|
|
require.NoError(b, err)
|
|
require.True(b, ok)
|
|
}
|
|
})
|
|
|
|
b.Run("s3", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
th := SetupConfig(b, func(cfg *model.Config) {
|
|
cfg.FileSettings = model.FileSettings{
|
|
DriverName: model.NewPointer(model.ImageDriverS3),
|
|
AmazonS3AccessKeyId: model.NewPointer(model.MinioAccessKey),
|
|
AmazonS3SecretAccessKey: model.NewPointer(model.MinioSecretKey),
|
|
AmazonS3Bucket: model.NewPointer("comparefilescontentbucket"),
|
|
AmazonS3Endpoint: model.NewPointer("localhost:9000"),
|
|
AmazonS3Region: model.NewPointer(""),
|
|
AmazonS3PathPrefix: model.NewPointer(""),
|
|
AmazonS3SSL: model.NewPointer(false),
|
|
AmazonS3RequestTimeoutMilliseconds: model.NewPointer(int64(300 * 1000)),
|
|
}
|
|
})
|
|
defer th.TearDown()
|
|
|
|
err := th.App.Srv().FileBackend().(*filestore.S3FileBackend).TestConnection()
|
|
require.NoError(b, err)
|
|
|
|
_, err = fileA.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
_, err = fileB.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
|
|
_, appErr := th.App.WriteFile(fileA, "compareFileA")
|
|
require.Nil(b, appErr)
|
|
defer func() {
|
|
err = th.App.RemoveFile("compareFileA")
|
|
require.NoError(b, err)
|
|
}()
|
|
|
|
_, appErr = th.App.WriteFile(fileB, "compareFileB")
|
|
require.Nil(b, appErr)
|
|
defer func() {
|
|
appErr = th.App.RemoveFile("compareFileB")
|
|
require.Nil(b, appErr)
|
|
}()
|
|
|
|
rdA, appErr := th.App.FileReader("compareFileA")
|
|
require.Nil(b, appErr)
|
|
defer func() {
|
|
err = rdA.Close()
|
|
require.NoError(b, err)
|
|
}()
|
|
|
|
rdB, appErr := th.App.FileReader("compareFileB")
|
|
require.Nil(b, appErr)
|
|
defer func() {
|
|
err = rdB.Close()
|
|
require.NoError(b, err)
|
|
}()
|
|
|
|
for _, fileSizeLabel := range fileSizeLabels {
|
|
fileSize := fileSizesMap[fileSizeLabel]
|
|
for _, bufSizeLabel := range bufSizeLabels {
|
|
bufSize := bufSizesMap[bufSizeLabel]
|
|
b.Run("bufSize-fileSize"+fileSizeLabel+"-bufSize"+bufSizeLabel, func(b *testing.B) {
|
|
for b.Loop() {
|
|
b.StopTimer()
|
|
_, err := rdA.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
_, err = rdB.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
|
|
b.StartTimer()
|
|
ok, err := compareFilesContent(&io.LimitedReader{
|
|
R: rdA,
|
|
N: fileSize,
|
|
}, &io.LimitedReader{
|
|
R: rdB,
|
|
N: fileSize,
|
|
}, bufSize)
|
|
require.NoError(b, err)
|
|
require.True(b, ok)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("zip", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
zipFilePath := filepath.Join(tmpDir, "compareFiles.zip")
|
|
zipFile, err := os.Create(zipFilePath)
|
|
require.NoError(b, err)
|
|
defer func() {
|
|
err = zipFile.Close()
|
|
require.NoError(b, err)
|
|
|
|
err = os.Remove(zipFilePath)
|
|
require.NoError(b, err)
|
|
}()
|
|
|
|
zipWr := zip.NewWriter(zipFile)
|
|
|
|
fileAZipWr, err := zipWr.CreateHeader(&zip.FileHeader{
|
|
Name: "compareFileA",
|
|
Method: zip.Store,
|
|
})
|
|
require.NoError(b, err)
|
|
_, err = io.Copy(fileAZipWr, fileA)
|
|
require.NoError(b, err)
|
|
|
|
fileBZipWr, err := zipWr.CreateHeader(&zip.FileHeader{
|
|
Name: "compareFileB",
|
|
Method: zip.Store,
|
|
})
|
|
require.NoError(b, err)
|
|
_, err = io.Copy(fileBZipWr, fileB)
|
|
require.NoError(b, err)
|
|
|
|
err = zipWr.Close()
|
|
require.NoError(b, err)
|
|
|
|
info, err := zipFile.Stat()
|
|
require.NoError(b, err)
|
|
|
|
zipFileSize := info.Size()
|
|
|
|
b.Run("local", func(b *testing.B) {
|
|
for _, label := range bufSizeLabels {
|
|
bufSize := bufSizesMap[label]
|
|
b.Run("bufSize-"+label, func(b *testing.B) {
|
|
for b.Loop() {
|
|
b.StopTimer()
|
|
_, err := zipFile.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
zipRd, err := zip.NewReader(zipFile, zipFileSize)
|
|
require.NoError(b, err)
|
|
|
|
zipFileA, err := zipRd.Open("compareFileA")
|
|
require.NoError(b, err)
|
|
|
|
zipFileB, err := zipRd.Open("compareFileB")
|
|
require.NoError(b, err)
|
|
|
|
b.StartTimer()
|
|
ok, err := compareFilesContent(zipFileA, zipFileB, bufSize)
|
|
require.NoError(b, err)
|
|
require.True(b, ok)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
b.Run("s3", func(b *testing.B) {
|
|
th := SetupConfig(b, func(cfg *model.Config) {
|
|
cfg.FileSettings = model.FileSettings{
|
|
DriverName: model.NewPointer(model.ImageDriverS3),
|
|
AmazonS3AccessKeyId: model.NewPointer(model.MinioAccessKey),
|
|
AmazonS3SecretAccessKey: model.NewPointer(model.MinioSecretKey),
|
|
AmazonS3Bucket: model.NewPointer("comparefilescontentbucket"),
|
|
AmazonS3Endpoint: model.NewPointer("localhost:9000"),
|
|
AmazonS3Region: model.NewPointer(""),
|
|
AmazonS3PathPrefix: model.NewPointer(""),
|
|
AmazonS3SSL: model.NewPointer(false),
|
|
AmazonS3RequestTimeoutMilliseconds: model.NewPointer(int64(300 * 1000)),
|
|
}
|
|
})
|
|
defer th.TearDown()
|
|
|
|
err := th.App.Srv().FileBackend().(*filestore.S3FileBackend).TestConnection()
|
|
require.NoError(b, err)
|
|
|
|
_, appErr := th.App.WriteFile(zipFile, "compareFiles.zip")
|
|
require.Nil(b, appErr)
|
|
defer func() {
|
|
appErr = th.App.RemoveFile("compareFiles.zip")
|
|
require.Nil(b, appErr)
|
|
}()
|
|
|
|
zipFileRd, appErr := th.App.FileReader("compareFiles.zip")
|
|
require.Nil(b, appErr)
|
|
defer func() {
|
|
err = zipFileRd.Close()
|
|
require.NoError(b, err)
|
|
}()
|
|
|
|
for _, fileSizeLabel := range fileSizeLabels {
|
|
fileSize := fileSizesMap[fileSizeLabel]
|
|
for _, bufSizeLabel := range bufSizeLabels {
|
|
bufSize := bufSizesMap[bufSizeLabel]
|
|
b.Run("bufSize-fileSize"+fileSizeLabel+"-bufSize"+bufSizeLabel, func(b *testing.B) {
|
|
for b.Loop() {
|
|
b.StopTimer()
|
|
_, err := zipFileRd.Seek(0, io.SeekStart)
|
|
require.NoError(b, err)
|
|
zipRd, err := zip.NewReader(zipFileRd.(io.ReaderAt), zipFileSize)
|
|
require.NoError(b, err)
|
|
|
|
zipFileA, err := zipRd.Open("compareFileA")
|
|
require.NoError(b, err)
|
|
|
|
zipFileB, err := zipRd.Open("compareFileB")
|
|
require.NoError(b, err)
|
|
|
|
b.StartTimer()
|
|
ok, err := compareFilesContent(&io.LimitedReader{
|
|
R: zipFileA,
|
|
N: fileSize,
|
|
}, &io.LimitedReader{
|
|
R: zipFileB,
|
|
N: fileSize,
|
|
}, bufSize)
|
|
require.NoError(b, err)
|
|
require.True(b, ok)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|