From 7572a609252466122cb59a0071a848cdf40f48b6 Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 20:51:39 +0900 Subject: [PATCH 1/8] chore: Add Editor and IDE files to .gitignore --- .gitignore | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.gitignore b/.gitignore index 3b735ec..f273cac 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,15 @@ # Go workspace file go.work + +# macOS +.DS_Store + +# VS Code +.vscode + +# IntelliJ +.idea + +# vim +*.swp From bd59660163a03588dc0b63f30a1954843df33c0a Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 20:52:23 +0900 Subject: [PATCH 2/8] chore: Install testify for test --- go.mod | 8 ++++++++ go.sum | 10 ++++++++++ 2 files changed, 18 insertions(+) create mode 100644 go.sum diff --git a/go.mod b/go.mod index 39ed6f4..c6b7671 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,11 @@ module github.com/raksul/go-testclient go 1.21.0 + +require github.com/stretchr/testify v1.8.4 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..fa4b6e6 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 2784e53767d2e7f2598902ffad87a6f58e33a0c3 Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 20:52:59 +0900 Subject: [PATCH 3/8] test: Add tests for client.go --- client_test.go | 266 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 client_test.go diff --git a/client_test.go b/client_test.go new file mode 100644 index 0000000..9ddb483 --- /dev/null +++ b/client_test.go @@ -0,0 +1,266 @@ +package testclient + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +type TestHandler struct { + Path string + Method string + Response string + StatusCode int + Middleware func(t *testing.T, w http.ResponseWriter, r *http.Request) +} + +func createTestServer(t *testing.T, handlers []TestHandler) http.Handler { + mux := http.NewServeMux() + + for _, h := range handlers { + handler := h // For closure + mux.HandleFunc(handler.Path, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, handler.Method, r.Method) + + if handler.Middleware != nil { + handler.Middleware(t, w, r) + } + + w.WriteHeader(handler.StatusCode) + _, _ = w.Write([]byte(handler.Response)) + }) + } + + return mux +} + +func TestClient_New(t *testing.T) { + server := http.NewServeMux() + client := New(server) + assert.NotNil(t, client) +} + +func TestClient_Request(t *testing.T) { + type want struct { + code int + body string + } + tests := []struct { + name string + path string + method string + handlers []TestHandler + want want + }{ + { + name: "When request is GET", + path: "/get", + method: http.MethodGet, + handlers: []TestHandler{ + { + Path: "/get", + Method: http.MethodGet, + StatusCode: http.StatusOK, + Response: "ok", + }, + }, + want: want{ + code: http.StatusOK, + body: "ok", + }, + }, + { + name: "When request is POST", + path: "/post", + method: http.MethodPost, + handlers: []TestHandler{ + { + Path: "/post", + Method: http.MethodPost, + StatusCode: http.StatusOK, + Response: "ok", + }, + }, + want: want{ + code: http.StatusOK, + body: "ok", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + server := createTestServer(t, tt.handlers) + client := New(server) + req := httptest.NewRequest(tt.method, tt.path, nil) + client.Request(req) + res := client.Response() + + assert.Equal(t, tt.want.code, res.StatusCode) + + body, _ := io.ReadAll(res.Body) + assert.Equal(t, tt.want.body, string(body)) + }) + } +} + +func TestClient_PostForm(t *testing.T) { + type want struct { + code int + body string + } + tests := []struct { + name string + path string + params map[string]string + handlers []TestHandler + want want + }{ + { + name: "When request has some parameters", + path: "/post", + params: map[string]string{ + "key1": "value1", + "key2": "value2", + }, + handlers: []TestHandler{ + { + Path: "/post", + Method: http.MethodPost, + StatusCode: http.StatusOK, + Response: "ok", + Middleware: func(t *testing.T, w http.ResponseWriter, r *http.Request) { + contentType := r.Header.Get("Content-Type") + assert.Equal(t, "application/x-www-form-urlencoded", contentType) + + err := r.ParseForm() + assert.NoError(t, err) + + assert.Equal(t, "value1", r.PostFormValue("key1")) + assert.Equal(t, "value2", r.PostFormValue("key2")) + }, + }, + }, + want: want{ + code: http.StatusOK, + body: "ok", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + server := createTestServer(t, tt.handlers) + client := New(server) + client.PostForm(tt.path, tt.params) + res := client.Response() + + assert.Equal(t, tt.want.code, res.StatusCode) + + body, _ := io.ReadAll(res.Body) + assert.Equal(t, tt.want.body, string(body)) + }) + } +} + +func TestClient_FollowRedirect(t *testing.T) { + type want struct { + code int + body string + } + tests := []struct { + name string + path string + params map[string]string + handlers []TestHandler + want want + wantErr bool + }{ + { + name: "When redirect with cookie", + path: "/redirect", + handlers: []TestHandler{ + { + Path: "/redirect", + Method: http.MethodGet, + StatusCode: http.StatusFound, + Middleware: func(t *testing.T, w http.ResponseWriter, r *http.Request) { + http.SetCookie(w, &http.Cookie{ + Name: "cookie", + Value: "candy", + }) + http.Redirect(w, r, "/target", http.StatusFound) + }, + }, + { + Path: "/target", + Method: http.MethodGet, + Response: "ok", + StatusCode: http.StatusOK, + Middleware: func(t *testing.T, w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie("cookie") + assert.NoError(t, err) + assert.Equal(t, "candy", cookie.Value) + }, + }, + }, + want: want{ + code: http.StatusOK, + body: "ok", + }, + wantErr: false, + }, + { + name: "When no redirect", + path: "/no-redirect", + handlers: []TestHandler{ + { + Path: "/no-redirect", + Method: http.MethodGet, + Response: "ok", + StatusCode: http.StatusOK, + }, + }, + want: want{}, + wantErr: true, + }, + { + name: "When no location header", + path: "/no-location", + handlers: []TestHandler{ + { + Path: "/no-location", + Method: http.MethodGet, + Response: "ok", + StatusCode: http.StatusFound, + }, + }, + want: want{}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + server := createTestServer(t, tt.handlers) + client := New(server) + req := httptest.NewRequest(http.MethodGet, tt.path, nil) + client.Request(req) + + err := client.FollowRedirect() + if tt.wantErr { + assert.Error(t, err) + return + } + + res := client.Response() + assert.Equal(t, tt.want.code, res.StatusCode) + + body, _ := io.ReadAll(res.Body) + assert.Equal(t, tt.want.body, string(body)) + }) + } +} From 914a1638983cb350f1ae9cb2b76450df04407163 Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 20:53:18 +0900 Subject: [PATCH 4/8] chore: Add Makefile for test command --- Makefile | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..830a30f --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +.PHONY: test +test: + go test ./... From 616a5b87ec9ec08441af46bcfed3cdd42d7c2aaf Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 20:54:24 +0900 Subject: [PATCH 5/8] chore: Add GitHub Actions setting file for CI test. --- .github/workflows/test.yml | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..4f91254 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,40 @@ +name: Test +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + go: [1.21, 1.20] + runs-on: ${{ matrix.os }} + + steps: + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + + - name: Check out code + uses: actions/checkout@v3 + + - name: Restore Go modules cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: go-${{ runner.os }}-${{ hashFiles('go.mod') }} + restore-keys: | + go-${{ runner.os }}- + + - name: Download dependencies + run: go mod download + + - name: Run tests + run: go test -race ./... + + - name: Build + run: go build -v ./... From 7e9d3b8990204de777ca019715a40c9043caaa5b Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 21:10:04 +0900 Subject: [PATCH 6/8] fix: Specify Go version as string --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4f91254..4a408f7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - go: [1.21, 1.20] + go: ["1.21", "1.20"] runs-on: ${{ matrix.os }} steps: From d10687ea9cac57a8b67b824811851a939b423b59 Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 21:16:08 +0900 Subject: [PATCH 7/8] chore: Change go version 1.21.0 to 1.20.0 --- go.mod | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c6b7671..ccfb892 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/raksul/go-testclient -go 1.21.0 +// Specify to the minimum version that is supported in testing. +// .github/workflows/test.yml +go 1.20.0 require github.com/stretchr/testify v1.8.4 From f3ec4b5f004bffb356103651f75e558264d4187b Mon Sep 17 00:00:00 2001 From: aki-nagai Date: Thu, 24 Aug 2023 21:22:48 +0900 Subject: [PATCH 8/8] fix: Remove the specification of the patch version for Go. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index ccfb892..7bb143d 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/raksul/go-testclient // Specify to the minimum version that is supported in testing. // .github/workflows/test.yml -go 1.20.0 +go 1.20 require github.com/stretchr/testify v1.8.4