Skip to content
Snippets Groups Projects
Commit d04b3223 authored by Semyon Krestyaninov's avatar Semyon Krestyaninov :dog2:
Browse files

wip

parent d5ca1cdd
No related branches found
No related tags found
No related merge requests found
package executor
import (
"context"
"testing"
"git.perx.ru/perxis/perxis-go/pkg/schema/field"
"github.com/stretchr/testify/assert"
)
func TestCollectionFilterExecute(t *testing.T) {
tests := []struct {
name string
input CollectionFilter
want CollectionFilter
assertErr assert.ErrorAssertionFunc
}{
{
name: "empty",
input: CollectionFilter{},
want: CollectionFilter{},
assertErr: assert.NoError,
},
{
name: "simple id",
input: CollectionFilter{
ID: []string{
"{{ .data.id }}",
},
},
want: CollectionFilter{
ID: []string{
"adebcfg",
},
},
assertErr: assert.NoError,
},
{
name: "simple name",
input: CollectionFilter{
Name: []string{
"{{ .data.name }}",
},
},
want: CollectionFilter{
Name: []string{
"John",
},
},
assertErr: assert.NoError,
},
{
name: "simple tag",
input: CollectionFilter{
Tag: []string{
"{{ .data.layout }}",
},
},
want: CollectionFilter{
Tag: []string{
"post",
},
},
assertErr: assert.NoError,
},
{
name: "without template",
input: CollectionFilter{
Tag: []string{
"tag",
},
},
want: CollectionFilter{
Tag: []string{
"tag",
},
},
assertErr: assert.NoError,
},
{
name: "error function",
input: CollectionFilter{
Tag: []string{
`{{ error "some error" }}`,
},
},
want: CollectionFilter{},
assertErr: assert.NoError,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
exec := NewTemplateExecutor(map[string]any{
"data": map[string]any{
"id": "adebcfg",
"name": "John",
"layout": "post",
},
})
fld := field.String().AddOptions(tc.input)
err := Execute(context.Background(), fld, exec)
tc.assertErr(t, err)
want := field.String().AddOptions(tc.want)
assert.Equal(t, want, fld)
})
}
}
package executor
import (
"context"
"testing"
"git.perx.ru/perxis/perxis-go/pkg/schema/field"
"github.com/stretchr/testify/assert"
)
func TestItemFilter_Execute(t *testing.T) {
tests := []struct {
name string
input ItemFilter
want ItemFilter
assertErr assert.ErrorAssertionFunc
}{
{
name: "empty",
input: ItemFilter{},
want: ItemFilter{},
assertErr: assert.NoError,
},
{
name: "simple",
input: ItemFilter{
Query: []string{
`{{ .data.id }}`,
`first_name == "{{ .data.first_name }}"`,
`{{ .unknown }}`,
``,
},
},
want: ItemFilter{
Query: []string{
`adebcfg`,
`first_name == "John"`,
},
},
assertErr: assert.NoError,
},
{
name: "condition",
input: ItemFilter{
Query: []string{
`{{ if .data.first_name -}} first_name == "{{ .data.first_name }}" {{- end }}`,
`{{ if .data.last_name -}} last_name == "{{ .data.last_name }}" {{- else -}} first_name == "{{ .data.first_name }}" {{- end }}`,
},
},
want: ItemFilter{
Query: []string{
`first_name == "John"`,
`last_name == "Smith"`,
},
},
assertErr: assert.NoError,
},
{
name: "error function",
input: ItemFilter{
Query: []string{
`{{ .data.id }}`,
`{{ if .data.login -}} login == "{{ .data.login }}" {{- else }} {{ error "Пожалуйста, укажите значение для поля \"login\"" }} {{ end }}`,
},
QueryError: `{{ .Error }}`,
},
want: ItemFilter{
QueryError: `Пожалуйста, укажите значение для поля "login"`,
},
assertErr: assert.NoError,
},
{
name: "invalid template",
input: ItemFilter{
Query: []string{
`{{ if `,
},
},
want: ItemFilter{
Query: []string{
`{{ if `,
},
},
assertErr: assert.Error,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
exec := NewTemplateExecutor(map[string]any{
"data": map[string]any{
"id": "adebcfg",
"first_name": "John",
"last_name": "Smith",
},
})
fld := field.String().AddOptions(tc.input)
err := Execute(context.Background(), fld, exec)
tc.assertErr(t, err)
want := field.String().AddOptions(tc.want)
assert.Equal(t, want, fld)
})
}
}
package executor
import (
"bytes"
"context"
"sync"
"text/template"
"git.perx.ru/perxis/perxis-go/pkg/errors"
)
type TemplateExecutor struct {
env map[string]any
funcMap template.FuncMap
}
func NewTemplateExecutor(env map[string]any) *TemplateExecutor {
te := &TemplateExecutor{
env: env,
}
te.init()
return te
}
func (exec *TemplateExecutor) init() {
if exec.env == nil {
exec.env = make(map[string]any)
}
delete(exec.env, "Error")
exec.funcMap = template.FuncMap{
"error": exec.errorFunc,
}
}
func (exec *TemplateExecutor) Execute(_ context.Context, input string) (string, error) {
templ, err := template.New("template_executor").Funcs(exec.funcMap).Parse(input)
if err != nil {
return "", err
}
buf := getBuffer()
defer releaseBuffer(buf)
err = templ.Execute(buf, exec.env)
if err != nil {
return "", err
}
output := buf.String()
if output == "<no value>" {
return "", nil
}
return output, nil
}
func (exec *TemplateExecutor) IsCanceled() bool {
_, ok := exec.env["Error"]
return ok
}
func (exec *TemplateExecutor) errorFunc(text string) (string, error) {
exec.env["Error"] = text
return "", errors.New(text)
}
var bufferPool = &sync.Pool{
New: func() any {
return new(bytes.Buffer)
},
}
func getBuffer() *bytes.Buffer {
return bufferPool.Get().(*bytes.Buffer)
}
func releaseBuffer(buf *bytes.Buffer) {
if buf.Cap() > 1024 {
return
}
buf.Reset()
bufferPool.Put(buf)
}
......@@ -6,6 +6,7 @@ import (
"git.perx.ru/perxis/perxis-go/pkg/errors"
"git.perx.ru/perxis/perxis-go/pkg/expr"
"git.perx.ru/perxis/perxis-go/pkg/schema/executor"
"git.perx.ru/perxis/perxis-go/pkg/schema/field"
"git.perx.ru/perxis/perxis-go/pkg/schema/modify"
"git.perx.ru/perxis/perxis-go/pkg/schema/validate"
......@@ -33,6 +34,7 @@ var (
Modify = modify.Modify
Validate = validate.Validate
Evaluate = field.Evaluate
Execute = executor.Execute
)
func (s *Schema) Clone(reset bool) *Schema {
......@@ -266,6 +268,20 @@ func (s *Schema) Introspect(ctx context.Context, data map[string]interface{}) (m
return val, mutatedSchema, nil
}
func (s *Schema) Execute(ctx context.Context, exec executor.Executor) (*Schema, error) {
if err := s.Load(ctx); err != nil {
return nil, err
}
var clone = s.Clone(false)
err := Execute(ctx, clone, exec)
if err != nil {
return nil, err
}
return clone, nil
}
// GetEnum возвращает список опций перечисления для поля
func (s *Schema) GetEnum(fieldPath string) []validate.EnumOpt {
f := s.Field.GetField(fieldPath)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment