Adding in some mock examples

Noticed that I had missed something in the burgershop. Now that we can ‘see’ the spec, it’s going to open up a whole ton of new capabilities.

Signed-off-by: Quobix <dave@quobix.com>
This commit is contained in:
Quobix
2023-08-29 11:13:07 -04:00
committed by quobix
parent 8ae4603824
commit 9fb09f3a42
7 changed files with 166 additions and 20 deletions

View File

@@ -216,7 +216,7 @@ func TestNewDocument_Components_Schemas(t *testing.T) {
f := h.Components.Schemas["Fries"] f := h.Components.Schemas["Fries"]
assert.Equal(t, "salt", f.Schema().Properties["seasoning"].Schema().Items.A.Schema().Example) assert.Equal(t, "salt", f.Schema().Properties["seasoning"].Schema().Items.A.Schema().Example)
assert.Len(t, f.Schema().Properties["favoriteDrink"].Schema().Properties["drinkType"].Schema().Enum, 2) assert.Len(t, f.Schema().Properties["favoriteDrink"].Schema().Properties["drinkType"].Schema().Enum, 1)
d := h.Components.Schemas["Drink"] d := h.Components.Schemas["Drink"]
assert.Len(t, d.Schema().Required, 2) assert.Len(t, d.Schema().Required, 2)

View File

@@ -321,7 +321,7 @@ func ExampleCompareDocuments_openAPI() {
// Print out some interesting stats about the OpenAPI document changes. // Print out some interesting stats about the OpenAPI document changes.
fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.", fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.",
documentChanges.TotalChanges(), documentChanges.TotalBreakingChanges(), len(schemaChanges)) documentChanges.TotalChanges(), documentChanges.TotalBreakingChanges(), len(schemaChanges))
//Output: There are 72 changes, of which 17 are breaking. 5 schemas have changes. //Output: There are 75 changes, of which 19 are breaking. 6 schemas have changes.
} }

View File

