From da52e810cf98ffe9a57cb0a8ecf68df97f6ac6f7 Mon Sep 17 00:00:00 2001 From: hantonelli Date: Mon, 15 Apr 2019 22:26:35 +0100 Subject: [PATCH] Extend test and don't close form file. --- example/fileupload/fileupload_test.go | 51 +++++++++++++++++++++ handler/graphql.go | 1 - handler/graphql_test.go | 65 +++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/example/fileupload/fileupload_test.go b/example/fileupload/fileupload_test.go index 6ada462a150..e91029375f9 100644 --- a/example/fileupload/fileupload_test.go +++ b/example/fileupload/fileupload_test.go @@ -208,6 +208,57 @@ func TestFileUpload(t *testing.T) { require.Nil(t, err) require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1,"name":"a.txt","content":"test1"},{"id":2,"name":"b.txt","content":"test2"}]}}`, string(responseBody)) }) + + t.Run("valid file list upload with payload and file reuse", func(t *testing.T) { + resolver := &Resolver{ + MultipleUploadWithPayloadFunc: func(ctx context.Context, req []model.UploadFile) ([]model.File, error) { + require.Len(t, req, 2) + var ids []int + var contents []string + var resp []model.File + for i := range req { + require.NotNil(t, req[i].File) + require.NotNil(t, req[i].File.File) + ids = append(ids, req[i].ID) + req[i].File.File.Seek(0, 0) + content, err := ioutil.ReadAll(req[i].File.File) + require.Nil(t, err) + contents = append(contents, string(content)) + resp = append(resp, model.File{ + ID: i + 1, + Name: req[i].File.Filename, + Content: string(content), + }) + } + require.ElementsMatch(t, []int{1, 2}, ids) + require.ElementsMatch(t, []string{"test1", "test1"}, contents) + return resp, nil + }, + } + srv := httptest.NewServer(handler.GraphQL(NewExecutableSchema(Config{Resolvers: resolver}), handler.UploadMaxMemory(2))) + defer srv.Close() + + operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id, name, content } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }` + mapData := `{ "0": ["variables.req.0.file", "variables.req.1.file"] }` + files := []file{ + { + mapKey: "0", + name: "a.txt", + content: "test1", + }, + } + req := createUploadRequest(t, srv.URL, operations, mapData, files) + + resp, err := client.Do(req) + require.Nil(t, err) + defer func() { + _ = resp.Body.Close() + }() + require.Equal(t, http.StatusOK, resp.StatusCode) + responseBody, err := ioutil.ReadAll(resp.Body) + require.Nil(t, err) + require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1,"name":"a.txt","content":"test1"},{"id":2,"name":"a.txt","content":"test1"}]}}`, string(responseBody)) + }) } type file struct { diff --git a/handler/graphql.go b/handler/graphql.go index 2e52f1d9be5..e34329a8f05 100644 --- a/handler/graphql.go +++ b/handler/graphql.go @@ -563,7 +563,6 @@ func processMultipart(w http.ResponseWriter, r *http.Request, request *params, u if err != nil { return fmt.Errorf("failed to get key %s from form", key) } - defer file.Close() if len(paths) == 0 { return fmt.Errorf("invalid empty operations paths list for key %s", key) } diff --git a/handler/graphql_test.go b/handler/graphql_test.go index cb9b1788e31..fd353cff1b8 100644 --- a/handler/graphql_test.go +++ b/handler/graphql_test.go @@ -3,6 +3,7 @@ package handler import ( "bytes" "context" + "fmt" "io/ioutil" "mime/multipart" "net/http" @@ -301,6 +302,33 @@ func TestFileUpload(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1},{"id":2}]}}`, resp.Body.String()) }) + + t.Run("valid file list upload with payload and file reuse", func(t *testing.T) { + mock := &executableSchemaMock{ + MutationFunc: func(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { + require.Equal(t, len(op.VariableDefinitions), 1) + require.Equal(t, op.VariableDefinitions[0].Variable, "req") + return &graphql.Response{Data: []byte(`{"multipleUploadWithPayload":[{"id":1},{"id":2}]}`)} + }, + } + handler := GraphQL(mock) + + operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }` + mapData := `{ "0": ["variables.req.0.file", "variables.req.1.file"] }` + files := []file{ + { + mapKey: "0", + name: "a.txt", + content: "test1", + }, + } + req := createUploadRequest(t, operations, mapData, files) + + resp := httptest.NewRecorder() + handler.ServeHTTP(resp, req) + require.Equal(t, http.StatusOK, resp.Code) + require.Equal(t, `{"data":{"multipleUploadWithPayload":[{"id":1},{"id":2}]}}`, resp.Body.String()) + }) } func TestProcessMultipart(t *testing.T) { @@ -401,6 +429,43 @@ func TestProcessMultipart(t *testing.T) { require.Nil(t, err) require.Equal(t, "test1", string(content)) }) + + t.Run("valid request with two values", func(t *testing.T) { + operations := `{ "query": "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id } }", "variables": { "req": [ { "id": 1, "file": null }, { "id": 2, "file": null } ] } }` + mapData := `{ "0": ["variables.req.0.file", "variables.req.1.file"] }` + files := []file{ + { + mapKey: "0", + name: "a.txt", + content: "test1", + }, + } + req := createUploadRequest(t, operations, mapData, files) + + var reqParams params + w := httptest.NewRecorder() + err := processMultipart(w, req, &reqParams, DefaultUploadMaxSize, 2) + require.Nil(t, err) + require.Equal(t, "mutation($req: [UploadFile!]!) { multipleUploadWithPayload(req: $req) { id } }", reqParams.Query) + require.Equal(t, "", reqParams.OperationName) + require.Equal(t, 1, len(reqParams.Variables)) + require.NotNil(t, reqParams.Variables["req"]) + reqParamsFile, ok := reqParams.Variables["req"].([]interface{}) + require.True(t, ok) + require.Equal(t, 2, len(reqParamsFile)) + for i, item := range reqParamsFile { + itemMap := item.(map[string]interface{}) + require.Equal(t, fmt.Sprint(itemMap["id"]), fmt.Sprint(i+1)) + file := itemMap["file"].(graphql.Upload) + require.Equal(t, "a.txt", file.Filename) + require.Equal(t, int64(len("test1")), file.Size) + _, err = file.File.Seek(0, 0) + require.Nil(t, err) + content, err := ioutil.ReadAll(file.File) + require.Nil(t, err) + require.Equal(t, "test1", string(content)) + } + }) } func TestAddUploadToOperations(t *testing.T) {