mattermost-community-enterp.../cmd/mmctl/commands/user_attributes_value_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

380 lines
11 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package commands
import (
"encoding/json"
"github.com/mattermost/mattermost/server/public/model"
"github.com/spf13/cobra"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/printer"
)
// cleanCPAValuesForUser removes all CPA values for a user
func (s *MmctlE2ETestSuite) cleanCPAValuesForUser(userID string) {
existingValues, appErr := s.th.App.ListCPAValues(userID)
s.Require().Nil(appErr)
// Clear all existing values by setting them to null
updates := make(map[string]json.RawMessage)
for _, value := range existingValues {
updates[value.FieldID] = json.RawMessage("null")
}
if len(updates) > 0 {
_, appErr = s.th.App.PatchCPAValues(userID, updates, false)
s.Require().Nil(appErr)
}
}
func (s *MmctlE2ETestSuite) TestCPAValueList() {
s.SetupEnterpriseTestHelper().InitBasic()
s.th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
s.Run("List CPA values with no values", func() {
c := s.th.SystemAdminClient
printer.Clean()
s.cleanCPAFields()
s.cleanCPAValuesForUser(s.th.BasicUser.Id)
// Test listing when no values are set
err := cpaValueListCmdF(c, &cobra.Command{}, []string{s.th.BasicUser.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("List CPA values with existing values", func() {
c := s.th.SystemAdminClient
printer.Clean()
s.cleanCPAFields()
s.cleanCPAValuesForUser(s.th.BasicUser.Id)
// Create a text field
textField := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Department",
Type: model.PropertyFieldTypeText,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
},
}
createdField, appErr := s.th.App.CreateCPAField(textField)
s.Require().Nil(appErr)
// Set a text value using the app layer
updates := map[string]json.RawMessage{
createdField.ID: json.RawMessage(`"Engineering"`),
}
_, appErr = s.th.App.PatchCPAValues(s.th.BasicUser.Id, updates, false)
s.Require().Nil(appErr)
// Test listing the values with plain format (human-readable)
printer.SetFormat(printer.FormatPlain)
err := cpaValueListCmdF(c, &cobra.Command{}, []string{s.th.BasicUser.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Check that the human-readable format is used
output := printer.GetLines()[0].(string)
s.Require().Equal("Department (text): Engineering", output)
// Test with JSON format to ensure raw data is preserved
printer.Clean()
printer.SetFormat(printer.FormatJSON)
err = cpaValueListCmdF(c, &cobra.Command{}, []string{s.th.BasicUser.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Check that JSON format outputs raw data structure
outputMap := printer.GetLines()[0].(map[string]any)
s.Require().Contains(outputMap, createdField.ID)
s.Require().Equal(`"Engineering"`, string(outputMap[createdField.ID].(json.RawMessage)))
})
}
func (s *MmctlE2ETestSuite) TestCPAValueSet() {
s.SetupEnterpriseTestHelper().InitBasic()
s.th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
s.Run("Set value for text type field", func() {
c := s.th.SystemAdminClient
printer.Clean()
s.cleanCPAFields()
s.cleanCPAValuesForUser(s.th.BasicUser.Id)
// Create a text field
textField := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Department",
Type: model.PropertyFieldTypeText,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
},
}
createdField, appErr := s.th.App.CreateCPAField(textField)
s.Require().Nil(appErr)
// Set a text value
cmd := &cobra.Command{}
cmd.Flags().StringSlice("value", []string{}, "")
err := cmd.Flags().Set("value", "Engineering")
s.Require().Nil(err)
err = cpaValueSetCmdF(c, cmd, []string{s.th.BasicUser.Email, createdField.ID})
s.Require().Nil(err)
// Verify the value was set
values, appErr := s.th.App.ListCPAValues(s.th.BasicUser.Id)
s.Require().Nil(appErr)
s.Require().Len(values, 1)
s.Require().Equal(createdField.ID, values[0].FieldID)
s.Require().Equal(`"Engineering"`, string(values[0].Value))
})
s.Run("Set value for select type field", func() {
c := s.th.SystemAdminClient
printer.Clean()
s.cleanCPAFields()
s.cleanCPAValuesForUser(s.th.BasicUser.Id)
// Create a select field with options
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"},
{ID: model.NewId(), Name: "Lead"},
},
},
}
createdField, appErr := s.th.App.CreateCPAField(selectField)
s.Require().Nil(appErr)
// Convert to CPAField to access options
cpaField, err := model.NewCPAFieldFromPropertyField(createdField)
s.Require().Nil(err)
// Set a select value using the option name
cmd := &cobra.Command{}
cmd.Flags().StringSlice("value", []string{}, "")
err = cmd.Flags().Set("value", "Senior")
s.Require().Nil(err)
err = cpaValueSetCmdF(c, cmd, []string{s.th.BasicUser.Email, createdField.ID})
s.Require().Nil(err)
// Verify the value was set (should be stored as option ID)
values, appErr := s.th.App.ListCPAValues(s.th.BasicUser.Id)
s.Require().Nil(appErr)
s.Require().Len(values, 1)
s.Require().Equal(createdField.ID, values[0].FieldID)
// Find the Senior option ID for verification
var seniorOptionID string
for _, option := range cpaField.Attrs.Options {
if option.Name == "Senior" {
seniorOptionID = option.ID
break
}
}
s.Require().Equal(`"`+seniorOptionID+`"`, string(values[0].Value))
})
s.Run("Set value for multiselect type field", func() {
c := s.th.SystemAdminClient
printer.Clean()
s.cleanCPAFields()
s.cleanCPAValuesForUser(s.th.BasicUser.Id)
// Create a multiselect field with options
multiselectField := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Skills",
Type: model.PropertyFieldTypeMultiselect,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
Options: []*model.CustomProfileAttributesSelectOption{
{ID: model.NewId(), Name: "Go"},
{ID: model.NewId(), Name: "React"},
{ID: model.NewId(), Name: "Python"},
{ID: model.NewId(), Name: "JavaScript"},
},
},
}
createdField, appErr := s.th.App.CreateCPAField(multiselectField)
s.Require().Nil(appErr)
// Convert to CPAField to access options
cpaField, err := model.NewCPAFieldFromPropertyField(createdField)
s.Require().Nil(err)
// Set multiple values using option names
cmd := &cobra.Command{}
cmd.Flags().StringSlice("value", []string{}, "")
err = cmd.Flags().Set("value", "Go")
s.Require().Nil(err)
err = cmd.Flags().Set("value", "React")
s.Require().Nil(err)
err = cmd.Flags().Set("value", "Python")
s.Require().Nil(err)
err = cpaValueSetCmdF(c, cmd, []string{s.th.BasicUser.Email, createdField.ID})
s.Require().Nil(err)
// Verify the values were set (should be stored as option IDs)
values, appErr := s.th.App.ListCPAValues(s.th.BasicUser.Id)
s.Require().Nil(appErr)
s.Require().Len(values, 1)
s.Require().Equal(createdField.ID, values[0].FieldID)
// Find the option IDs for verification
var goOptionID, reactOptionID, pythonOptionID string
for _, option := range cpaField.Attrs.Options {
switch option.Name {
case "Go":
goOptionID = option.ID
case "React":
reactOptionID = option.ID
case "Python":
pythonOptionID = option.ID
}
}
// The multiselect values should be stored as an array of option IDs
// The JSON serialization may include spaces, so we need to compare the content, not exact string
actualValue := string(values[0].Value)
s.Require().Contains(actualValue, goOptionID)
s.Require().Contains(actualValue, reactOptionID)
s.Require().Contains(actualValue, pythonOptionID)
})
s.Run("Set a single value for multiselect type field", func() {
c := s.th.SystemAdminClient
printer.Clean()
s.cleanCPAFields()
s.cleanCPAValuesForUser(s.th.BasicUser.Id)
// Create a multiselect field with options
multiselectField := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Programming Languages",
Type: model.PropertyFieldTypeMultiselect,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
Options: []*model.CustomProfileAttributesSelectOption{
{ID: model.NewId(), Name: "Go"},
{ID: model.NewId(), Name: "Python"},
{ID: model.NewId(), Name: "JavaScript"},
},
},
}
createdField, appErr := s.th.App.CreateCPAField(multiselectField)
s.Require().Nil(appErr)
// Convert to CPAField to access options
cpaField, err := model.NewCPAFieldFromPropertyField(createdField)
s.Require().Nil(err)
// Set a single value using option name
cmd := &cobra.Command{}
cmd.Flags().StringSlice("value", []string{}, "")
err = cmd.Flags().Set("value", "Python")
s.Require().Nil(err)
err = cpaValueSetCmdF(c, cmd, []string{s.th.BasicUser.Email, createdField.ID})
s.Require().Nil(err)
// Verify the value was set (should be stored as an array with single option ID)
values, appErr := s.th.App.ListCPAValues(s.th.BasicUser.Id)
s.Require().Nil(appErr)
s.Require().Len(values, 1)
s.Require().Equal(createdField.ID, values[0].FieldID)
// Find the option ID for verification
var pythonOptionID string
for _, option := range cpaField.Attrs.Options {
if option.Name == "Python" {
pythonOptionID = option.ID
break
}
}
// The multiselect value should be stored as an array with single option ID
// Even for single value, multiselect fields store values as arrays
actualValue := string(values[0].Value)
s.Require().Contains(actualValue, pythonOptionID)
s.Require().Contains(actualValue, "[")
s.Require().Contains(actualValue, "]")
// Verify it doesn't contain other option IDs
for _, option := range cpaField.Attrs.Options {
if option.Name != "Python" {
s.Require().NotContains(actualValue, option.ID)
}
}
})
s.Run("Set value for user type field", func() {
c := s.th.SystemAdminClient
printer.Clean()
s.cleanCPAFields()
s.cleanCPAValuesForUser(s.th.BasicUser.Id)
// Create a user field
userField := &model.CPAField{
PropertyField: model.PropertyField{
Name: "Manager",
Type: model.PropertyFieldTypeUser,
TargetType: "user",
},
Attrs: model.CPAAttrs{
Managed: "",
},
}
createdField, appErr := s.th.App.CreateCPAField(userField)
s.Require().Nil(appErr)
// Set a user value using the system admin user ID
cmd := &cobra.Command{}
cmd.Flags().StringSlice("value", []string{}, "")
err := cmd.Flags().Set("value", s.th.SystemAdminUser.Id)
s.Require().Nil(err)
err = cpaValueSetCmdF(c, cmd, []string{s.th.BasicUser.Email, createdField.ID})
s.Require().Nil(err)
// Verify the value was set
values, appErr := s.th.App.ListCPAValues(s.th.BasicUser.Id)
s.Require().Nil(appErr)
s.Require().Len(values, 1)
s.Require().Equal(createdField.ID, values[0].FieldID)
s.Require().Equal(`"`+s.th.SystemAdminUser.Id+`"`, string(values[0].Value))
})
}