Skip to content

Commit

Permalink
Fake Data generator (#33)
Browse files Browse the repository at this point in the history
* Added base fake data generator

* Added array generator

* Added valdiator

* created fake data prototype

* Fixed tests

* Added validator tests

* Updated sonar properties

* Added tests for validator

* Fixed seeding

* Added test for handler

* Added options tests

* Added test for response

* Improve tets

* Added tests for validator

* Added tests for fake data list

* Updated response validator

* Updated fake node validator

* Added docs generator

* Updated tests

* Cleanup data

* Added numbers

* Added groups to the generator

* Configurare base data

* Added full correct options to generate data

* Cleanup data
  • Loading branch information
evg4b committed Sep 22, 2024
1 parent 161af3c commit 1f3d952
Show file tree
Hide file tree
Showing 31 changed files with 4,281 additions and 47 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ coverage.out
.DS_Store
uncors
!uncors/
tools/fakedata/scheme.json
tools/fakedata/docs.md
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.22.2
require (
github.com/PuerkitoBio/purell v1.2.1
github.com/bmatcuk/doublestar/v4 v4.6.1
github.com/brianvoe/gofakeit/v7 v7.0.4
github.com/charmbracelet/lipgloss v0.13.0
github.com/charmbracelet/log v0.4.0
github.com/deckarep/golang-set/v2 v2.6.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/brianvoe/gofakeit/v7 v7.0.4 h1:Mkxwz9jYg8Ad8NvT9HA27pCMZGFQo08MK6jD0QTKEww=
github.com/brianvoe/gofakeit/v7 v7.0.4/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA=
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
Expand Down
6 changes: 5 additions & 1 deletion internal/config/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ func URLMappingHookFunc() mapstructure.DecodeHookFunc {
}

mapping := Mapping{}
err := decodeConfig(data, &mapping, StaticDirMappingHookFunc())
err := decodeConfig(
data,
&mapping,
StaticDirMappingHookFunc(),
)

return mapping, err
}
Expand Down
18 changes: 17 additions & 1 deletion internal/config/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ package config
import (
"time"

"github.com/evg4b/uncors/pkg/fakedata"

"github.com/evg4b/uncors/internal/helpers"
)

type Response struct {
Code int `mapstructure:"code"`
Headers map[string]string `mapstructure:"headers"`
Delay time.Duration `mapstructure:"delay"`
Raw string `mapstructure:"raw"`
File string `mapstructure:"file"`
Delay time.Duration `mapstructure:"delay"`
Fake *fakedata.Node `mapstructure:"fake"`
}

func (r *Response) Clone() Response {
Expand All @@ -21,5 +24,18 @@ func (r *Response) Clone() Response {
Raw: r.Raw,
File: r.File,
Delay: r.Delay,
Fake: r.Fake,
}
}

func (r *Response) IsRaw() bool {
return len(r.Raw) > 0
}

func (r *Response) IsFile() bool {
return len(r.File) > 0
}

func (r *Response) IsFake() bool {
return r.Fake != nil
}
61 changes: 61 additions & 0 deletions internal/config/response_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"testing"
"time"

"github.com/evg4b/uncors/pkg/fakedata"

"github.com/evg4b/uncors/internal/config"
"github.com/go-http-utils/headers"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -35,4 +37,63 @@ func TestResponseClone(t *testing.T) {
t.Run("not same Headers map", func(t *testing.T) {
assert.NotSame(t, &response.Headers, &clonedResponse.Headers)
})

t.Run("response type", func(t *testing.T) {
t.Run("raw response", func(t *testing.T) {
response := config.Response{
Code: http.StatusOK,
Raw: "this is plain text",
}

t.Run("IsRaw", func(t *testing.T) {
assert.True(t, response.IsRaw())
})

t.Run("IsFile", func(t *testing.T) {
assert.False(t, response.IsFile())
})

t.Run("IsFake", func(t *testing.T) {
assert.False(t, response.IsFake())
})
})

t.Run("file response", func(t *testing.T) {
response := config.Response{
Code: http.StatusOK,
File: "~/projects/uncors/response/demo.json",
}

t.Run("IsRaw", func(t *testing.T) {
assert.False(t, response.IsRaw())
})

t.Run("IsFile", func(t *testing.T) {
assert.True(t, response.IsFile())
})

t.Run("IsFake", func(t *testing.T) {
assert.False(t, response.IsFake())
})
})

t.Run("file response", func(t *testing.T) {
response := config.Response{
Code: http.StatusOK,
Fake: &fakedata.Node{Type: "sentence"},
}

t.Run("IsRaw", func(t *testing.T) {
assert.False(t, response.IsRaw())
})

t.Run("IsFile", func(t *testing.T) {
assert.False(t, response.IsFile())
})

t.Run("IsFake", func(t *testing.T) {
assert.True(t, response.IsFake())
})
})
})
}
23 changes: 23 additions & 0 deletions internal/config/validators/base/string_enum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package base

import (
"fmt"

"github.com/gobuffalo/validate"
)

type StringEnumValidator struct {
Field string
Value string
Options []string
}

func (f *StringEnumValidator) IsValid(errors *validate.Errors) {
for _, option := range f.Options {
if f.Value == option {
return
}
}

errors.Add(f.Field, fmt.Sprintf("'%s' is not a valid option", f.Value))
}
43 changes: 43 additions & 0 deletions internal/config/validators/base/string_enum_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package base_test

import (
"testing"

"github.com/evg4b/uncors/internal/config/validators/base"
"github.com/gobuffalo/validate"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const (
option1 = "option-1"
option2 = "option-2"
)

func TestStringEnumValidator(t *testing.T) {
t.Run("valid option", func(t *testing.T) {
errors := validate.Validate(&base.StringEnumValidator{
Field: "field",
Value: option1,
Options: []string{
option1,
option2,
},
})

assert.False(t, errors.HasAny())
})

t.Run("valid option", func(t *testing.T) {
errors := validate.Validate(&base.StringEnumValidator{
Field: "field",
Value: "option-x",
Options: []string{
option1,
option2,
},
})

require.EqualError(t, errors, "'option-x' is not a valid option")
})
}
73 changes: 73 additions & 0 deletions internal/config/validators/fakedata_node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package validators

import (
"github.com/evg4b/uncors/internal/config/validators/base"
"github.com/evg4b/uncors/pkg/fakedata"
"github.com/gobuffalo/validate"
)

type FakedataNodeValidator struct {
Field string
Value *fakedata.Node
Root bool
}

func (c *FakedataNodeValidator) IsValid(errors *validate.Errors) {
errors.Append(validate.Validate(&base.StringEnumValidator{
Field: joinPath(c.Field, "type"),
Value: c.Value.Type,
Options: fakedata.GetTypes(),
}))

if !c.Root && c.Value.Seed != uint64(0) {
errors.Add(joinPath(c.Field, "seed"), "property 'seed' is not allowed in nested nodes")
}

if c.Value.Type == "object" {
c.validateAsObject(errors)
}

if c.Value.Type == "array" {
c.validateAsArray(errors)
}
}

func (c *FakedataNodeValidator) validateAsArray(errors *validate.Errors) {
if c.Value.Properties != nil {
errors.Add(joinPath(c.Field, "properties"), "property 'properties' is not allowed for array nodes")
}

if c.Value.Item == nil {
errors.Add(joinPath(c.Field, "item"), "property 'item' is required for array nodes")
} else {
errors.Append(validate.Validate(&FakedataNodeValidator{
Field: joinPath(c.Field, "item"),
Value: c.Value.Item,
}))
}

if c.Value.Count < 0 {
errors.Add(joinPath(c.Field, "count"), "property 'count' must be greater than or equal to 0")
}
}

func (c *FakedataNodeValidator) validateAsObject(errors *validate.Errors) {
if c.Value.Count != 0 {
errors.Add(joinPath(c.Field, "count"), "property 'count' is not allowed for object nodes")
}

if c.Value.Item != nil {
errors.Add(joinPath(c.Field, "item"), "property 'item' is not allowed for object nodes")
}

if c.Value.Options != nil {
errors.Add(joinPath(c.Field, "options"), "property 'options' is not allowed for object nodes")
}

for key, node := range c.Value.Properties {
errors.Append(validate.Validate(&FakedataNodeValidator{
Field: joinPath(c.Field, key),
Value: &node,
}))
}
}
Loading

0 comments on commit 1f3d952

Please sign in to comment.