Skip to content

Commit

Permalink
Implement tests and usages
Browse files Browse the repository at this point in the history
  • Loading branch information
ysyesilyurt committed Apr 3, 2021
1 parent e947f1a commit 2b7a28b
Show file tree
Hide file tree
Showing 3 changed files with 486 additions and 0 deletions.
105 changes: 105 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import (
"github.com/pkg/errors"
"go-restclient/restclient"
"log"
"net/http"
"net/url"
"time"
)

type dummyHttpResponse struct {
StatusCode int `json:"status_code"`
Data interface{} `json:"data"`
}

type dummyBasicAuthenticator struct {
Username, Password string
}

func NewTestBasicAuthenticator(username, password string) restclient.Authenticator {
return &dummyBasicAuthenticator{
Username: username,
Password: password,
}
}

func (b dummyBasicAuthenticator) Apply(request *http.Request) error {
request.SetBasicAuth(b.Username, b.Password)
return nil
}

func usage1() error {
var response dummyHttpResponse
headers := http.Header{"Content-Type": []string{"application/json"}, "Cookie": []string{"test-1234"}}
queryParams := url.Values{"tenantId": []string{"d90c3101-53bc-4c54-94db-21582bab8e17"}, "vectorId": []string{"1"}}
ri := restclient.NewRequestInfo("https", "ysyesilyurt.com", []string{"tasks", "1"}, &queryParams, &headers, nil)
req, err := restclient.NewRequest(ri)
if err != nil {
return errors.Wrap(err, "Failed to construct http.Request out of RequestInfo")
}

client := restclient.NewHttpClient(true, 30*time.Second)
cri := restclient.NewDoRequestInfo(req, nil, &response)
err = client.Get(cri)
if err != nil {
return errors.Wrap(err, "Failed to do HTTP GET request")
}
return nil
}

func usage2() error {
var response dummyHttpResponse
headers := http.Header{"Content-Type": []string{"application/json"}, "Cookie": []string{"test-1234"}}
ri, err := restclient.NewRequestInfoFromRawURL("https://ysyesilyurt.com/tasks/1?tenantId=d90c3101-53bc-4c54-94db-21582bab8e17&vectorId=1", &headers, nil)
if err != nil {
return errors.Wrap(err, "Failed to construct RequestInfo out of Raw URL")
}

req, err := restclient.NewRequest(ri)
if err != nil {
return errors.Wrap(err, "Failed to construct http.Request out of RequestInfo")
}

client := restclient.NewHttpClient(true, 0)
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
cri := restclient.NewDoRequestInfoWithTimeout(req, auth, &response, 15*time.Second)
err = client.Get(cri)
if err != nil {
return errors.Wrap(err, "Failed to do HTTP GET request")
}
return nil
}

func usage3() error {
var response dummyHttpResponse
headers := http.Header{"Content-Type": []string{"application/json"}, "Cookie": []string{"test-1234"}}
ri, err := restclient.NewRequestInfoFromRawURL("https://ysyesilyurt.com/tasks/1?tenantId=d90c3101-53bc-4c54-94db-21582bab8e17&vectorId=1", &headers, nil)
if err != nil {
return errors.Wrap(err, "Failed to construct RequestInfo out of Raw URL")
}

auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
err = restclient.PerformGetRequest(ri, auth, &response, true, 30*time.Second)
if err != nil {
return errors.Wrap(err, "Failed to perform HTTP GET request")
}
return nil
}

func main() {
// Below usages will fail with `no such host` when run
err := usage1()
if err != nil {
log.Printf("Example usage1 failed, reason: %v", err)
}
err = usage2()
if err != nil {
log.Printf("Example usage2 failed, reason: %v", err)
}
err = usage3()
if err != nil {
log.Printf("Example usage3 failed, reason: %v", err)
}
}
253 changes: 253 additions & 0 deletions restclient/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
package restclient

import (
"encoding/json"
"fmt"
. "github.com/smartystreets/goconvey/convey"
"log"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)

const (
TestDataFormat = "%s - %s"
TestSuccess = "TestSuccess"
TestFailed = "TestFailed"
)

type testBasicAuthenticator struct {
Username, Password string
}

func NewTestBasicAuthenticator(username, password string) Authenticator {
return &testBasicAuthenticator{
Username: username,
Password: password,
}
}

func (b testBasicAuthenticator) Apply(request *http.Request) error {
request.SetBasicAuth(b.Username, b.Password)
return nil
}

type testRequestBody struct {
TestId int `json:"test_id"`
TestName string `json:"test_name"`
}

type testHttpResponse struct {
StatusCode int `json:"status_code"`
Data interface{} `json:"data"`
}

func TestHttpClientRequests(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var response testHttpResponse
w.Header().Set("Content-Type", "application/json")

handleRequest := func(reqMethod string, statusCode int, resultString string) {
username, password, ok := r.BasicAuth()
if !ok || username != "ysyesilyurt" || password != "0123" {
statusCode = http.StatusUnauthorized
resultString = TestFailed
}
response.StatusCode = statusCode
response.Data = fmt.Sprintf(TestDataFormat, resultString, reqMethod)
w.WriteHeader(statusCode)
}

handleRequestWithBody := func(reqMethod string) {
status := http.StatusOK
resultString := TestSuccess
var body testRequestBody
err := UnmarshalRequestBody(r, &body)
if err != nil || body.TestName != "Testing Request Body" || body.TestId != 123 {
status = http.StatusBadRequest
resultString = TestFailed
}
handleRequest(reqMethod, status, resultString)
}

switch r.Method {
case http.MethodGet:
handleRequest(http.MethodGet, http.StatusOK, TestSuccess)
case http.MethodPost:
handleRequestWithBody(http.MethodPost)
case http.MethodPut:
handleRequestWithBody(http.MethodPut)
case http.MethodPatch:
handleRequestWithBody(http.MethodPatch)
case http.MethodDelete:
handleRequest(http.MethodDelete, http.StatusOK, TestSuccess)
default:
response.StatusCode = http.StatusForbidden
response.Data = fmt.Sprintf(TestDataFormat, TestFailed, r.Method)
}
err := json.NewEncoder(w).Encode(response)
if err != nil {
log.Fatalf("httptest server failed to respond with testHttpResponse %v", err.Error())
}
}))
defer ts.Close()
// e.g. ts URL: http://127.0.0.1:63316
splittedURL := strings.Split(ts.URL, "://")
testServerScheme := splittedURL[0]
testServerHost := splittedURL[1]

