Skip to content

Commit

Permalink
Refactor tests to use new framework
Browse files Browse the repository at this point in the history
In addition updates error code and message for not valid json payloads
  • Loading branch information
buger authored and asoorm committed Jan 31, 2018
1 parent 8b894fb commit 80c9ac8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 179 deletions.
4 changes: 2 additions & 2 deletions mw_validate_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ func (k *ValidateJSON) ProcessRequest(w http.ResponseWriter, r *http.Request, _
rCopy := copyRequest(r)
bodyBytes, err := ioutil.ReadAll(rCopy.Body)
if err != nil {
return err, http.StatusInternalServerError
return err, http.StatusBadRequest
}
defer rCopy.Body.Close()

schema := vPathMeta.ValidateWith

result, err := k.validate(bodyBytes, schema)
if err != nil {
return err, http.StatusInternalServerError
return fmt.Errorf("JSON parsing error: %v", err), http.StatusBadRequest
}

if !result.Valid() {
Expand Down
201 changes: 24 additions & 177 deletions mw_validate_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,13 @@ package main

import (
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"

"github.com/justinas/alice"

"github.com/TykTechnologies/tyk/user"
"github.com/TykTechnologies/tyk/apidef"
"github.com/TykTechnologies/tyk/test"
)

type res struct {
Error string
Code int
}

type fixture struct {
in string
out res
name string
}

var schema = `{
var testJsonSchema = `{
"title": "Person",
"type": "object",
"properties": {
Expand All @@ -44,165 +27,29 @@ var schema = `{
"required": ["firstName", "lastName"]
}`

var fixtures = []fixture{
{
in: `{"age":23, "firstName": "Harry"}`,
out: res{Error: `lastName: lastName is required`, Code: http.StatusUnprocessableEntity},
name: "missing field",
},
{
in: `{"age":23}`,
out: res{Error: `firstName: firstName is required, lastName: lastName is required`, Code: http.StatusUnprocessableEntity},
name: "missing two fields",
},
{
in: `{}`,
out: res{Error: `firstName: firstName is required, lastName: lastName is required`, Code: http.StatusUnprocessableEntity},
name: "empty object",
},
{
in: `[]`,
out: res{Error: `(root): Invalid type. Expected: object, given: array`, Code: http.StatusUnprocessableEntity},
name: "array",
},
{
in: `{"age":"23", "firstName": "Harry", "lastName": "Potter"}`,
out: res{Error: `age: Invalid type. Expected: integer, given: string`, Code: http.StatusUnprocessableEntity},
name: "wrong type",
},
{
in: `{"age":23, "firstName": "Harry", "lastName": "Potter"}`,
out: res{Error: `null`, Code: http.StatusOK},
name: "valid",
},
}

func getJsonPathGatewaySetup() string {

validateJSONPathGatewaySetup := `{
"api_id": "jsontest",
"definition": {
"location": "header",
"key": "version"
},
"auth": {"auth_header_name": "authorization"},
"version_data": {
"not_versioned": true,
"versions": {
"default": {
"name": "default",
"use_extended_paths": true,
"extended_paths": {
"validate_json": [{
"method": "POST",
"path": "me",
"validate_with": REPLACE_SCHEMA
}]
}
}
}
},
"proxy": {
"listen_path": "/validate/",
"target_url": "` + testHttpAny + `"
}
}`
validateJSONPathGatewaySetup = strings.Replace(validateJSONPathGatewaySetup, "REPLACE_SCHEMA", schema, 1)

return validateJSONPathGatewaySetup
}

func TestValidateJSON_validate(t *testing.T) {

for _, f := range fixtures {

t.Run(f.name, func(st *testing.T) {
vj := ValidateJSON{}

dat := map[string]interface{}{}

if err := json.Unmarshal([]byte(schema), &dat); err != nil {
t.Fatal(err)
}

res, err := vj.validate([]byte(f.in), dat)
if err != nil {
t.Fatal(err)
}

if !res.Valid() && f.out.Code != http.StatusUnprocessableEntity {
st.Fatal("Expected invalid")
}

if res.Valid() && f.out.Code != http.StatusOK {
t.Log(res.Errors())
st.Fatal("expected valid", res.Valid(), f.out.Code)
}
})
}
}

func TestValidateJSON_ProcessRequest(t *testing.T) {

for _, f := range fixtures {

t.Run(f.name, func(st *testing.T) {

spec := createSpecTest(st, getJsonPathGatewaySetup())
recorder := httptest.NewRecorder()
req := testReq(t, "POST", "/validate/me", f.in)

session := createJSONVersionedSession()
spec.SessionManager.UpdateSession("986968696869688869696999", session, 60)
req.Header.Set("Authorization", "986968696869688869696999")

chain := getJSONValidChain(spec)
chain.ServeHTTP(recorder, req)

if recorder.Code != f.out.Code {
st.Errorf("failed: %v, code: %v (body: %v)", req.URL.String(), recorder.Code, recorder.Body)
}

if f.out.Code == http.StatusUnprocessableEntity {
recorderBody := recorder.Body.String()
if !strings.Contains(recorderBody, f.out.Error) {
st.Errorf("Incorrect error msg:\nwant: %v\ngot: %v", f.out.Error, recorderBody)
func TestValidateJSONSchema(t *testing.T) {
ts := newTykTestServer()
defer ts.Close()

buildAndLoadAPI(func(spec *APISpec) {
updateAPIVersion(spec, "v1", func(v *apidef.VersionInfo) {
json.Unmarshal([]byte(`[
{
"path": "/v",
"method": "POST",
"validate_with": `+testJsonSchema+`
}
}
]`), &v.ExtendedPaths.ValidateJSON)
})
}
}

func createJSONVersionedSession() *user.SessionState {
session := new(user.SessionState)
session.Rate = 10000
session.Allowance = session.Rate
session.LastCheck = time.Now().Unix()
session.Per = 60
session.Expires = -1
session.QuotaRenewalRate = 300 // 5 minutes
session.QuotaRenews = time.Now().Unix()
session.QuotaRemaining = 10
session.QuotaMax = -1
session.AccessRights = map[string]user.AccessDefinition{"jsontest": {APIName: "Tyk Test API", APIID: "jsontest", Versions: []string{"default"}}}
return session
}
spec.Proxy.ListenPath = "/"
})

func getJSONValidChain(spec *APISpec) http.Handler {
remote, _ := url.Parse(spec.Proxy.TargetURL)
proxy := TykNewSingleHostReverseProxy(remote, spec)
proxyHandler := ProxyHandler(proxy, spec)
baseMid := BaseMiddleware{spec, proxy}
chain := alice.New(mwList(
&IPWhiteListMiddleware{baseMid},
&MiddlewareContextVars{BaseMiddleware: baseMid},
&AuthKey{baseMid},
&VersionCheck{BaseMiddleware: baseMid},
&KeyExpired{baseMid},
&AccessRightsCheck{baseMid},
&RateLimitAndQuotaCheck{baseMid},
&ValidateJSON{BaseMiddleware: baseMid},
&TransformHeaders{baseMid},
)...).Then(proxyHandler)
return chain
ts.Run(t, []test.TestCase{
{Method: "POST", Path: "/without_validation", Data: "{not_valid}", Code: 200},
{Method: "POST", Path: "/v", Data: `{"age":23}`, BodyMatch: `firstName: firstName is required, lastName: lastName is required`, Code: 422},
{Method: "POST", Path: "/v", Data: `[]`, BodyMatch: `Expected: object, given: array`, Code: 422},
{Method: "POST", Path: "/v", Data: `not_json`, Code: 400},
{Method: "POST", Path: "/v", Data: `{"age":23, "firstName": "Harry", "lastName": "Potter"}`, Code: 200},
}...)
}

0 comments on commit 80c9ac8

Please sign in to comment.