diff --git a/examples/stubs.json b/examples/stubs.json new file mode 100644 index 0000000..0a3fa8c --- /dev/null +++ b/examples/stubs.json @@ -0,0 +1,37 @@ +[ + { + "method": "GET", + "path": "/", + "status": 200, + "response": { + "success": true + } + }, + { + "method": "GET", + "path": "/users", + "status": 200, + "response": { + "success": true, + "ids": [1, 2, 3] + } + }, + { + "method": "POST", + "path": "/users", + "status": 201, + "response": { + "success": true, + "id": 4 + } + }, + { + "method": "GET", + "path": "/admin", + "status": 401, + "response": { + "success": false, + "message": "unauthorized" + } + } +] \ No newline at end of file diff --git a/http/server.go b/http/server.go index f94869f..71cf286 100644 --- a/http/server.go +++ b/http/server.go @@ -30,7 +30,7 @@ func NewMux(schemas []localroast.Schema) Mux { method: schema.Method, path: schema.Path, } - mux[route] = schema.StatusCode + mux[route] = schema.Status } return mux } diff --git a/http/server_test.go b/http/server_test.go index e83e8b5..6552f76 100644 --- a/http/server_test.go +++ b/http/server_test.go @@ -20,19 +20,19 @@ func TestNewServer(t *testing.T) { func TestNewMux(t *testing.T) { schemas := []localroast.Schema{ localroast.Schema{ - Method: "GET", - Path: "/", - StatusCode: 200, + Method: "GET", + Path: "/", + Status: 200, }, localroast.Schema{ - Method: "GET", - Path: "/users", - StatusCode: 200, + Method: "GET", + Path: "/users", + Status: 200, }, localroast.Schema{ - Method: "POST", - Path: "/users", - StatusCode: 201, + Method: "POST", + Path: "/users", + Status: 201, }, } @@ -52,7 +52,7 @@ func TestNewMux(t *testing.T) { } assert.Nil(t, err) - assert.Equal(t, schema.StatusCode, resp.StatusCode) + assert.Equal(t, schema.Status, resp.StatusCode) } resp, err = http.Get(server.URL + "/unknown") diff --git a/localroast.go b/localroast.go index 86efd5c..23771be 100644 --- a/localroast.go +++ b/localroast.go @@ -1,7 +1,7 @@ package localroast type Schema struct { - Method string - Path string - StatusCode int + Method string + Path string + Status int } diff --git a/schema/json.go b/schema/json.go new file mode 100644 index 0000000..c0d4f9b --- /dev/null +++ b/schema/json.go @@ -0,0 +1,61 @@ +package schema + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "strings" + + "github.com/caalberts/localroast" +) + +func FromJSON(filepath string) ([]localroast.Schema, error) { + f, err := ioutil.ReadFile(filepath) + if err != nil { + return []localroast.Schema{}, err + } + return BytesToSchema(f) +} + +type stub struct { + Method *string `json:"method"` + Path *string `json:"path"` + Status *int `json:"status"` + Response json.RawMessage `json:"response"` +} + +func BytesToSchema(bytes []byte) ([]localroast.Schema, error) { + var stubs []stub + err := json.Unmarshal(bytes, &stubs) + if err != nil { + return []localroast.Schema{}, err + } + + schemas := make([]localroast.Schema, len(stubs)) + for i, stub := range stubs { + if f := missingFields(stub); len(f) > 0 { + return []localroast.Schema{}, fmt.Errorf("Missing required fields: %s", strings.Join(f, ", ")) + } + schemas[i] = localroast.Schema{ + Method: *stub.Method, + Path: *stub.Path, + Status: *stub.Status, + } + } + + return schemas, nil +} + +func missingFields(s stub) []string { + var missingFields []string + if s.Method == nil { + missingFields = append(missingFields, "method") + } + if s.Path == nil { + missingFields = append(missingFields, "path") + } + if s.Status == nil { + missingFields = append(missingFields, "status") + } + return missingFields +} diff --git a/schema/json_test.go b/schema/json_test.go new file mode 100644 index 0000000..c366de4 --- /dev/null +++ b/schema/json_test.go @@ -0,0 +1,84 @@ +package schema + +import ( + "io/ioutil" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +var validJSON, _ = ioutil.ReadFile("../examples/stubs.json") + +func TestBytesToSchema(t *testing.T) { + schemas, err := BytesToSchema(validJSON) + + assert.Nil(t, err) + assert.Equal(t, 4, len(schemas)) + + assert.Equal(t, http.MethodGet, schemas[0].Method) + assert.Equal(t, http.MethodGet, schemas[1].Method) + assert.Equal(t, http.MethodPost, schemas[2].Method) + assert.Equal(t, http.MethodGet, schemas[3].Method) + + assert.Equal(t, "/", schemas[0].Path) + assert.Equal(t, "/users", schemas[1].Path) + assert.Equal(t, "/users", schemas[2].Path) + assert.Equal(t, "/admin", schemas[3].Path) + + assert.Equal(t, http.StatusOK, schemas[0].Status) + assert.Equal(t, http.StatusOK, schemas[1].Status) + assert.Equal(t, http.StatusCreated, schemas[2].Status) + assert.Equal(t, http.StatusUnauthorized, schemas[3].Status) +} + +var missingKeys = ` +[ + { + "response": { + "success": true + } + } +] +` + +func TestJSONWithMissingKeys(t *testing.T) { + _, err := BytesToSchema([]byte(missingKeys)) + assert.NotNil(t, err) + assert.Equal(t, "Missing required fields: method, path, status", err.Error()) +} + +var invalidJSON = ` +[ + { + method: "GET", + path: "/", + status: 200, + response: { + "success": true + } + } +] +` + +func TestInvalidJSON(t *testing.T) { + _, err := BytesToSchema([]byte(invalidJSON)) + assert.NotNil(t, err) +} + +var jsonObject = ` +{ + "method": "POST", + "path": "/users", + "status": 201, + "response": { + "success": true, + "id": 4 + } +} +` + +func TestJSONObject(t *testing.T) { + _, err := BytesToSchema([]byte(jsonObject)) + assert.NotNil(t, err) +} diff --git a/schema/string.go b/schema/string.go index 60b466d..3826fbb 100644 --- a/schema/string.go +++ b/schema/string.go @@ -32,11 +32,11 @@ func FromString(definition string) (localroast.Schema, error) { method := matches[1] path := matches[2] - code, _ := strconv.Atoi(matches[3]) + status, _ := strconv.Atoi(matches[3]) schema := localroast.Schema{ - Method: method, - Path: path, - StatusCode: code, + Method: method, + Path: path, + Status: status, } return schema, nil } diff --git a/schema/string_test.go b/schema/string_test.go index dbbaea3..03e71f2 100644 --- a/schema/string_test.go +++ b/schema/string_test.go @@ -29,9 +29,9 @@ func TestFromStrings(t *testing.T) { assert.Equal(t, "/users", schemas[1].Path) assert.Equal(t, "/user/1", schemas[2].Path) - assert.Equal(t, http.StatusOK, schemas[0].StatusCode) - assert.Equal(t, http.StatusCreated, schemas[1].StatusCode) - assert.Equal(t, http.StatusForbidden, schemas[2].StatusCode) + assert.Equal(t, http.StatusOK, schemas[0].Status) + assert.Equal(t, http.StatusCreated, schemas[1].Status) + assert.Equal(t, http.StatusForbidden, schemas[2].Status) definitions = []string{ "GET / 200", @@ -48,25 +48,25 @@ var schemaTests = []struct { { "GET / 200", localroast.Schema{ - Method: http.MethodGet, - Path: "/", - StatusCode: http.StatusOK, + Method: http.MethodGet, + Path: "/", + Status: http.StatusOK, }, }, { "POST / 201", localroast.Schema{ - Method: http.MethodPost, - Path: "/", - StatusCode: http.StatusCreated, + Method: http.MethodPost, + Path: "/", + Status: http.StatusCreated, }, }, { "PUT /user/1 403", localroast.Schema{ - Method: http.MethodPut, - Path: "/user/1", - StatusCode: http.StatusForbidden, + Method: http.MethodPut, + Path: "/user/1", + Status: http.StatusForbidden, }, }, } @@ -77,7 +77,7 @@ func TestFromString(t *testing.T) { assert.Nil(t, err) assert.Equal(t, test.expected.Method, schema.Method) assert.Equal(t, test.expected.Path, schema.Path) - assert.Equal(t, test.expected.StatusCode, schema.StatusCode) + assert.Equal(t, test.expected.Status, schema.Status) } }