@@ -44,8 +44,6 @@ func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) {
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
fieldName := v.Type().Field(i).Name fieldName := v.Type().Field(i).Name
switch fieldName { switch fieldName {
case Schema:
fieldCount++
case Example: case Example:
fieldCount++ fieldCount++
case Examples: case Examples:
@@ -54,12 +52,12 @@ func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) {
} }
mockReady := false mockReady := false
// check if all fields are present, if so, we can generate a mock // check if all fields are present, if so, we can generate a mock
if fieldCount == 3 { if fieldCount == 2 {
mockReady = true mockReady = true
} }
if !mockReady { if !mockReady {
return nil, fmt.Errorf("mockable struct only contains %d of the required "+ return nil, fmt.Errorf("mockable struct only contains %d of the required "+
"fields (%s, %s, %s)", fieldCount, Schema, Example, Examples) "fields (%s, %s)", fieldCount, Example, Examples)
} }
// if the value has an example, try and render it out as is. // if the value has an example, try and render it out as is.
@@ -70,29 +68,49 @@ func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) {
} }
// if there is no example, but there are multi-examples. // if there is no example, but there are multi-examples.
examplesValue := v.FieldByName(Examples).Interface() examples := v.FieldByName(Examples)
if examplesValue != nil { examplesValue := examples.Interface()
if examplesValue != nil && !examples.IsNil() {
// cast examples to map[string]interface{} // cast examples to map[string]interface{}
examples := examplesValue.(map[string]*highbase.Example) examplesMap := examplesValue.(map[string]*highbase.Example)
// if the name is not empty, try and find the example by name // if the name is not empty, try and find the example by name
for k, exp := range examples { for k, exp := range examplesMap {
if k == name { if k == name {
return mg.renderMock(exp.Value), nil return mg.renderMock(exp.Value), nil
} }
} }
// if the name is empty, just return the first example // if the name is empty, just return the first example
for _, exp := range examples { for _, exp := range examplesMap {
return mg.renderMock(exp.Value), nil return mg.renderMock(exp.Value), nil
} }
} }
// no examples? no problem, we can try and generate a mock from the schema. // no examples? no problem, we can try and generate a mock from the schema.
schemaValue := v.FieldByName(Schema).Interface().(*highbase.SchemaProxy) // check if this is a SchemaProxy, if not, then see if it has a Schema, if not, then we can't generate a mock.
var schemaValue *highbase.Schema
switch reflect.TypeOf(mock) {
case reflect.TypeOf(&highbase.SchemaProxy{}):
schemaValue = mock.(*highbase.SchemaProxy).Schema()
case reflect.TypeOf(&highbase.Schema{}):
schemaValue = mock.(*highbase.Schema)
default:
if sv, ok := v.FieldByName(Schema).Interface().(*highbase.Schema); ok {
if sv != nil {
schemaValue = sv
}
}
if sv, ok := v.FieldByName(Schema).Interface().(*highbase.SchemaProxy); ok {
if sv != nil {
schemaValue = sv.Schema()
}
}
}
if schemaValue != nil { if schemaValue != nil {
renderMap := mg.renderer.RenderSchema(schemaValue.Schema()) renderMap := mg.renderer.RenderSchema(schemaValue)
if renderMap != nil { if renderMap != nil {
return mg.renderMock(renderMap), nil return mg.renderMock(renderMap), nil
} }

View File

@@ -0,0 +1,128 @@
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT
package renderer
import (
"fmt"
"github.com/pb33f/libopenapi"
"os"
)
func ExampleMockGenerator_generateBurgerMock_yaml() {
// create a new YAML mock generator
mg := NewMockGenerator(MockYAML)
burgerShop, _ := os.ReadFile("../test_specs/burgershop.openapi.yaml")
// create a new document from specification and build a v3 model.
document, _ := libopenapi.NewDocument(burgerShop)
v3Model, _ := document.BuildV3Model()
// create a mock of the Burger model
burgerModel := v3Model.Model.Components.Schemas["Burger"]
burger := burgerModel.Schema()
mock, err := mg.GenerateMock(burger, "")
if err != nil {
panic(err)
}
fmt.Println(string(mock))
// Output: name: Big Mac
//numPatties: 2
}
func ExampleMockGenerator_generateFriesMock_json() {
// create a new YAML mock generator
mg := NewMockGenerator(MockJSON)
burgerShop, _ := os.ReadFile("../test_specs/burgershop.openapi.yaml")
// create a new document from specification and build a v3 model.
document, _ := libopenapi.NewDocument(burgerShop)
v3Model, _ := document.BuildV3Model()
// create a mock of the Fries model
friesModel := v3Model.Model.Components.Schemas["Fries"]
fries := friesModel.Schema()
mock, err := mg.GenerateMock(fries, "")
if err != nil {
panic(err)
}
fmt.Println(string(mock))
// Output: {"favoriteDrink":{"drinkType":"coke","size":"M"},"potatoShape":"Crispy Shoestring"}
}
func ExampleMockGenerator_generateRequestMock_json() {
// create a new YAML mock generator
mg := NewMockGenerator(MockJSON)
burgerShop, _ := os.ReadFile("../test_specs/burgershop.openapi.yaml")
// create a new document from specification and build a v3 model.
document, _ := libopenapi.NewDocument(burgerShop)
v3Model, _ := document.BuildV3Model()
// create a mock of the burger request model, extracted from the operation directly.
burgerRequestModel := v3Model.Model.Paths.PathItems["/burgers"].Post.RequestBody.Content["application/json"]
// use the 'cakeBurger' example to generate a mock
mock, err := mg.GenerateMock(burgerRequestModel, "cakeBurger")
if err != nil {
panic(err)
}
fmt.Println(string(mock))
// Output: {"name":"Chocolate Cake Burger","numPatties":5}
}
func ExampleMockGenerator_generateResponseMock_json() {
mg := NewMockGenerator(MockJSON)
// create a new YAML mock generator
burgerShop, _ := os.ReadFile("../test_specs/burgershop.openapi.yaml")
// create a new document from specification and build a v3 model.
document, _ := libopenapi.NewDocument(burgerShop)
v3Model, _ := document.BuildV3Model()
// create a mock of the burger response model, extracted from the operation directly.
burgerResponseModel := v3Model.Model.Paths.PathItems["/burgers"].Post.Responses.Codes["200"].Content["application/json"]
// use the 'filetOFish' example to generate a mock
mock, err := mg.GenerateMock(burgerResponseModel, "filetOFish")
if err != nil {
panic(err)
}
fmt.Println(string(mock))
// Output: {"name":"Filet-O-Fish","numPatties":1}
}
func ExampleMockGenerator_generatePolymorphicMock_json() {
mg := NewMockGenerator(MockJSON)
// create a new YAML mock generator
burgerShop, _ := os.ReadFile("../test_specs/burgershop.openapi.yaml")
// create a new document from specification and build a v3 model.
document, _ := libopenapi.NewDocument(burgerShop)
v3Model, _ := document.BuildV3Model()
// create a mock of the SomePayload component, which uses polymorphism (incorrectly)
payloadModel := v3Model.Model.Components.Schemas["SomePayload"]
payload := payloadModel.Schema()
mock, err := mg.GenerateMock(payload, "")
if err != nil {
panic(err)
}
fmt.Println(string(mock))
// Output: {"drinkType":"coke","size":"M"}
}

View File

@@ -503,10 +503,10 @@ components:
ice: ice:
type: boolean type: boolean
drinkType: drinkType:
type: string
description: select from coke or sprite description: select from coke or sprite
enum: enum:
- coke - coke
- sprite
size: size:
type: string type: string
description: what size man? S/M/L description: what size man? S/M/L
@@ -517,7 +517,7 @@ components:
mapping: mapping:
drink: some value drink: some value
SomePayload: SomePayload:
type: string type: object
description: some kind of payload for something. description: some kind of payload for something.
xml: xml:
name: is html programming? yes. name: is html programming? yes.

View File

@@ -33,6 +33,6 @@ func TestCreateSummary_OverallReport(t *testing.T) {
assert.Equal(t, 2, report.ChangeReport[v3.ServersLabel].Total) assert.Equal(t, 2, report.ChangeReport[v3.ServersLabel].Total)
assert.Equal(t, 1, report.ChangeReport[v3.ServersLabel].Breaking) assert.Equal(t, 1, report.ChangeReport[v3.ServersLabel].Breaking)
assert.Equal(t, 1, report.ChangeReport[v3.SecurityLabel].Total) assert.Equal(t, 1, report.ChangeReport[v3.SecurityLabel].Total)
assert.Equal(t, 17, report.ChangeReport[v3.ComponentsLabel].Total) assert.Equal(t, 20, report.ChangeReport[v3.ComponentsLabel].Total)
assert.Equal(t, 6, report.ChangeReport[v3.ComponentsLabel].Breaking) assert.Equal(t, 8, report.ChangeReport[v3.ComponentsLabel].Breaking)
} }

View File

@@ -24,8 +24,8 @@ func TestCompareOpenAPIDocuments(t *testing.T) {
modDoc, _ := v3.CreateDocument(infoMod) modDoc, _ := v3.CreateDocument(infoMod)
changes := CompareOpenAPIDocuments(origDoc, modDoc) changes := CompareOpenAPIDocuments(origDoc, modDoc)
assert.Equal(t, 72, changes.TotalChanges()) assert.Equal(t, 75, changes.TotalChanges())
assert.Equal(t, 17, changes.TotalBreakingChanges()) assert.Equal(t, 19, changes.TotalBreakingChanges())
//out, _ := json.MarshalIndent(changes, "", " ") //out, _ := json.MarshalIndent(changes, "", " ")
//_ = ioutil.WriteFile("outputv3.json", out, 0776) //_ = ioutil.WriteFile("outputv3.json", out, 0776)
} }
@@ -149,5 +149,5 @@ func ExampleCompareOpenAPIDocuments() {
// Print out some interesting stats. // Print out some interesting stats.
fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.", fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.",
changes.TotalChanges(), changes.TotalBreakingChanges(), len(schemaChanges)) changes.TotalChanges(), changes.TotalBreakingChanges(), len(schemaChanges))
//Output: There are 72 changes, of which 17 are breaking. 5 schemas have changes. //Output: There are 75 changes, of which 19 are breaking. 6 schemas have changes.
} }