diff --git a/workitem/enum_type.go b/workitem/enum_type.go index e2e254bc84..0104710631 100644 --- a/workitem/enum_type.go +++ b/workitem/enum_type.go @@ -162,10 +162,17 @@ func containsAll(a []interface{}, v []interface{}) bool { return result } +// ConvertFromModel implements the FieldType interface func (t EnumType) ConvertFromModel(value interface{}) (interface{}, error) { - converted, err := t.BaseType.ConvertToModel(value) + if value == nil { + return nil, nil + } + converted, err := t.BaseType.ConvertFromModel(value) if err != nil { - return nil, fmt.Errorf("error converting enum value: %s", err.Error()) + return nil, errs.Errorf("error converting enum value: %s", err.Error()) + } + if !contains(t.Values, converted) { + return nil, errs.Errorf("value: %+v (%[1]T) is not part of allowed enum values: %+v", value, t.Values) } return converted, nil } diff --git a/workitem/enum_type_blackbox_test.go b/workitem/enum_type_blackbox_test.go index 7f7a2fa381..424b5cbdd6 100644 --- a/workitem/enum_type_blackbox_test.go +++ b/workitem/enum_type_blackbox_test.go @@ -339,3 +339,86 @@ func TestEnumType_EqualEnclosing(t *testing.T) { }) }) } + +func TestEnumType_ConvertFromModel(t *testing.T) { + t.Parallel() + resource.Require(t, resource.UnitTest) + type testCase struct { + subTestName string + input interface{} // contains valid and invalid values + expectedOutput interface{} + wantErr bool + } + tests := []struct { + name string + enum w.EnumType + data []testCase + }{ + { + "kind string", + w.EnumType{ + SimpleType: w.SimpleType{Kind: w.KindEnum}, + BaseType: w.SimpleType{Kind: w.KindString}, + Values: []interface{}{"first", "second", "third"}, + }, + []testCase{ + {"ok", "second", "second", false}, + {"ok - nil", nil, nil, false}, + {"fail - invalid string", "fourth", nil, true}, + {"fail - int", 11, nil, true}, + {"fail - float", 1.3, nil, true}, + {"fail - empty string", "", nil, true}, + {"fail - list", []string{"x", "y"}, nil, true}, + }, + }, + { + "kind int", + w.EnumType{ + SimpleType: w.SimpleType{Kind: w.KindEnum}, + BaseType: w.SimpleType{Kind: w.KindInteger}, + Values: []interface{}{4, 5, 6}, + }, + []testCase{ + {"ok", 4, 4, false}, + {"ok - nil", nil, nil, false}, + {"fail - invalid int", 2, nil, true}, + {"fail - string", "11", nil, true}, + {"fail - float", 1.3, nil, true}, + {"fail - bool", true, nil, true}, + {"fail - list", []string{"x", "y"}, nil, true}, + }, + }, + { + "kind float", + w.EnumType{ + SimpleType: w.SimpleType{Kind: w.KindEnum}, + BaseType: w.SimpleType{Kind: w.KindFloat}, + Values: []interface{}{1.1, 2.2, 3.3}, + }, + []testCase{ + {"ok", 1.1, 1.1, false}, + {"ok - nil", nil, nil, false}, + {"fail - invalid float", 4.4, nil, true}, + {"fail - int", 1, nil, true}, + {"fail - string", "11", nil, true}, + {"fail - bool", true, nil, true}, + {"fail - list", []string{"x", "y"}, nil, true}, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for _, subtt := range test.data { + t.Run(subtt.subTestName, func(tt *testing.T) { + val, err := test.enum.ConvertFromModel(subtt.input) + if subtt.wantErr { + require.Error(tt, err) + } else { + require.NoError(tt, err) + } + require.Equal(tt, subtt.expectedOutput, val) + }) + } + }) + } +} diff --git a/workitem/simple_type.go b/workitem/simple_type.go index 2daeae9348..339dff1bdc 100644 --- a/workitem/simple_type.go +++ b/workitem/simple_type.go @@ -176,7 +176,7 @@ func (t SimpleType) ConvertToModel(value interface{}) (interface{}, error) { } } -// ConvertFromModel implements the t interface +// ConvertFromModel implements the FieldType interface func (t SimpleType) ConvertFromModel(value interface{}) (interface{}, error) { if value == nil { return nil, nil diff --git a/workitem/workitem_repository.go b/workitem/workitem_repository.go index 6acf658f9b..6c5b9acb4d 100644 --- a/workitem/workitem_repository.go +++ b/workitem/workitem_repository.go @@ -595,7 +595,7 @@ func (r *GormWorkItemRepository) Save(ctx context.Context, spaceID uuid.UUID, up } fieldValue := updatedWorkItem.Fields[fieldName] var err error - if fieldName == SystemAssignees || fieldName == SystemLabels || fieldName == SystemBoardcolumns { + if fieldDef.Type.GetKind() == KindList { switch fieldValue.(type) { case []string: if len(fieldValue.([]string)) == 0 { @@ -735,7 +735,7 @@ func (r *GormWorkItemRepository) Create(ctx context.Context, spaceID uuid.UUID, if err != nil { return nil, nil, errors.NewBadParameterError(fieldName, fieldValue) // TODO(kwk): Change errors pkg to consume the original error as well } - if (fieldName == SystemAssignees || fieldName == SystemLabels || fieldName == SystemBoardcolumns) && fieldValue == nil { + if fieldDef.Type.GetKind() == KindList && fieldValue == nil { delete(wi.Fields, fieldName) } if fieldName == SystemDescription && wi.Fields[fieldName] != nil {