diff --git a/pkg/items/middleware/client_encode_middleware.go b/pkg/items/middleware/client_encode_middleware.go index 324c648ea398efab8295077fd6e49f897cf86f93..476687b84f2820537bddee79c00243f5ec05a475 100644 --- a/pkg/items/middleware/client_encode_middleware.go +++ b/pkg/items/middleware/client_encode_middleware.go @@ -31,18 +31,21 @@ func (m *encodeDecodeMiddleware) Introspect(ctx context.Context, item *items.Ite return nil, nil, err } - if item, err = item.Encode(ctx, coll.Schema); err != nil { - return + encoded, err := item.Encode(ctx, coll.Schema) + if err != nil { + // Возвращаем исходные данные для возможности обработки полей с ошибками. + return item, coll.Schema, err } - itm, sch, err = m.next.Introspect(ctx, item, opts...) - if itm != nil && sch != nil { + introspected, sch, err := m.next.Introspect(ctx, encoded, opts...) + if introspected != nil && sch != nil { var err error - if itm, err = itm.Decode(ctx, sch); err != nil { - return nil, nil, err + if introspected, err = introspected.Decode(ctx, sch); err != nil { + // Возвращаем исходные данные для возможности обработки полей с ошибками. + return item, coll.Schema, err } } - return itm, sch, err + return introspected, sch, err } diff --git a/pkg/items/middleware/client_encode_middleware_test.go b/pkg/items/middleware/client_encode_middleware_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4adbdb655f164f650ab357e028dd18c9f95c6971 --- /dev/null +++ b/pkg/items/middleware/client_encode_middleware_test.go @@ -0,0 +1,144 @@ +package middleware + +import ( + "context" + "testing" + "time" + + "git.perx.ru/perxis/perxis-go/pkg/collections" + collectionsmocks "git.perx.ru/perxis/perxis-go/pkg/collections/mocks" + "git.perx.ru/perxis/perxis-go/pkg/items" + itemsmocks "git.perx.ru/perxis/perxis-go/pkg/items/mocks" + "git.perx.ru/perxis/perxis-go/pkg/schema" + "git.perx.ru/perxis/perxis-go/pkg/schema/field" + "git.perx.ru/perxis/perxis-go/pkg/schema/modify" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestEncodeDecodeMiddleware_Introspect(t *testing.T) { + t.Run("Successful", func(t *testing.T) { + sch := schema.New( + "date", field.Time(), + ) + + itemsMock := itemsmocks.NewItems(t) + itemsMock.On("Introspect", mock.Anything, mock.Anything).Return(&items.Item{ + ID: "", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "date": time.Date(2025, 12, 1, 0, 0, 0, 0, time.UTC), + }, + }, sch, nil).Once() + + collectionsMock := collectionsmocks.NewCollections(t) + collectionsMock.On("Get", mock.Anything, "space", "env", "coll").Return(&collections.Collection{ + ID: "coll", + SpaceID: "space", + EnvID: "env", + Schema: sch, + }, nil).Once() + + middleware := ClientEncodeMiddleware(collectionsMock)(itemsMock) + item, sch, err := middleware.Introspect(context.Background(), &items.Item{ + ID: "id", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + }) + require.NoError(t, err) + assert.Equal(t, map[string]any{"date": time.Date(2025, 12, 1, 0, 0, 0, 0, time.UTC)}, item.Data) + assert.NotNil(t, sch) + }) + t.Run("Error during encoding", func(t *testing.T) { + sch := schema.New( + "date", field.Time(), + ) + + itemsMock := itemsmocks.NewItems(t) + collectionsMock := collectionsmocks.NewCollections(t) + collectionsMock.On("Get", mock.Anything, "space", "env", "coll").Return(&collections.Collection{ + ID: "coll", + SpaceID: "space", + EnvID: "env", + Schema: sch, + }, nil).Once() + + middleware := ClientEncodeMiddleware(collectionsMock)(itemsMock) + item, sch, err := middleware.Introspect(context.Background(), &items.Item{ + ID: "", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "date": "invalid date", + }, + }) + require.EqualError( + t, + err, + "encode error: 1 error occurred:\n\t* field 'date': TimeType: encode: unsupported value type : \"string\"\n\n", + ) + assert.Equal(t, + map[string]any{ + "date": "invalid date", + }, + item.Data, + "При возникновении ошибки декодирования в ответе должны быть возвращены исходные данные", + ) + assert.NotNil(t, sch) + }) + t.Run("Error during decoding", func(t *testing.T) { + sch := schema.New( + "num", field.Number(field.NumberFormatInt), + "str", field.String().AddOptions(modify.Value("num")), + ) + + itemsMock := itemsmocks.NewItems(t) + itemsMock.On("Introspect", mock.Anything, mock.Anything).Return(&items.Item{ + ID: "id", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "num": 100, + "str": 100, + }, + }, sch, nil).Once() + + collectionsMock := collectionsmocks.NewCollections(t) + collectionsMock.On("Get", mock.Anything, "space", "env", "coll").Return(&collections.Collection{ + ID: "coll", + SpaceID: "space", + EnvID: "env", + Schema: sch, + }, nil).Once() + + middleware := ClientEncodeMiddleware(collectionsMock)(itemsMock) + item, sch, err := middleware.Introspect(context.Background(), &items.Item{ + ID: "id", + SpaceID: "space", + EnvID: "env", + CollectionID: "coll", + Data: map[string]any{ + "num": 100, + }, + }) + require.EqualError( + t, + err, + "decode error: 1 error occurred:\n\t* field 'str': StringField decode error: unsupported value type : \"int\"\n\n", + ) + assert.Equal(t, + map[string]any{ + "num": 100, + }, + item.Data, + "При возникновении ошибки кодирования в ответе должны быть возвращены исходные данные", + ) + assert.NotNil(t, sch) + }) +}