// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package utils import ( "bytes" "html/template" "io/ioutil" "os" "path/filepath" "testing" "time" "github.com/nicksnyder/go-i18n/i18n" "github.com/nicksnyder/go-i18n/i18n/bundle" "github.com/nicksnyder/go-i18n/i18n/language" "github.com/nicksnyder/go-i18n/i18n/translation" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/mattermost/mattermost-server/model" ) var htmlTestTranslationBundle *bundle.Bundle func init() { htmlTestTranslationBundle = bundle.New() fooBold, _ := translation.NewTranslation(map[string]interface{}{ "id": "foo.bold", "translation": "

[[{{ .Foo }}]]

", }) htmlTestTranslationBundle.AddTranslation(&language.Language{Tag: "en"}, fooBold) } func TestHTMLTemplateWatcher(t *testing.T) { TranslationsPreInit() dir, err := ioutil.TempDir("", "") require.NoError(t, err) defer os.RemoveAll(dir) require.NoError(t, os.Mkdir(filepath.Join(dir, "templates"), 0700)) require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}foo{{ end }}`), 0600)) prevDir, err := os.Getwd() require.NoError(t, err) defer os.Chdir(prevDir) os.Chdir(dir) watcher, err := NewHTMLTemplateWatcher("templates") require.NotNil(t, watcher) require.NoError(t, err) defer watcher.Close() tpl := NewHTMLTemplate(watcher.Templates(), "foo") assert.Equal(t, "foo", tpl.Render()) require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}bar{{ end }}`), 0600)) for i := 0; i < 30; i++ { tpl = NewHTMLTemplate(watcher.Templates(), "foo") if tpl.Render() == "bar" { break } time.Sleep(time.Millisecond * 50) } assert.Equal(t, "bar", tpl.Render()) } func TestHTMLTemplateWatcher_BadDirectory(t *testing.T) { TranslationsPreInit() watcher, err := NewHTMLTemplateWatcher("notarealdirectory") assert.Nil(t, watcher) assert.Error(t, err) } func TestHTMLTemplate(t *testing.T) { tpl := template.New("test") _, err := tpl.Parse(`{{ define "foo" }}foo{{ .Props.Bar }}{{ end }}`) require.NoError(t, err) htmlTemplate := NewHTMLTemplate(tpl, "foo") htmlTemplate.Props["Bar"] = "bar" assert.Equal(t, "foobar", htmlTemplate.Render()) buf := &bytes.Buffer{} require.NoError(t, htmlTemplate.RenderToWriter(buf)) assert.Equal(t, "foobar", buf.String()) } func TestHTMLTemplate_RenderError(t *testing.T) { tpl := template.New("test") _, err := tpl.Parse(`{{ define "foo" }}foo{{ .Foo.Bar }}bar{{ end }}`) require.NoError(t, err) htmlTemplate := NewHTMLTemplate(tpl, "foo") assert.Equal(t, "foo", htmlTemplate.Render()) buf := &bytes.Buffer{} assert.Error(t, htmlTemplate.RenderToWriter(buf)) assert.Equal(t, "foo", buf.String()) } func TestTranslateAsHtml(t *testing.T) { assert.EqualValues(t, "

<i>foo</i>

", TranslateAsHtml(i18n.TranslateFunc(htmlTestTranslationBundle.MustTfunc("en")), "foo.bold", map[string]interface{}{ "Foo": "foo", })) } func TestEscapeForHtml(t *testing.T) { for name, tc := range map[string]struct { In interface{} Expected interface{} }{ "NoHTML": { In: "abc", Expected: "abc", }, "String": { In: "abc", Expected: "<b>abc</b>", }, "StringPointer": { In: model.NewString("abc"), Expected: "<b>abc</b>", }, "Map": { In: map[string]interface{}{ "abc": "abc", "123": "123", }, Expected: map[string]interface{}{ "abc": "abc", "123": "<b>123</b>", }, }, "Unsupported": { In: struct{ string }{"abc"}, Expected: "", }, } { t.Run(name, func(t *testing.T) { assert.Equal(t, tc.Expected, escapeForHtml(tc.In)) }) } }