mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2025-02-20 14:53:14 +03:00
Merge pull request #9 from Neur0toxine/master
[improvement] avoid panic if template was added twice
This commit is contained in:
commit
bf689e15b0
@ -11,23 +11,44 @@ import (
|
||||
type Renderer struct {
|
||||
multitemplate.Renderer
|
||||
TemplatesBox *packr.Box
|
||||
FuncMap template.FuncMap
|
||||
FuncMap template.FuncMap
|
||||
alreadyAdded map[string]*template.Template
|
||||
}
|
||||
|
||||
// NewRenderer is a Renderer constructor
|
||||
func NewRenderer(funcMap template.FuncMap) Renderer {
|
||||
return newRendererWithMultitemplate(funcMap, multitemplate.NewRenderer())
|
||||
}
|
||||
|
||||
// NewStaticRenderer is a Renderer constructor with multitemplate.Render
|
||||
func NewStaticRenderer(funcMap template.FuncMap) Renderer {
|
||||
return newRendererWithMultitemplate(funcMap, multitemplate.New())
|
||||
}
|
||||
|
||||
// NewStaticRenderer is a Renderer constructor with multitemplate.DynamicRender
|
||||
func NewDynamicRenderer(funcMap template.FuncMap) Renderer {
|
||||
return newRendererWithMultitemplate(funcMap, multitemplate.NewDynamic())
|
||||
}
|
||||
|
||||
// newRendererWithMultitemplate initializes Renderer with provided multitemplate.Renderer instance
|
||||
func newRendererWithMultitemplate(funcMap template.FuncMap, renderer multitemplate.Renderer) Renderer {
|
||||
return Renderer{
|
||||
Renderer: multitemplate.NewRenderer(),
|
||||
FuncMap: funcMap,
|
||||
Renderer: renderer,
|
||||
FuncMap: funcMap,
|
||||
alreadyAdded: map[string]*template.Template{},
|
||||
}
|
||||
}
|
||||
|
||||
// Push is an AddFromFilesFuncs wrapper
|
||||
func (r *Renderer) Push(name string, files ...string) *template.Template {
|
||||
if tpl := r.getTemplate(name); tpl != nil {
|
||||
return tpl
|
||||
}
|
||||
|
||||
if r.TemplatesBox == nil {
|
||||
return r.AddFromFilesFuncs(name, r.FuncMap, files...)
|
||||
return r.storeTemplate(name, r.AddFromFilesFuncs(name, r.FuncMap, files...))
|
||||
} else {
|
||||
return r.addFromBox(name, r.FuncMap, files...)
|
||||
return r.storeTemplate(name, r.addFromBox(name, r.FuncMap, files...))
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,4 +63,32 @@ func (r *Renderer) addFromBox(name string, funcMap template.FuncMap, files ...st
|
||||
}
|
||||
|
||||
return r.AddFromStringsFuncs(name, funcMap, filesData...)
|
||||
}
|
||||
}
|
||||
|
||||
// storeTemplate stores built template if multitemplate.DynamicRender is used.
|
||||
// Dynamic render doesn't store templates - it stores builders, that's why we can't just extract them.
|
||||
// It possibly can cause data inconsistency in developer enviroments where return value from Renderer.Push is used.
|
||||
func (r *Renderer) storeTemplate(name string, tpl *template.Template) *template.Template {
|
||||
if _, ok := r.Renderer.(multitemplate.DynamicRender); ok {
|
||||
r.alreadyAdded[name] = tpl
|
||||
}
|
||||
|
||||
return tpl
|
||||
}
|
||||
|
||||
// getTemplate returns template from render or from storage
|
||||
func (r *Renderer) getTemplate(name string) *template.Template {
|
||||
if renderer, ok := r.Renderer.(multitemplate.Render); ok {
|
||||
if i, ok := renderer[name]; ok {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := r.Renderer.(multitemplate.DynamicRender); ok {
|
||||
if i, ok := r.alreadyAdded[name]; ok {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-contrib/multitemplate"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
@ -20,10 +21,17 @@ var (
|
||||
|
||||
type TemplateTest struct {
|
||||
suite.Suite
|
||||
renderer Renderer
|
||||
static Renderer
|
||||
dynamic Renderer
|
||||
}
|
||||
|
||||
func (t *TemplateTest) SetupSuite() {
|
||||
t.initTestData()
|
||||
t.static = t.initStatic()
|
||||
t.dynamic = t.initDynamic()
|
||||
}
|
||||
|
||||
func (t *TemplateTest) initTestData() {
|
||||
if _, err := os.Stat(testTemplatesDir); err != nil && os.IsNotExist(err) {
|
||||
err := os.Mkdir(testTemplatesDir, os.ModePerm)
|
||||
require.Nil(t.T(), err)
|
||||
@ -34,8 +42,22 @@ func (t *TemplateTest) SetupSuite() {
|
||||
require.Nil(t.T(), err1)
|
||||
require.Nil(t.T(), err2)
|
||||
}
|
||||
}
|
||||
|
||||
t.renderer = NewRenderer(template.FuncMap{
|
||||
func (t *TemplateTest) initStatic() Renderer {
|
||||
return NewStaticRenderer(template.FuncMap{
|
||||
"trans": func(data string) string {
|
||||
if data == "test" {
|
||||
return "ok"
|
||||
}
|
||||
|
||||
return "fail"
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (t *TemplateTest) initDynamic() Renderer {
|
||||
return NewDynamicRenderer(template.FuncMap{
|
||||
"trans": func(data string) string {
|
||||
if data == "test" {
|
||||
return "ok"
|
||||
@ -47,10 +69,60 @@ func (t *TemplateTest) SetupSuite() {
|
||||
}
|
||||
|
||||
func (t *TemplateTest) Test_Push() {
|
||||
tpl := t.renderer.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||
tplStatic := t.static.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||
tplDynamic := t.dynamic.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||
assert.Equal(t.T(), 3, len(tplStatic.Templates()))
|
||||
assert.Equal(t.T(), 3, len(tplDynamic.Templates()))
|
||||
}
|
||||
|
||||
func (t *TemplateTest) Test_PushAlreadyExists() {
|
||||
defer func() {
|
||||
assert.Nil(t.T(), recover())
|
||||
}()
|
||||
|
||||
tplStatic := t.static.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||
tplDynamic := t.dynamic.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||
assert.Equal(t.T(), 3, len(tplStatic.Templates()))
|
||||
assert.Equal(t.T(), 3, len(tplDynamic.Templates()))
|
||||
}
|
||||
|
||||
func (t *TemplateTest) Test_PushNewInstanceStatic() {
|
||||
defer func() {
|
||||
assert.Nil(t.T(), recover())
|
||||
}()
|
||||
|
||||
newInstance := t.initStatic()
|
||||
tpl := newInstance.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||
assert.Equal(t.T(), 3, len(tpl.Templates()))
|
||||
}
|
||||
|
||||
func (t *TemplateTest) Test_PushNewInstanceDynamic() {
|
||||
defer func() {
|
||||
assert.Nil(t.T(), recover())
|
||||
}()
|
||||
|
||||
newInstance := t.initDynamic()
|
||||
tpl := newInstance.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2))
|
||||
assert.Equal(t.T(), 3, len(tpl.Templates()))
|
||||
}
|
||||
|
||||
func TestTemplate_NewRenderer(t *testing.T) {
|
||||
r := NewRenderer(template.FuncMap{})
|
||||
assert.NotNil(t, r)
|
||||
}
|
||||
|
||||
func TestTemplate_NewStaticRenderer(t *testing.T) {
|
||||
r := NewStaticRenderer(template.FuncMap{})
|
||||
assert.NotNil(t, r)
|
||||
assert.IsType(t, multitemplate.New(), r.Renderer)
|
||||
}
|
||||
|
||||
func TestTemplate_NewDynamicRenderer(t *testing.T) {
|
||||
r := NewDynamicRenderer(template.FuncMap{})
|
||||
assert.NotNil(t, r)
|
||||
assert.IsType(t, multitemplate.NewDynamic(), r.Renderer)
|
||||
}
|
||||
|
||||
func TestTemplate_Suite(t *testing.T) {
|
||||
suite.Run(t, new(TemplateTest))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user