diff --git a/renderer/mock_generator.go b/renderer/mock_generator.go index 4b058ff1..6ad29a5d 100644 --- a/renderer/mock_generator.go +++ b/renderer/mock_generator.go @@ -6,12 +6,11 @@ package renderer import ( "encoding/json" "fmt" - "reflect" - "strconv" - highbase "github.com/pb33f/libopenapi/datamodel/high/base" "github.com/pb33f/libopenapi/orderedmap" "go.yaml.in/yaml/v4" + "reflect" + "strconv" ) const ( @@ -107,7 +106,25 @@ func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) { "fields (%s, %s)", fieldCount, Example, Examples) } - // if the value has an example, try and render it out as is. + var fallbackExample *highbase.Example = nil + // trying to find a named example + examples := v.FieldByName(Examples) + examplesValue := examples.Interface() + if examplesValue != nil && !examples.IsNil() { + + // cast examples to *orderedmap.Map[string, *highbase.Example] + examplesMap := examplesValue.(*orderedmap.Map[string, *highbase.Example]) + if examplesMap.Len() > 0 { + if example, ok := examplesMap.Get(name); ok { + return mg.renderMock(example.Value), nil + } else { + //take the first example from the list + fallbackExample = examplesMap.Oldest().Value + } + } + } + + // looking for an inline example f := v.FieldByName(Example) if !f.IsNil() { // Pointer/Interface Shenanigans @@ -120,30 +137,14 @@ func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) { } } if ex != nil { - // try and serialize the example value + // try and serialize the example value (very hacky since ex can be anything) return mg.renderMock(ex), nil } } - // if there is no example, but there are multi-examples. - examples := v.FieldByName(Examples) - examplesValue := examples.Interface() - if examplesValue != nil && !examples.IsNil() { - - // cast examples to *orderedmap.Map[string, *highbase.Example] - examplesMap := examplesValue.(*orderedmap.Map[string, *highbase.Example]) - - // if the name is not empty, try and find the example by name - for k, exp := range examplesMap.FromOldest() { - if k == name { - return mg.renderMock(exp.Value), nil - } - } - - // if the name is empty, just return the first example - for exp := range examplesMap.ValuesFromOldest() { - return mg.renderMock(exp.Value), nil - } + // rendering fallback if it's not nil + if fallbackExample != nil { + return mg.renderMock(fallbackExample.Value), nil } // no examples? no problem, we can try and generate a mock from the schema. @@ -167,7 +168,7 @@ func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) { if schemaValue != nil { - // now lets check the schema for `Examples` and `Example` fields. + // now let's check the schema for `Examples` and `Example` fields. if schemaValue.Examples != nil { if name != "" { // try and convert the example to an integer diff --git a/renderer/mock_generator_test.go b/renderer/mock_generator_test.go index ea817252..b3a82a55 100644 --- a/renderer/mock_generator_test.go +++ b/renderer/mock_generator_test.go @@ -523,3 +523,77 @@ properties: // It should be different from the first two assert.NotEqual(t, string(mock1), string(mock3)) } + +func TestMockGenerator_GenerateMock_PickNamedExample(t *testing.T) { + mg := NewMockGenerator(YAML) + + type mockable struct { + Example *base.Example + Examples *orderedmap.Map[string, *base.Example] + } + + inlineExample := &base.Example{ + Value: utils.CreateStringNode("inline example"), + } + examples := orderedmap.New[string, *base.Example]() + examples.Set("exampleOne", &base.Example{ + Value: utils.CreateStringNode("example 1"), + }) + + mock, err := mg.GenerateMock(&mockable{ + Example: inlineExample, + Examples: examples, + }, "exampleOne") + assert.NoError(t, err) + assert.Equal(t, "example 1", strings.TrimSpace(string(mock))) +} + +func TestMockGenerator_GenerateMock_PickOldestExample(t *testing.T) { + mg := NewMockGenerator(YAML) + + type mockable struct { + Example any + Examples *orderedmap.Map[string, *base.Example] + } + + examples := orderedmap.New[string, *base.Example]() + examples.Set("exampleOne", &base.Example{ + Value: utils.CreateStringNode("example 1"), + }) + examples.Set("exampleTwo", &base.Example{ + Value: utils.CreateStringNode("example 2"), + }) + + mock, err := mg.GenerateMock(&mockable{ + Examples: examples, + }, "nonexisting example") + assert.NoError(t, err) + assert.Equal(t, "example 1", strings.TrimSpace(string(mock))) +} + +func TestMockGenerator_GenerateMock_GetInline(t *testing.T) { + mg := NewMockGenerator(YAML) + + type mockable struct { + Example any + Examples *orderedmap.Map[string, *base.Example] + } + inlineExample := &yaml.Node{ + Kind: yaml.ScalarNode, + Value: "inline example", + } + examples := orderedmap.New[string, *base.Example]() + examples.Set("exampleOne", &base.Example{ + Value: utils.CreateStringNode("example 1"), + }) + examples.Set("exampleTwo", &base.Example{ + Value: utils.CreateStringNode("example 2"), + }) + + mock, err := mg.GenerateMock(&mockable{ + Example: inlineExample, + Examples: examples, + }, "nonexisting example") + assert.NoError(t, err) + assert.Equal(t, "inline example", strings.TrimSpace(string(mock))) +}