From 2f684ea678c0bcd59b8faed69cace00c9a4d29e6 Mon Sep 17 00:00:00 2001 From: Alex Petraky <petraky@perx.ru> Date: Thu, 20 Jun 2024 10:12:57 +0000 Subject: [PATCH] =?UTF-8?q?fix(core):=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=20?= =?UTF-8?q?=D1=81=D1=85=D0=B5=D0=BC=D1=8B=20Walk=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=82=D0=B8=D0=BF=D0=B0=20Array,=20=D1=80=D0=B5=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0=20=D0=BE?= =?UTF-8?q?=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2=D0=B8=D1=8F=20=D1=81?= =?UTF-8?q?=D1=85=D0=B5=D0=BC=D1=8B=20=D0=BF=D1=80=D0=B8=20=D0=B2=D1=8B?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B5=20Introspect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/schema/field/array.go | 14 +++--- pkg/schema/field/array_test.go | 79 ++++++++++++++++++++++++++++++++++ pkg/schema/test/object_test.go | 54 +++++++++++++++++++++++ 3 files changed, 140 insertions(+), 7 deletions(-) diff --git a/pkg/schema/field/array.go b/pkg/schema/field/array.go index 6700eb9b..32d6f72f 100644 --- a/pkg/schema/field/array.go +++ b/pkg/schema/field/array.go @@ -116,17 +116,17 @@ func (ArrayType) Walk(ctx context.Context, field *Field, v interface{}, fn WalkF return nil, false, nil } - // Выполняется обход по схеме - if opts.WalkSchema && v == nil { - params.Item.Walk(ctx, v, fn, WalkOpts(opts)) - return nil, false, nil - } - arr, ok := v.([]interface{}) - if !ok { + if !ok && v != nil { return nil, false, fmt.Errorf("incorrect type: \"%s\", expected \"[]interface{}\"", reflect.ValueOf(v).Kind()) } + // Выполняется обход по схеме + if opts.WalkSchema && len(arr) == 0 { + _, _, _ = params.Item.Walk(ctx, nil, fn, WalkOpts(opts)) + return nil, false, nil + } + m := make([]interface{}, 0, len(arr)) var merr *multierror.Error diff --git a/pkg/schema/field/array_test.go b/pkg/schema/field/array_test.go index 94e60258..964075c3 100644 --- a/pkg/schema/field/array_test.go +++ b/pkg/schema/field/array_test.go @@ -1,6 +1,7 @@ package field import ( + "context" "fmt" "testing" @@ -23,6 +24,26 @@ func TestArrayField_Decode(t *testing.T) { []interface{}{1.0, 2.0}, false, }, + { + "With object inside with nil-data", + Array( + Object("a", String(), + "b", String()), + ), + nil, + nil, + false, + }, + { + "With object inside with data", + Array( + Object("a", String(), + "b", String()), + ), + []interface{}{map[string]interface{}{"a": "1", "b": "2"}}, + []interface{}{map[string]interface{}{"a": "1", "b": "2"}}, + false, + }, { "Incorrect type", Array(Number("int")), @@ -83,3 +104,61 @@ func TestArrayField_Encode(t *testing.T) { }) } } + +func TestArrayType_Walk(t *testing.T) { + tests := []struct { + name string + field *Field + v interface{} + fn WalkFunc + opts *WalkOptions + want interface{} + want1 bool + wantErr assert.ErrorAssertionFunc + }{ + { + name: "With nil data and WalkSchema = false", + field: Array(Object("a", String(), "b", String())), + v: nil, + opts: &WalkOptions{WalkSchema: false}, + want: nil, + want1: false, + wantErr: assert.NoError, + }, + { + name: "With empty data and WalkSchema = false", + field: Array(Object("a", String(), "b", String())), + v: []interface{}{map[string]interface{}{}}, + opts: &WalkOptions{WalkSchema: false}, + fn: func(ctx context.Context, fld *Field, v interface{}) (result WalkFuncResult, err error) { + return WalkFuncResult{}, err + }, + want: []interface{}{map[string]interface{}{}}, + want1: false, + wantErr: assert.NoError, + }, + { + name: "With data and WalkSchema = false", + field: Array(Object("a", String(), "b", String())), + v: []interface{}{map[string]interface{}{"a": "1", "b": "2"}}, + opts: &WalkOptions{WalkSchema: false}, + fn: func(ctx context.Context, fld *Field, v interface{}) (result WalkFuncResult, err error) { + return WalkFuncResult{}, err + }, + want: []interface{}{map[string]interface{}{"a": "1", "b": "2"}}, + want1: false, + wantErr: assert.NoError, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ar := ArrayType{} + got, got1, err := ar.Walk(context.Background(), tt.field, tt.v, tt.fn, tt.opts) + if !tt.wantErr(t, err, fmt.Sprintf("Walk(%v, %v, %v, %v)", tt.field, tt.v, tt.fn, tt.opts)) { + return + } + assert.Equalf(t, tt.want, got, "Walk(%v, %v, %v, %v)", tt.field, tt.v, tt.fn, tt.opts) + assert.Equalf(t, tt.want1, got1, "Walk(%v, %v, %v, %v)", tt.field, tt.v, tt.fn, tt.opts) + }) + } +} diff --git a/pkg/schema/test/object_test.go b/pkg/schema/test/object_test.go index 38868f66..8ba60d9d 100644 --- a/pkg/schema/test/object_test.go +++ b/pkg/schema/test/object_test.go @@ -1343,6 +1343,60 @@ func TestSchema_Introspect(t *testing.T) { []string{"object_a", "field1", "field2"}, false, }, + { + // если у объекта нет данных Introspect возвращает все поля + "With not initialized object in data", + map[string]interface{}{"object": []interface{}{}}, + schema.New( + "object", field.Array( + field.Object( + "a", field.String(), + "b", field.String(), + "c", field.String(), + ), + ).WithUI(&field.UI{Widget: "Tags"}), + ), + map[string]interface{}{"object": []interface{}{}}, + []string{"object.a", "object.b", "object.c"}, + []string{}, + false, + }, + { + // при добавлении значения по умолчанию для поля запрос Introspect возвращает все поля + "Object initialized by modify.Default in schema", + map[string]interface{}{}, + schema.New( + "object", field.Array( + field.Object( + "a", field.String(), + "b", field.String(), + "c", field.String(), + ), + ).AddOptions(modify.Default([]interface{}{map[string]interface{}{}})).WithUI(&field.UI{Widget: "Tags"}), + ), + map[string]interface{}{}, + []string{"object.a", "object.b", "object.c"}, + []string{}, + false, + }, + { + // при добавлении пустого объекта перед запросом Introspect возвращаются все поля + "Object initialized in data", + map[string]interface{}{"object": []interface{}{map[string]interface{}{}}}, + schema.New( + "object", field.Array( + field.Object( + "a", field.String(), + "b", field.String(), + "c", field.String(), + ), + ).WithUI(&field.UI{Widget: "Tags"}), + ), + map[string]interface{}{"object": []interface{}{map[string]interface{}{}}}, + []string{"object.a", "object.b", "object.c"}, + []string{}, + false, + }, } ctx := context.Background() -- GitLab