From 752877425043784b1e640b0b1c2b9711fc8a1f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Thu, 24 Oct 2019 16:48:21 +0200 Subject: [PATCH] Add record impor tests --- compose/rest/record.go | 4 +- compose/service/error.go | 29 +++--- compose/service/import_session.go | 3 +- tests/compose/record_test.go | 166 ++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 17 deletions(-) diff --git a/compose/rest/record.go b/compose/rest/record.go index e6944f3e8..cbbbbd96c 100644 --- a/compose/rest/record.go +++ b/compose/rest/record.go @@ -211,7 +211,7 @@ func (ctrl *Record) ImportInit(ctx context.Context, r *request.RecordImportInit) recordDecoder = decoder.NewFlatReader(csv.NewReader(f), f) default: - return nil, errors.New(fmt.Sprintf("unsupported format (\"%s\")", ext)) + return nil, service.ErrRecordImportFormatNotSupported } entryCount, err = recordDecoder.EntryCount() @@ -252,7 +252,7 @@ func (ctrl *Record) ImportRun(ctx context.Context, r *request.RecordImportRun) ( } if ses.Progress.StartedAt != nil { - return nil, errors.New("Unable to start import: Import session already active") + return nil, service.ErrRecordImportSessionAlreadyStarted } ses.Fields = make(map[string]string) diff --git a/compose/service/error.go b/compose/service/error.go index e2c5e09de..f2d967c29 100644 --- a/compose/service/error.go +++ b/compose/service/error.go @@ -9,19 +9,22 @@ type ( ) const ( - ErrInvalidID serviceError = "InvalidID" - ErrInvalidHandle serviceError = "InvalidHandle" - ErrStaleData serviceError = "StaleData" - ErrNoPermissions serviceError = "NoPermissions" - ErrNoGrantPermissions serviceError = "NoGrantPermissions" - ErrNoCreatePermissions serviceError = "NoCreatePermissions" - ErrNoReadPermissions serviceError = "NoReadPermissions" - ErrNoUpdatePermissions serviceError = "NoUpdatePermissions" - ErrNoDeletePermissions serviceError = "NoDeletePermissions" - ErrNoTriggerManagementPermissions serviceError = "NoTriggerManagementPermissions" - ErrNamespaceRequired serviceError = "NamespaceRequired" - ErrModulePageExists serviceError = "ModulePageExists" - ErrNotImplemented serviceError = "NotImplemented" + ErrInvalidID serviceError = "InvalidID" + ErrInvalidHandle serviceError = "InvalidHandle" + ErrStaleData serviceError = "StaleData" + ErrNoPermissions serviceError = "NoPermissions" + ErrNoGrantPermissions serviceError = "NoGrantPermissions" + ErrNoCreatePermissions serviceError = "NoCreatePermissions" + ErrNoReadPermissions serviceError = "NoReadPermissions" + ErrNoUpdatePermissions serviceError = "NoUpdatePermissions" + ErrNoDeletePermissions serviceError = "NoDeletePermissions" + ErrNoTriggerManagementPermissions serviceError = "NoTriggerManagementPermissions" + ErrNamespaceRequired serviceError = "NamespaceRequired" + ErrModulePageExists serviceError = "ModulePageExists" + ErrNotImplemented serviceError = "NotImplemented" + ErrRecordImportSessionNotFound serviceError = "RecordImportSessionNotFound" + ErrRecordImportSessionAlreadyStarted serviceError = "RecordImportSessionAlreadyStarted" + ErrRecordImportFormatNotSupported serviceError = "RecordImportFormatNotSupported" ) func (e serviceError) Error() string { diff --git a/compose/service/import_session.go b/compose/service/import_session.go index ce84adc4f..1697b9cf6 100644 --- a/compose/service/import_session.go +++ b/compose/service/import_session.go @@ -9,7 +9,6 @@ import ( "github.com/cortezaproject/corteza-server/pkg/auth" - "github.com/pkg/errors" "go.uber.org/zap" ) @@ -56,7 +55,7 @@ func (svc *importSession) FindRecordByID(ctx context.Context, sessionID uint64) if i >= 0 { return svc.records[i], nil } - return nil, errors.New("Can't access session: session not found") + return nil, ErrRecordImportSessionNotFound } func (svc *importSession) SetRecordByID(ctx context.Context, sessionID, namespaceID, moduleID uint64, fields map[string]string, progress *RecordImportProgress, decoder Decoder) (*RecordImportSession, error) { diff --git a/tests/compose/record_test.go b/tests/compose/record_test.go index dfb43413c..70ef5ec87 100644 --- a/tests/compose/record_test.go +++ b/tests/compose/record_test.go @@ -1,13 +1,16 @@ package compose import ( + "bytes" "context" "fmt" "io/ioutil" + "mime/multipart" "net/http" "testing" "time" + "github.com/steinfletcher/apitest" jsonpath "github.com/steinfletcher/apitest-jsonpath" "github.com/cortezaproject/corteza-server/compose/repository" @@ -15,6 +18,14 @@ import ( "github.com/cortezaproject/corteza-server/tests/helpers" ) +type ( + rImportSession struct { + Response struct { + SessionID string `json:"sessionID"` + } `json:"response"` + } +) + func (h helper) repoRecord() repository.RecordRepository { return repository.Record(context.Background(), db()) } @@ -220,3 +231,158 @@ func TestRecordExport(t *testing.T) { h.a.NoError(err) h.a.Equal("name\nd0\nd1\nd2\nd3\nd4\nd5\nd6\nd7\nd8\nd9\n", string(b)) } + +func (h helper) apiInitRecordImport(api *apitest.APITest, url, f string, file []byte) *apitest.Response { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + part, err := writer.CreateFormFile("upload", f) + h.a.NoError(err) + + _, err = part.Write(file) + h.a.NoError(err) + h.a.NoError(writer.Close()) + + return api. + Post(url). + Body(body.String()). + ContentType(writer.FormDataContentType()). + Expect(h.t). + Status(http.StatusOK) +} + +func (h helper) apiRunRecordImport(api *apitest.APITest, url, b string) *apitest.Response { + return api. + Patch(url). + JSON(b). + Expect(h.t). + Status(http.StatusOK) +} + +func TestRecordImportInit(t *testing.T) { + h := newHelper(t) + + module := h.repoMakeRecordModuleWithFields("record import init module") + tests := []struct { + Name string + Content string + }{ + { + Name: "f1.csv", + Content: "name,email\nv1,v2\n", + }, + { + Name: "f1.json", + Content: `{"name":"v1","email":"v2"}` + "\n", + }, + } + + for _, test := range tests { + t.Run(t.Name(), func(t *testing.T) { + url := fmt.Sprintf("/namespace/%d/module/%d/record/import", module.NamespaceID, module.ID) + h.apiInitRecordImport(h.apiInit(), url, test.Name, []byte(test.Content)). + Assert(jsonpath.Present("$.response.sessionID")). + Assert(jsonpath.Present(`$.response.fields.name==""`)). + Assert(jsonpath.Present(`$.response.fields.email==""`)). + Assert(jsonpath.Present("$.response.progress")). + Assert(jsonpath.Present("$.response.progress.entryCount==1")). + End() + }) + } +} + +func TestRecordImportInit_invalidFileFormat(t *testing.T) { + h := newHelper(t) + + module := h.repoMakeRecordModuleWithFields("record import init module") + url := fmt.Sprintf("/namespace/%d/module/%d/record/import", module.NamespaceID, module.ID) + h.apiInitRecordImport(h.apiInit(), url, "invalid", []byte("nope")). + Assert(helpers.AssertError("compose.service.RecordImportFormatNotSupported")). + End() +} + +func TestRecordImportRun(t *testing.T) { + h := newHelper(t) + + module := h.repoMakeRecordModuleWithFields("record import run module") + tests := []struct { + Name string + Content string + }{ + { + Name: "f1.csv", + Content: "fname,femail\nv1,v2\n", + }, + } + + for _, test := range tests { + t.Run(t.Name(), func(t *testing.T) { + url := fmt.Sprintf("/namespace/%d/module/%d/record/import", module.NamespaceID, module.ID) + rsp := &rImportSession{} + api := h.apiInit() + + r := h.apiInitRecordImport(api, url, test.Name, []byte(test.Content)).End() + r.JSON(rsp) + + h.apiRunRecordImport(api, fmt.Sprintf("%s/%s", url, rsp.Response.SessionID), `{"fields":{"fname":"name","femail":"email"},"onError":"fail"}`). + Assert(helpers.AssertNoErrors). + Assert(jsonpath.Present("$.response.progress")). + Assert(jsonpath.Present(`$.response.fields.fname=="name"`)). + Assert(jsonpath.Present(`$.response.fields.femail=="email"`)). + End() + }) + } +} + +func TestRecordImportRun_sessionNotFound(t *testing.T) { + h := newHelper(t) + + module := h.repoMakeRecordModuleWithFields("record import run module") + h.apiRunRecordImport(h.apiInit(), fmt.Sprintf("/namespace/%d/module/%d/record/import/123", module.NamespaceID, module.ID), `{"fields":{"fname":"name","femail":"email"},"onError":"fail"}`). + Assert(helpers.AssertError("compose.service.RecordImportSessionNotFound")). + End() +} + +func TestRecordImportImportProgress(t *testing.T) { + h := newHelper(t) + + module := h.repoMakeRecordModuleWithFields("record import session module") + tests := []struct { + Name string + Content string + }{ + { + Name: "f1.csv", + Content: "fname,femail\nv1,v2\n", + }, + } + + for _, test := range tests { + t.Run(t.Name(), func(t *testing.T) { + url := fmt.Sprintf("/namespace/%d/module/%d/record/import", module.NamespaceID, module.ID) + rsp := &rImportSession{} + api := h.apiInit() + + r := h.apiInitRecordImport(api, url, test.Name, []byte(test.Content)).End() + r.JSON(rsp) + + api.Get(fmt.Sprintf("%s/%s", url, rsp.Response.SessionID)). + Expect(h.t). + Status(http.StatusOK). + Assert(helpers.AssertNoErrors). + Assert(jsonpath.Present("$.response.progress")). + End() + }) + } +} + +func TestRecordImportImportProgress_sessionNotFound(t *testing.T) { + h := newHelper(t) + + module := h.repoMakeRecordModuleWithFields("record import module") + h.apiInit(). + Get(fmt.Sprintf("/namespace/%d/module/%d/record/import/123", module.NamespaceID, module.ID)). + Expect(h.t). + Status(http.StatusOK). + Assert(helpers.AssertError("compose.service.RecordImportSessionNotFound")). + End() +}