mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-11 04:20:24 +00:00
Added docs, more tests and cleanup.
Signed-off-by: Quobix <dave@quobix.com>
This commit is contained in:
@@ -22,21 +22,47 @@ const (
|
|||||||
MockYAML
|
MockYAML
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MockGenerator is used to generate mocks for high-level mockable structs or *base.Schema pointers.
|
||||||
|
// The mock generator will attempt to generate a mock from a struct using the following fields:
|
||||||
|
// - Example: any type, this is the default example to use if no examples are present.
|
||||||
|
// - Examples: map[string]*base.Example, this is a map of examples keyed by name.
|
||||||
|
// - Schema: *base.SchemaProxy, this is the schema to use if no examples are present.
|
||||||
|
//
|
||||||
|
// The mock generator will attempt to generate a mock from a *base.Schema pointer.
|
||||||
|
// Use NewMockGenerator or NewMockGeneratorWithDictionary to create a new mock generator.
|
||||||
type MockGenerator struct {
|
type MockGenerator struct {
|
||||||
renderer *SchemaRenderer
|
renderer *SchemaRenderer
|
||||||
mockType MockType
|
mockType MockType
|
||||||
|
pretty bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMockGeneratorWithDictionary creates a new mock generator using a custom dictionary. This is useful if you want to
|
||||||
|
// use a custom dictionary to generate mocks. The location of a text file with one word per line is expected.
|
||||||
func NewMockGeneratorWithDictionary(dictionaryLocation string, mockType MockType) *MockGenerator {
|
func NewMockGeneratorWithDictionary(dictionaryLocation string, mockType MockType) *MockGenerator {
|
||||||
renderer := CreateRendererUsingDictionary(dictionaryLocation)
|
renderer := CreateRendererUsingDictionary(dictionaryLocation)
|
||||||
return &MockGenerator{renderer: renderer, mockType: mockType}
|
return &MockGenerator{renderer: renderer, mockType: mockType}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMockGenerator creates a new mock generator using the default dictionary. The default is located at /usr/share/dict/words
|
||||||
|
// on most systems. Windows users will need to use NewMockGeneratorWithDictionary to specify a custom dictionary.
|
||||||
func NewMockGenerator(mockType MockType) *MockGenerator {
|
func NewMockGenerator(mockType MockType) *MockGenerator {
|
||||||
renderer := CreateRendererUsingDefaultDictionary()
|
renderer := CreateRendererUsingDefaultDictionary()
|
||||||
return &MockGenerator{renderer: renderer, mockType: mockType}
|
return &MockGenerator{renderer: renderer, mockType: mockType}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPretty sets the pretty flag on the mock generator. If true, the mock will be rendered with indentation and newlines.
|
||||||
|
// If false, the mock will be rendered as a single line which is good for API responses. False is the default.
|
||||||
|
// This option only effects JSON mocks, there is no concept of pretty printing YAML.
|
||||||
|
func (mg *MockGenerator) SetPretty() {
|
||||||
|
mg.pretty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateMock generates a mock for a given high-level mockable struct. The mockable struct must contain the following fields:
|
||||||
|
// Example: any type, this is the default example to use if no examples are present.
|
||||||
|
// Examples: map[string]*base.Example, this is a map of examples keyed by name.
|
||||||
|
// Schema: *base.SchemaProxy, this is the schema to use if no examples are present.
|
||||||
|
// The name parameter is optional, if provided, the mock generator will attempt to find an example with the given name.
|
||||||
|
// If no name is provided, the first example will be used.
|
||||||
func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) {
|
func (mg *MockGenerator) GenerateMock(mock any, name string) ([]byte, error) {
|
||||||
v := reflect.ValueOf(mock).Elem()
|
v := reflect.ValueOf(mock).Elem()
|
||||||
num := v.NumField()
|
num := v.NumField()
|
||||||
@@ -130,7 +156,11 @@ func (mg *MockGenerator) renderMockJSON(v any) []byte {
|
|||||||
// determine the type, render properly.
|
// determine the type, render properly.
|
||||||
switch reflect.ValueOf(v).Kind() {
|
switch reflect.ValueOf(v).Kind() {
|
||||||
case reflect.Map, reflect.Slice, reflect.Array, reflect.Struct, reflect.Ptr:
|
case reflect.Map, reflect.Slice, reflect.Array, reflect.Struct, reflect.Ptr:
|
||||||
data, _ = json.Marshal(v)
|
if mg.pretty {
|
||||||
|
data, _ = json.MarshalIndent(v, "", " ")
|
||||||
|
} else {
|
||||||
|
data, _ = json.Marshal(v)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
data = []byte(fmt.Sprint(v))
|
data = []byte(fmt.Sprint(v))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ func TestMockGenerator_GenerateJSONMock_MultiExamples_NoName_JSON(t *testing.T)
|
|||||||
mg := NewMockGenerator(MockJSON)
|
mg := NewMockGenerator(MockJSON)
|
||||||
mock, err := mg.GenerateMock(fake, "JimmyJammyJimJams") // does not exist
|
mock, err := mg.GenerateMock(fake, "JimmyJammyJimJams") // does not exist
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "{\"fish-and-chips\":\"cod-and-chips-twice\"}", string(mock))
|
assert.NotEmpty(t, string(mock))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMockGenerator_GenerateJSONMock_MultiExamples_JSON(t *testing.T) {
|
func TestMockGenerator_GenerateJSONMock_MultiExamples_JSON(t *testing.T) {
|
||||||
@@ -170,6 +170,24 @@ func TestMockGenerator_GenerateJSONMock_MultiExamples_JSON(t *testing.T) {
|
|||||||
assert.Equal(t, "{\"rice-and-peas\":\"brown-or-white-rice\"}", string(mock))
|
assert.Equal(t, "{\"rice-and-peas\":\"brown-or-white-rice\"}", string(mock))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMockGenerator_GenerateJSONMock_MultiExamples_PrettyJSON(t *testing.T) {
|
||||||
|
fakeExample := map[string]any{
|
||||||
|
"exampleOne": map[string]any{
|
||||||
|
"fish-and-chips": "cod-and-chips-twice",
|
||||||
|
},
|
||||||
|
"exampleTwo": map[string]any{
|
||||||
|
"rice-and-peas": "brown-or-white-rice",
|
||||||
|
"peas": "buttery",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fake := createFakeMock(simpleFakeMockSchema, fakeExample, nil)
|
||||||
|
mg := NewMockGenerator(MockJSON)
|
||||||
|
mg.SetPretty()
|
||||||
|
mock, err := mg.GenerateMock(fake, "exampleTwo")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "{\n \"peas\": \"buttery\",\n \"rice-and-peas\": \"brown-or-white-rice\"\n}", string(mock))
|
||||||
|
}
|
||||||
|
|
||||||
func TestMockGenerator_GenerateJSONMock_MultiExamples_YAML(t *testing.T) {
|
func TestMockGenerator_GenerateJSONMock_MultiExamples_YAML(t *testing.T) {
|
||||||
fakeExample := map[string]any{
|
fakeExample := map[string]any{
|
||||||
"exampleOne": map[string]any{
|
"exampleOne": map[string]any{
|
||||||
|
|||||||
@@ -17,6 +17,34 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const rootType = "rootType"
|
||||||
|
const stringType = "string"
|
||||||
|
const numberType = "number"
|
||||||
|
const integerType = "integer"
|
||||||
|
const booleanType = "boolean"
|
||||||
|
const objectType = "object"
|
||||||
|
const arrayType = "array"
|
||||||
|
const int32Type = "int32"
|
||||||
|
const floatType = "float"
|
||||||
|
const doubleType = "double"
|
||||||
|
const byteType = "byte"
|
||||||
|
const binaryType = "binary"
|
||||||
|
const passwordType = "password"
|
||||||
|
const dateType = "date"
|
||||||
|
const dateTimeType = "date-time"
|
||||||
|
const timeType = "time"
|
||||||
|
const emailType = "email"
|
||||||
|
const hostnameType = "hostname"
|
||||||
|
const ipv4Type = "ipv4"
|
||||||
|
const ipv6Type = "ipv6"
|
||||||
|
const uriType = "uri"
|
||||||
|
const uriReferenceType = "uri-reference"
|
||||||
|
const uuidType = "uuid"
|
||||||
|
const allOfType = "allOf"
|
||||||
|
const anyOfType = "anyOf"
|
||||||
|
const oneOfType = "oneOf"
|
||||||
|
const itemsType = "items"
|
||||||
|
|
||||||
// used to generate random words if there is no dictionary applied.
|
// used to generate random words if there is no dictionary applied.
|
||||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
@@ -31,6 +59,8 @@ type SchemaRenderer struct {
|
|||||||
words []string
|
words []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateRendererUsingDictionary will create a new SchemaRenderer using a custom dictionary file.
|
||||||
|
// The location of a text file with one word per line is expected.
|
||||||
func CreateRendererUsingDictionary(dictionaryLocation string) *SchemaRenderer {
|
func CreateRendererUsingDictionary(dictionaryLocation string) *SchemaRenderer {
|
||||||
// try and read in the dictionary file
|
// try and read in the dictionary file
|
||||||
words := ReadDictionary(dictionaryLocation)
|
words := ReadDictionary(dictionaryLocation)
|
||||||
@@ -38,6 +68,8 @@ func CreateRendererUsingDictionary(dictionaryLocation string) *SchemaRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateRendererUsingDefaultDictionary will create a new SchemaRenderer using the default dictionary file.
|
// CreateRendererUsingDefaultDictionary will create a new SchemaRenderer using the default dictionary file.
|
||||||
|
// The default dictionary is located at /usr/share/dict/words on most systems.
|
||||||
|
// Windows users will need to use CreateRendererUsingDictionary to specify a custom dictionary.
|
||||||
func CreateRendererUsingDefaultDictionary() *SchemaRenderer {
|
func CreateRendererUsingDefaultDictionary() *SchemaRenderer {
|
||||||
wr := new(SchemaRenderer)
|
wr := new(SchemaRenderer)
|
||||||
wr.words = ReadDictionary("/usr/share/dict/words")
|
wr.words = ReadDictionary("/usr/share/dict/words")
|
||||||
@@ -48,8 +80,8 @@ func CreateRendererUsingDefaultDictionary() *SchemaRenderer {
|
|||||||
func (wr *SchemaRenderer) RenderSchema(schema *base.Schema) any {
|
func (wr *SchemaRenderer) RenderSchema(schema *base.Schema) any {
|
||||||
// dive into the schema and render it
|
// dive into the schema and render it
|
||||||
structure := make(map[string]any)
|
structure := make(map[string]any)
|
||||||
wr.DiveIntoSchema(schema, "root", structure, 0)
|
wr.DiveIntoSchema(schema, rootType, structure, 0)
|
||||||
return structure["root"].(any)
|
return structure[rootType].(any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiveIntoSchema will dive into a schema and inject values from examples into a map. If there are no examples in
|
// DiveIntoSchema will dive into a schema and inject values from examples into a map. If there are no examples in
|
||||||
@@ -69,7 +101,7 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
// render out a string.
|
// render out a string.
|
||||||
if slices.Contains(schema.Type, "string") {
|
if slices.Contains(schema.Type, stringType) {
|
||||||
// check for an enum, if there is one, then pick a random value from it.
|
// check for an enum, if there is one, then pick a random value from it.
|
||||||
if schema.Enum != nil && len(schema.Enum) > 0 {
|
if schema.Enum != nil && len(schema.Enum) > 0 {
|
||||||
structure[key] = schema.Enum[rand.Int()%len(schema.Enum)]
|
structure[key] = schema.Enum[rand.Int()%len(schema.Enum)]
|
||||||
@@ -87,43 +119,43 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch schema.Format {
|
switch schema.Format {
|
||||||
case "date-time":
|
case dateTimeType:
|
||||||
structure[key] = time.Now().Format(time.RFC3339)
|
structure[key] = time.Now().Format(time.RFC3339)
|
||||||
case "date":
|
case dateType:
|
||||||
structure[key] = time.Now().Format("2006-01-02")
|
structure[key] = time.Now().Format("2006-01-02")
|
||||||
case "time":
|
case timeType:
|
||||||
structure[key] = time.Now().Format("15:04:05")
|
structure[key] = time.Now().Format("15:04:05")
|
||||||
case "email":
|
case emailType:
|
||||||
structure[key] = fmt.Sprintf("%s@%s.com",
|
structure[key] = fmt.Sprintf("%s@%s.com",
|
||||||
wr.RandomWord(minLength, maxLength, 0),
|
wr.RandomWord(minLength, maxLength, 0),
|
||||||
wr.RandomWord(minLength, maxLength, 0))
|
wr.RandomWord(minLength, maxLength, 0))
|
||||||
case "hostname":
|
case hostnameType:
|
||||||
structure[key] = fmt.Sprintf("%s.com", wr.RandomWord(minLength, maxLength, 0))
|
structure[key] = fmt.Sprintf("%s.com", wr.RandomWord(minLength, maxLength, 0))
|
||||||
case "ipv4":
|
case ipv4Type:
|
||||||
structure[key] = fmt.Sprintf("%d.%d.%d.%d",
|
structure[key] = fmt.Sprintf("%d.%d.%d.%d",
|
||||||
rand.Int()%255, rand.Int()%255, rand.Int()%255, rand.Int()%255)
|
rand.Int()%255, rand.Int()%255, rand.Int()%255, rand.Int()%255)
|
||||||
case "ipv6":
|
case ipv6Type:
|
||||||
structure[key] = fmt.Sprintf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
|
structure[key] = fmt.Sprintf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
|
||||||
rand.Intn(65535), rand.Intn(65535), rand.Intn(65535), rand.Intn(65535),
|
rand.Intn(65535), rand.Intn(65535), rand.Intn(65535), rand.Intn(65535),
|
||||||
rand.Intn(65535), rand.Intn(65535), rand.Intn(65535), rand.Intn(65535),
|
rand.Intn(65535), rand.Intn(65535), rand.Intn(65535), rand.Intn(65535),
|
||||||
)
|
)
|
||||||
case "uri":
|
case uriType:
|
||||||
structure[key] = fmt.Sprintf("https://%s-%s-%s.com/%s",
|
structure[key] = fmt.Sprintf("https://%s-%s-%s.com/%s",
|
||||||
wr.RandomWord(minLength, maxLength, 0),
|
wr.RandomWord(minLength, maxLength, 0),
|
||||||
wr.RandomWord(minLength, maxLength, 0),
|
wr.RandomWord(minLength, maxLength, 0),
|
||||||
wr.RandomWord(minLength, maxLength, 0),
|
wr.RandomWord(minLength, maxLength, 0),
|
||||||
wr.RandomWord(minLength, maxLength, 0))
|
wr.RandomWord(minLength, maxLength, 0))
|
||||||
case "uri-reference":
|
case uriReferenceType:
|
||||||
structure[key] = fmt.Sprintf("/%s/%s",
|
structure[key] = fmt.Sprintf("/%s/%s",
|
||||||
wr.RandomWord(minLength, maxLength, 0),
|
wr.RandomWord(minLength, maxLength, 0),
|
||||||
wr.RandomWord(minLength, maxLength, 0))
|
wr.RandomWord(minLength, maxLength, 0))
|
||||||
case "uuid":
|
case uuidType:
|
||||||
structure[key] = wr.PseudoUUID()
|
structure[key] = wr.PseudoUUID()
|
||||||
case "byte":
|
case byteType:
|
||||||
structure[key] = fmt.Sprintf("%x", wr.RandomWord(minLength, maxLength, 0))
|
structure[key] = fmt.Sprintf("%x", wr.RandomWord(minLength, maxLength, 0))
|
||||||
case "password":
|
case passwordType:
|
||||||
structure[key] = fmt.Sprintf("%s", wr.RandomWord(minLength, maxLength, 0))
|
structure[key] = fmt.Sprintf("%s", wr.RandomWord(minLength, maxLength, 0))
|
||||||
case "binary":
|
case binaryType:
|
||||||
structure[key] = fmt.Sprintf("%s",
|
structure[key] = fmt.Sprintf("%s",
|
||||||
base64.StdEncoding.EncodeToString([]byte(wr.RandomWord(minLength, maxLength, 0))))
|
base64.StdEncoding.EncodeToString([]byte(wr.RandomWord(minLength, maxLength, 0))))
|
||||||
default:
|
default:
|
||||||
@@ -142,7 +174,7 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle numbers
|
// handle numbers
|
||||||
if slices.Contains(schema.Type, "number") || slices.Contains(schema.Type, "integer") {
|
if slices.Contains(schema.Type, numberType) || slices.Contains(schema.Type, integerType) {
|
||||||
|
|
||||||
if schema.Enum != nil && len(schema.Enum) > 0 {
|
if schema.Enum != nil && len(schema.Enum) > 0 {
|
||||||
structure[key] = schema.Enum[rand.Int()%len(schema.Enum)]
|
structure[key] = schema.Enum[rand.Int()%len(schema.Enum)]
|
||||||
@@ -159,11 +191,11 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch schema.Format {
|
switch schema.Format {
|
||||||
case "float":
|
case floatType:
|
||||||
structure[key] = rand.Float32()
|
structure[key] = rand.Float32()
|
||||||
case "double":
|
case doubleType:
|
||||||
structure[key] = rand.Float64()
|
structure[key] = rand.Float64()
|
||||||
case "int32":
|
case int32Type:
|
||||||
structure[key] = int(wr.RandomInt(minimum, maximum))
|
structure[key] = int(wr.RandomInt(minimum, maximum))
|
||||||
default:
|
default:
|
||||||
structure[key] = wr.RandomInt(minimum, maximum)
|
structure[key] = wr.RandomInt(minimum, maximum)
|
||||||
@@ -173,12 +205,12 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle booleans
|
// handle booleans
|
||||||
if slices.Contains(schema.Type, "boolean") {
|
if slices.Contains(schema.Type, booleanType) {
|
||||||
structure[key] = true
|
structure[key] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle objects
|
// handle objects
|
||||||
if slices.Contains(schema.Type, "object") {
|
if slices.Contains(schema.Type, objectType) {
|
||||||
properties := schema.Properties
|
properties := schema.Properties
|
||||||
propertyMap := make(map[string]any)
|
propertyMap := make(map[string]any)
|
||||||
|
|
||||||
@@ -206,8 +238,8 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
allOfMap := make(map[string]any)
|
allOfMap := make(map[string]any)
|
||||||
for _, allOfSchema := range allOf {
|
for _, allOfSchema := range allOf {
|
||||||
allOfCompiled := allOfSchema.Schema()
|
allOfCompiled := allOfSchema.Schema()
|
||||||
wr.DiveIntoSchema(allOfCompiled, "allOf", allOfMap, depth+1)
|
wr.DiveIntoSchema(allOfCompiled, allOfType, allOfMap, depth+1)
|
||||||
for k, v := range allOfMap["allOf"].(map[string]any) {
|
for k, v := range allOfMap[allOfType].(map[string]any) {
|
||||||
propertyMap[k] = v
|
propertyMap[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,8 +267,8 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
oneOfMap := make(map[string]any)
|
oneOfMap := make(map[string]any)
|
||||||
for _, oneOfSchema := range oneOf {
|
for _, oneOfSchema := range oneOf {
|
||||||
oneOfCompiled := oneOfSchema.Schema()
|
oneOfCompiled := oneOfSchema.Schema()
|
||||||
wr.DiveIntoSchema(oneOfCompiled, "oneOf", oneOfMap, depth+1)
|
wr.DiveIntoSchema(oneOfCompiled, oneOfType, oneOfMap, depth+1)
|
||||||
for k, v := range oneOfMap["oneOf"].(map[string]any) {
|
for k, v := range oneOfMap[oneOfType].(map[string]any) {
|
||||||
propertyMap[k] = v
|
propertyMap[k] = v
|
||||||
}
|
}
|
||||||
break // one run once for the first result.
|
break // one run once for the first result.
|
||||||
@@ -249,8 +281,8 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
anyOfMap := make(map[string]any)
|
anyOfMap := make(map[string]any)
|
||||||
for _, anyOfSchema := range anyOf {
|
for _, anyOfSchema := range anyOf {
|
||||||
anyOfCompiled := anyOfSchema.Schema()
|
anyOfCompiled := anyOfSchema.Schema()
|
||||||
wr.DiveIntoSchema(anyOfCompiled, "anyOf", anyOfMap, depth+1)
|
wr.DiveIntoSchema(anyOfCompiled, anyOfType, anyOfMap, depth+1)
|
||||||
for k, v := range anyOfMap["anyOf"].(map[string]any) {
|
for k, v := range anyOfMap[anyOfType].(map[string]any) {
|
||||||
propertyMap[k] = v
|
propertyMap[k] = v
|
||||||
}
|
}
|
||||||
break // one run once for the first result only, same as oneOf
|
break // one run once for the first result only, same as oneOf
|
||||||
@@ -260,7 +292,7 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if slices.Contains(schema.Type, "array") {
|
if slices.Contains(schema.Type, arrayType) {
|
||||||
|
|
||||||
// an array needs an items schema
|
// an array needs an items schema
|
||||||
itemsSchema := schema.Items
|
itemsSchema := schema.Items
|
||||||
@@ -280,8 +312,8 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
for i := int64(0); i < minItems; i++ {
|
for i := int64(0); i < minItems; i++ {
|
||||||
itemMap := make(map[string]any)
|
itemMap := make(map[string]any)
|
||||||
itemsSchemaCompiled := itemsSchema.A.Schema()
|
itemsSchemaCompiled := itemsSchema.A.Schema()
|
||||||
wr.DiveIntoSchema(itemsSchemaCompiled, "items", itemMap, depth+1)
|
wr.DiveIntoSchema(itemsSchemaCompiled, itemsType, itemMap, depth+1)
|
||||||
renderedItems = append(renderedItems, itemMap["items"])
|
renderedItems = append(renderedItems, itemMap[itemsType])
|
||||||
}
|
}
|
||||||
structure[key] = renderedItems
|
structure[key] = renderedItems
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -989,6 +989,36 @@ properties:
|
|||||||
assert.Equal(t, `{"name":"pb33f"}`, string(rendered))
|
assert.Equal(t, `{"name":"pb33f"}`, string(rendered))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderSchema_WithEnum_Float(t *testing.T) {
|
||||||
|
testObject := `type: [object]
|
||||||
|
properties:
|
||||||
|
count:
|
||||||
|
type: number
|
||||||
|
enum: [9934.223]`
|
||||||
|
|
||||||
|
compiled := getSchema([]byte(testObject))
|
||||||
|
schema := make(map[string]any)
|
||||||
|
wr := createSchemaRenderer()
|
||||||
|
wr.DiveIntoSchema(compiled, "pb33f", schema, 0)
|
||||||
|
rendered, _ := json.Marshal(schema["pb33f"])
|
||||||
|
assert.Equal(t, `{"count":9934.223}`, string(rendered))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderSchema_WithEnum_Integer(t *testing.T) {
|
||||||
|
testObject := `type: [object]
|
||||||
|
properties:
|
||||||
|
count:
|
||||||
|
type: number
|
||||||
|
enum: [9934]`
|
||||||
|
|
||||||
|
compiled := getSchema([]byte(testObject))
|
||||||
|
schema := make(map[string]any)
|
||||||
|
wr := createSchemaRenderer()
|
||||||
|
wr.DiveIntoSchema(compiled, "pb33f", schema, 0)
|
||||||
|
rendered, _ := json.Marshal(schema["pb33f"])
|
||||||
|
assert.Equal(t, `{"count":9934}`, string(rendered))
|
||||||
|
}
|
||||||
|
|
||||||
func TestCreateRendererUsingDefaultDictionary(t *testing.T) {
|
func TestCreateRendererUsingDefaultDictionary(t *testing.T) {
|
||||||
assert.NotNil(t, CreateRendererUsingDefaultDictionary())
|
assert.NotNil(t, CreateRendererUsingDefaultDictionary())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user