mattermost-community-enterp.../cmd/mmctl/commands/user_attributes_field_e2e_test.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
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>
2025-12-17 23:59:07 +09:00

585 lines
18 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package commands
import (
"github.com/mattermost/mattermost/server/public/model"
"github.com/spf13/cobra"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/client"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/printer"
)
// cleanCPAFields removes all existing CPA fields to ensure clean test state
func (s *MmctlE2ETestSuite) cleanCPAFields() {
existingFields, appErr := s.th.App.ListCPAFields()
s.Require().Nil(appErr)
for _, field := range existingFields {
appErr := s.th.App.DeleteCPAField(field.ID)
s.Require().Nil(appErr)
}
}
func (s *MmctlE2ETestSuite) TestCPAFieldListCmd() {
s.SetupEnterpriseTestHelper().InitBasic()
s.th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
s.RunForSystemAdminAndLocal("List CPA fields with no entries", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
err := cpaFieldListCmdF(c, &cobra.Command{}, []string{})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 0) // No fields should be present initially
s.Require().Len(printer.GetErrorLines(), 0)
})
s.RunForSystemAdminAndLocal("List CPA fields with entries", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// Create a couple of test CPA fields
textField := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Department",
Type: model.PropertyFieldTypeText,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "admin",
},
}
selectField := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Level",
Type: model.PropertyFieldTypeSelect,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
Options: []*model.CustomProfileAttributesSelectOption{
{ID: model.NewId(), Name: "Junior"},
{ID: model.NewId(), Name: "Senior"},
},
},
}
createdTextField, appErr := s.th.App.CreateCPAField(textField)
s.Require().Nil(appErr)
s.Require().NotNil(createdTextField)
createdSelectField, appErr := s.th.App.CreateCPAField(selectField)
s.Require().Nil(appErr)
s.Require().NotNil(createdSelectField)
// Now test the list command
err := cpaFieldListCmdF(c, &cobra.Command{}, []string{})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 2) // Should have 2 fields now
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the output contains our created fields
lines := printer.GetLines()
s.Require().Len(lines, 2, "Should have exactly 2 output lines for 2 fields")
})
}
func (s *MmctlE2ETestSuite) TestCPAFieldCreateCmd() {
s.SetupEnterpriseTestHelper().InitBasic()
s.th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
s.RunForSystemAdminAndLocal("Create managed text field", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// Create command with arguments and managed flag
cmd := &cobra.Command{}
cmd.Flags().Bool("managed", false, "")
cmd.Flags().String("attrs", "", "")
cmd.Flags().StringSlice("option", []string{}, "")
// Set the managed flag to true
err := cmd.Flags().Set("managed", "true")
s.Require().Nil(err)
err = cpaFieldCreateCmdF(c, cmd, []string{"Department", "text"})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the success message
output := printer.GetLines()[0].(string)
s.Require().Contains(output, "Field Department correctly created")
// Verify field was actually created in the database
fields, appErr := s.th.App.ListCPAFields()
s.Require().Nil(appErr)
s.Require().Len(fields, 1)
s.Require().Equal("Department", fields[0].Name)
s.Require().Equal(model.PropertyFieldTypeText, fields[0].Type)
s.Require().Equal("admin", fields[0].Attrs["managed"])
})
s.RunForSystemAdminAndLocal("Create multiselect field with options", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// Create command with arguments and option flags
cmd := &cobra.Command{}
cmd.Flags().Bool("managed", false, "")
cmd.Flags().String("attrs", "", "")
cmd.Flags().StringSlice("option", []string{}, "")
// Set the option flags
err := cmd.Flags().Set("option", "Go")
s.Require().Nil(err)
err = cmd.Flags().Set("option", "React")
s.Require().Nil(err)
err = cmd.Flags().Set("option", "Python")
s.Require().Nil(err)
err = cpaFieldCreateCmdF(c, cmd, []string{"Skills", "multiselect"})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the success message
output := printer.GetLines()[0].(string)
s.Require().Contains(output, "Field Skills correctly created")
// Verify field was actually created in the database with correct options
fields, appErr := s.th.App.ListCPAFields()
s.Require().Nil(appErr)
s.Require().Len(fields, 1)
s.Require().Equal("Skills", fields[0].Name)
s.Require().Equal(model.PropertyFieldTypeMultiselect, fields[0].Type)
// Convert to CPAField for easier option inspection
cpaField, err := model.NewCPAFieldFromPropertyField(fields[0])
s.Require().Nil(err)
// Verify the options were created
s.Require().Len(cpaField.Attrs.Options, 3)
// Extract option names to verify they match what we set
var optionNames []string
for _, option := range cpaField.Attrs.Options {
optionNames = append(optionNames, option.Name)
}
s.Require().Contains(optionNames, "Go")
s.Require().Contains(optionNames, "React")
s.Require().Contains(optionNames, "Python")
})
}
func (s *MmctlE2ETestSuite) TestCPAFieldEditCmd() {
s.SetupEnterpriseTestHelper().InitBasic()
s.th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
s.RunForSystemAdminAndLocal("Edit nonexistent field should fail", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
cmd := &cobra.Command{}
cmd.Flags().String("name", "", "")
cmd.Flags().Bool("managed", false, "")
cmd.Flags().String("attrs", "", "")
cmd.Flags().StringSlice("option", []string{}, "")
err := cmd.Flags().Set("name", "New Name")
s.Require().Nil(err)
err = cpaFieldEditCmdF(c, cmd, []string{"nonexistent-field-id"})
s.Require().NotNil(err)
s.Require().Contains(err.Error(), "failed to get field for \"nonexistent-field-id\"")
})
s.RunForSystemAdminAndLocal("Edit field using --name and --option flags", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// First create a field to edit
field := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Skills",
Type: model.PropertyFieldTypeSelect,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Options: []*model.CustomProfileAttributesSelectOption{
{ID: model.NewId(), Name: "Go"},
},
},
}
createdField, appErr := s.th.App.CreateCPAField(field)
s.Require().Nil(appErr)
// Now edit the field
cmd := &cobra.Command{}
cmd.Flags().String("name", "", "")
cmd.Flags().Bool("managed", false, "")
cmd.Flags().String("attrs", "", "")
cmd.Flags().StringSlice("option", []string{}, "")
err := cmd.Flags().Set("name", "Programming Languages")
s.Require().Nil(err)
err = cmd.Flags().Set("option", "Go")
s.Require().Nil(err)
err = cmd.Flags().Set("option", "Python")
s.Require().Nil(err)
err = cpaFieldEditCmdF(c, cmd, []string{createdField.ID})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the success message
output := printer.GetLines()[0].(string)
s.Require().Contains(output, "Field Programming Languages successfully updated")
// Verify field was actually updated
updatedField, appErr := s.th.App.GetCPAField(createdField.ID)
s.Require().Nil(appErr)
s.Require().Equal("Programming Languages", updatedField.Name)
// Convert to CPAField to check options
cpaField, err := model.NewCPAFieldFromPropertyField(updatedField)
s.Require().Nil(err)
s.Require().Len(cpaField.Attrs.Options, 2)
var optionNames []string
for _, option := range cpaField.Attrs.Options {
optionNames = append(optionNames, option.Name)
}
s.Require().Contains(optionNames, "Go")
s.Require().Contains(optionNames, "Python")
})
s.RunForSystemAdminAndLocal("Edit field using --managed flag", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// First create a field to edit
field := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Department",
Type: model.PropertyFieldTypeText,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
},
}
createdField, appErr := s.th.App.CreateCPAField(field)
s.Require().Nil(appErr)
// Now edit the field with --managed flag
cmd := &cobra.Command{}
cmd.Flags().String("name", "", "")
cmd.Flags().Bool("managed", false, "")
cmd.Flags().String("attrs", "", "")
cmd.Flags().StringSlice("option", []string{}, "")
err := cmd.Flags().Set("managed", "true")
s.Require().Nil(err)
err = cpaFieldEditCmdF(c, cmd, []string{createdField.ID})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify field was actually updated
updatedField, appErr := s.th.App.GetCPAField(createdField.ID)
s.Require().Nil(appErr)
// Convert to CPAField to check attrs
cpaField, err := model.NewCPAFieldFromPropertyField(updatedField)
s.Require().Nil(err)
// Verify that managed flag was set correctly
s.Require().Equal("admin", cpaField.Attrs.Managed)
})
s.RunForSystemAdminAndLocal("Edit field by name", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// First create a field to edit
field := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Department",
Type: model.PropertyFieldTypeText,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
},
}
createdField, appErr := s.th.App.CreateCPAField(field)
s.Require().Nil(appErr)
// Now edit the field using its name instead of ID
cmd := &cobra.Command{}
cmd.Flags().String("name", "", "")
cmd.Flags().Bool("managed", false, "")
cmd.Flags().String("attrs", "", "")
cmd.Flags().StringSlice("option", []string{}, "")
err := cmd.Flags().Set("name", "Team")
s.Require().Nil(err)
err = cmd.Flags().Set("managed", "true")
s.Require().Nil(err)
// Edit using field name "Department" instead of the field ID
err = cpaFieldEditCmdF(c, cmd, []string{"Department"})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the success message
output := printer.GetLines()[0].(string)
s.Require().Contains(output, "Field Team successfully updated")
// Verify field was actually updated by retrieving it
updatedField, appErr := s.th.App.GetCPAField(createdField.ID)
s.Require().Nil(appErr)
s.Require().Equal("Team", updatedField.Name)
// Convert to CPAField to check managed status
cpaField, err := model.NewCPAFieldFromPropertyField(updatedField)
s.Require().Nil(err)
s.Require().Equal("admin", cpaField.Attrs.Managed)
})
s.RunForSystemAdminAndLocal("Edit multiselect field with option preservation", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// First create a multiselect field with two options
field := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Programming Languages",
Type: model.PropertyFieldTypeMultiselect,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Options: []*model.CustomProfileAttributesSelectOption{
{ID: model.NewId(), Name: "Go"},
{ID: model.NewId(), Name: "Python"},
},
},
}
createdField, appErr := s.th.App.CreateCPAField(field)
s.Require().Nil(appErr)
// Get the original option IDs to verify they are preserved
originalCPAField, err := model.NewCPAFieldFromPropertyField(createdField)
s.Require().Nil(err)
s.Require().Len(originalCPAField.Attrs.Options, 2)
originalGoID := ""
originalPythonID := ""
for _, option := range originalCPAField.Attrs.Options {
switch option.Name {
case "Go":
originalGoID = option.ID
case "Python":
originalPythonID = option.ID
}
}
s.Require().NotEmpty(originalGoID)
s.Require().NotEmpty(originalPythonID)
// Now edit the field to add a third option while preserving the first two
cmd := &cobra.Command{}
cmd.Flags().String("name", "", "")
cmd.Flags().Bool("managed", false, "")
cmd.Flags().String("attrs", "", "")
cmd.Flags().StringSlice("option", []string{}, "")
err = cmd.Flags().Set("option", "Go")
s.Require().Nil(err)
err = cmd.Flags().Set("option", "Python")
s.Require().Nil(err)
err = cmd.Flags().Set("option", "React")
s.Require().Nil(err)
err = cpaFieldEditCmdF(c, cmd, []string{createdField.ID})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the success message
output := printer.GetLines()[0].(string)
s.Require().Contains(output, "Field Programming Languages successfully updated")
// Verify field was actually updated and options are preserved correctly
updatedField, appErr := s.th.App.GetCPAField(createdField.ID)
s.Require().Nil(appErr)
// Convert to CPAField to check options
updatedCPAField, err := model.NewCPAFieldFromPropertyField(updatedField)
s.Require().Nil(err)
s.Require().Len(updatedCPAField.Attrs.Options, 3)
// Verify the first two options preserved their original IDs and the third is new
foundGo := false
foundPython := false
foundReact := false
for _, option := range updatedCPAField.Attrs.Options {
switch option.Name {
case "Go":
s.Require().Equal(originalGoID, option.ID, "Go option should preserve its original ID")
foundGo = true
case "Python":
s.Require().Equal(originalPythonID, option.ID, "Python option should preserve its original ID")
foundPython = true
case "React":
s.Require().NotEmpty(option.ID, "React option should have a valid ID")
s.Require().NotEqual(originalGoID, option.ID, "React option should have a different ID than Go")
s.Require().NotEqual(originalPythonID, option.ID, "React option should have a different ID than Python")
foundReact = true
}
}
s.Require().True(foundGo, "Go option should be present")
s.Require().True(foundPython, "Python option should be present")
s.Require().True(foundReact, "React option should be present")
})
}
func (s *MmctlE2ETestSuite) TestCPAFieldDeleteCmd() {
s.SetupEnterpriseTestHelper().InitBasic()
s.th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
s.RunForSystemAdminAndLocal("Delete existing field", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// First create a field to delete
field := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Department",
Type: model.PropertyFieldTypeText,
TargetType: "user",
},
}
createdField, appErr := s.th.App.CreateCPAField(field)
s.Require().Nil(appErr)
cmd := &cobra.Command{}
cmd.Flags().Bool("confirm", false, "")
err := cmd.Flags().Set("confirm", "true")
s.Require().Nil(err)
err = cpaFieldDeleteCmdF(c, cmd, []string{createdField.ID})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the success message
output := printer.GetLines()[0].(string)
s.Require().Contains(output, "Successfully deleted CPA field")
// Verify field was actually deleted by checking if it exists in the list
fields, appErr := s.th.App.ListCPAFields()
s.Require().Nil(appErr)
// Field should not be in the list anymore
fieldExists := false
for _, field := range fields {
if field.ID == createdField.ID {
fieldExists = true
break
}
}
s.Require().False(fieldExists, "Field should have been deleted but still exists in the list")
})
s.RunForSystemAdminAndLocal("Delete existing field by name", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
// First create a field to delete
field := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Department",
Type: model.PropertyFieldTypeText,
TargetType: "user",
},
}
createdField, appErr := s.th.App.CreateCPAField(field)
s.Require().Nil(appErr)
cmd := &cobra.Command{}
cmd.Flags().Bool("confirm", false, "")
err := cmd.Flags().Set("confirm", "true")
s.Require().Nil(err)
// Delete using field name instead of ID
err = cpaFieldDeleteCmdF(c, cmd, []string{"Department"})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify the success message
output := printer.GetLines()[0].(string)
s.Require().Contains(output, "Successfully deleted CPA field: Department")
// Verify field was actually deleted by checking if it exists in the list
fields, appErr := s.th.App.ListCPAFields()
s.Require().Nil(appErr)
// Field should not be in the list anymore
fieldExists := false
for _, field := range fields {
if field.ID == createdField.ID {
fieldExists = true
break
}
}
s.Require().False(fieldExists, "Field should have been deleted but still exists in the list")
})
s.RunForSystemAdminAndLocal("Delete nonexistent field", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
cmd := &cobra.Command{}
cmd.Flags().Bool("confirm", false, "")
err := cmd.Flags().Set("confirm", "true")
s.Require().Nil(err)
err = cpaFieldDeleteCmdF(c, cmd, []string{"nonexistent-field-id"})
s.Require().NotNil(err)
s.Require().Contains(err.Error(), `failed to get field for "nonexistent-field-id"`)
})
s.RunForSystemAdminAndLocal("Delete nonexistent field by name", func(c client.Client) {
printer.Clean()
s.cleanCPAFields()
cmd := &cobra.Command{}
cmd.Flags().Bool("confirm", false, "")
err := cmd.Flags().Set("confirm", "true")
s.Require().Nil(err)
err = cpaFieldDeleteCmdF(c, cmd, []string{"NonexistentField"})
s.Require().NotNil(err)
s.Require().Contains(err.Error(), `failed to get field for "NonexistentField"`)
})
}