Convey("TEST HTTP GET", t, func() {
var testResponse testHttpResponse
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, nil)
testRequest, err := NewRequest(testRequestInfo)
if err != nil {
log.Fatal("failed to construct testRequest")
}
client := NewHttpClient(true, 30*time.Second)
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
err = client.Get(cri)
Convey("Response should be fetched without any err and with proper Data", func() {
data, ok := testResponse.Data.(string)
So(err, ShouldBeNil)
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
So(ok, ShouldBeTrue)
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodGet))
})
})

Convey("TEST HTTP GET with failing authentication credentials", t, func() {
var testResponse testHttpResponse
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, nil)
testRequest, err := NewRequest(testRequestInfo)
if err != nil {
log.Fatal("failed to construct testRequest")
}
client := NewHttpClient(true, 30*time.Second)
auth := NewTestBasicAuthenticator("FAILING", "CREDENTIALS")
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
err = client.Get(cri)
Convey("Response should be fetched without any err and with proper Data", func() {
_, ok := testResponse.Data.(string)
So(ok, ShouldBeFalse)
So(testResponse.StatusCode, ShouldEqual, 0)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldEqual, fmt.Sprintf("{\"status_code\":%d,\"data\":\"%s\"}\n: %s", http.StatusUnauthorized, fmt.Sprintf(TestDataFormat, TestFailed, http.MethodGet), unauthorizedErr))
})
})

Convey("TEST HTTP POST with correct body", t, func() {
var testResponse testHttpResponse
testBody := testRequestBody{
TestId: 123,
TestName: "Testing Request Body",
}
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
testRequest, err := NewRequest(testRequestInfo)
if err != nil {
log.Fatal("failed to construct testRequest")
}
client := NewHttpClient(true, 30*time.Second)
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
err = client.Post(cri)
Convey("Response should be fetched without any err and with proper Data", func() {
data, ok := testResponse.Data.(string)
So(err, ShouldBeNil)
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
So(ok, ShouldBeTrue)
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodPost))
})
})

Convey("TEST HTTP POST with incorrect body", t, func() {
var testResponse testHttpResponse
testBody := "INCORRECT REQUEST BODY"
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
testRequest, err := NewRequest(testRequestInfo)
if err != nil {
log.Fatal("failed to construct testRequest")
}
client := NewHttpClient(true, 30*time.Second)
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
err = client.Post(cri)
Convey("Response should be fetched without any err and with proper Data", func() {
_, ok := testResponse.Data.(string)
So(ok, ShouldBeFalse)
So(testResponse.StatusCode, ShouldEqual, 0)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldEqual, fmt.Sprintf("{\"status_code\":%d,\"data\":\"%s\"}\n: %s", http.StatusBadRequest, fmt.Sprintf(TestDataFormat, TestFailed, http.MethodPost), badRequestErr))
})
})

Convey("TEST HTTP PUT with correct body", t, func() {
var testResponse testHttpResponse
testBody := testRequestBody{
TestId: 123,
TestName: "Testing Request Body",
}
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
testRequest, err := NewRequest(testRequestInfo)
if err != nil {
log.Fatal("failed to construct testRequest")
}
client := NewHttpClient(true, 30*time.Second)
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
err = client.Put(cri)
Convey("Response should be fetched without any err and with proper Data", func() {
data, ok := testResponse.Data.(string)
So(err, ShouldBeNil)
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
So(ok, ShouldBeTrue)
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodPut))
})
})

Convey("TEST HTTP PATCH with correct body", t, func() {
var testResponse testHttpResponse
testBody := testRequestBody{
TestId: 123,
TestName: "Testing Request Body",
}
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
testRequest, err := NewRequest(testRequestInfo)
if err != nil {
log.Fatal("failed to construct testRequest")
}
client := NewHttpClient(true, 30*time.Second)
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
err = client.Patch(cri)
Convey("Response should be fetched without any err and with proper Data", func() {
data, ok := testResponse.Data.(string)
So(err, ShouldBeNil)
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
So(ok, ShouldBeTrue)
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodPatch))
})
})

Convey("TEST HTTP DELETE", t, func() {
var testResponse testHttpResponse
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, nil)
testRequest, err := NewRequest(testRequestInfo)
if err != nil {
log.Fatal("failed to construct testRequest")
}
client := NewHttpClient(true, 30*time.Second)
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
err = client.Delete(cri)
Convey("Response should be fetched without any err and with proper Data", func() {
data, ok := testResponse.Data.(string)
So(err, ShouldBeNil)
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
So(ok, ShouldBeTrue)
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodDelete))
})
})
}
Loading

0 comments on commit 2b7a28b

Please sign in to comment.