github.com/keys-pub/mattermost-server@v4.10.10+incompatible/utils/html_test.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package utils
     5  
     6  import (
     7  	"bytes"
     8  	"html/template"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/nicksnyder/go-i18n/i18n"
    16  	"github.com/nicksnyder/go-i18n/i18n/bundle"
    17  	"github.com/nicksnyder/go-i18n/i18n/language"
    18  	"github.com/nicksnyder/go-i18n/i18n/translation"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  
    22  	"github.com/mattermost/mattermost-server/model"
    23  )
    24  
    25  var htmlTestTranslationBundle *bundle.Bundle
    26  
    27  func init() {
    28  	htmlTestTranslationBundle = bundle.New()
    29  	fooBold, _ := translation.NewTranslation(map[string]interface{}{
    30  		"id":          "foo.bold",
    31  		"translation": "<b>{{ .Foo }}</b>",
    32  	})
    33  	htmlTestTranslationBundle.AddTranslation(&language.Language{Tag: "en"}, fooBold)
    34  }
    35  
    36  func TestHTMLTemplateWatcher(t *testing.T) {
    37  	TranslationsPreInit()
    38  
    39  	dir, err := ioutil.TempDir("", "")
    40  	require.NoError(t, err)
    41  	defer os.RemoveAll(dir)
    42  
    43  	require.NoError(t, os.Mkdir(filepath.Join(dir, "templates"), 0700))
    44  	require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}foo{{ end }}`), 0600))
    45  
    46  	prevDir, err := os.Getwd()
    47  	require.NoError(t, err)
    48  	defer os.Chdir(prevDir)
    49  	os.Chdir(dir)
    50  
    51  	watcher, err := NewHTMLTemplateWatcher("templates")
    52  	require.NotNil(t, watcher)
    53  	require.NoError(t, err)
    54  	defer watcher.Close()
    55  
    56  	tpl := NewHTMLTemplate(watcher.Templates(), "foo")
    57  	assert.Equal(t, "foo", tpl.Render())
    58  
    59  	require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "templates", "foo.html"), []byte(`{{ define "foo" }}bar{{ end }}`), 0600))
    60  
    61  	for i := 0; i < 30; i++ {
    62  		tpl = NewHTMLTemplate(watcher.Templates(), "foo")
    63  		if tpl.Render() == "bar" {
    64  			break
    65  		}
    66  		time.Sleep(time.Millisecond * 50)
    67  	}
    68  	assert.Equal(t, "bar", tpl.Render())
    69  }
    70  
    71  func TestHTMLTemplateWatcher_BadDirectory(t *testing.T) {
    72  	TranslationsPreInit()
    73  	watcher, err := NewHTMLTemplateWatcher("notarealdirectory")
    74  	assert.Nil(t, watcher)
    75  	assert.Error(t, err)
    76  }
    77  
    78  func TestHTMLTemplate(t *testing.T) {
    79  	tpl := template.New("test")
    80  	_, err := tpl.Parse(`{{ define "foo" }}foo{{ .Props.Bar }}{{ end }}`)
    81  	require.NoError(t, err)
    82  
    83  	htmlTemplate := NewHTMLTemplate(tpl, "foo")
    84  	htmlTemplate.Props["Bar"] = "bar"
    85  	assert.Equal(t, "foobar", htmlTemplate.Render())
    86  
    87  	buf := &bytes.Buffer{}
    88  	require.NoError(t, htmlTemplate.RenderToWriter(buf))
    89  	assert.Equal(t, "foobar", buf.String())
    90  }
    91  
    92  func TestHTMLTemplate_RenderError(t *testing.T) {
    93  	tpl := template.New("test")
    94  	_, err := tpl.Parse(`{{ define "foo" }}foo{{ .Foo.Bar }}bar{{ end }}`)
    95  	require.NoError(t, err)
    96  
    97  	htmlTemplate := NewHTMLTemplate(tpl, "foo")
    98  	assert.Equal(t, "foo", htmlTemplate.Render())
    99  
   100  	buf := &bytes.Buffer{}
   101  	assert.Error(t, htmlTemplate.RenderToWriter(buf))
   102  	assert.Equal(t, "foo", buf.String())
   103  }
   104  
   105  func TestTranslateAsHtml(t *testing.T) {
   106  	assert.EqualValues(t, "<b>&lt;i&gt;foo&lt;/i&gt;</b>", TranslateAsHtml(i18n.TranslateFunc(htmlTestTranslationBundle.MustTfunc("en")), "foo.bold", map[string]interface{}{
   107  		"Foo": "<i>foo</i>",
   108  	}))
   109  }
   110  
   111  func TestEscapeForHtml(t *testing.T) {
   112  	for name, tc := range map[string]struct {
   113  		In       interface{}
   114  		Expected interface{}
   115  	}{
   116  		"NoHTML": {
   117  			In:       "abc",
   118  			Expected: "abc",
   119  		},
   120  		"String": {
   121  			In:       "<b>abc</b>",
   122  			Expected: "&lt;b&gt;abc&lt;/b&gt;",
   123  		},
   124  		"StringPointer": {
   125  			In:       model.NewString("<b>abc</b>"),
   126  			Expected: "&lt;b&gt;abc&lt;/b&gt;",
   127  		},
   128  		"Map": {
   129  			In: map[string]interface{}{
   130  				"abc": "abc",
   131  				"123": "<b>123</b>",
   132  			},
   133  			Expected: map[string]interface{}{
   134  				"abc": "abc",
   135  				"123": "&lt;b&gt;123&lt;/b&gt;",
   136  			},
   137  		},
   138  		"Unsupported": {
   139  			In:       struct{ string }{"<b>abc</b>"},
   140  			Expected: "",
   141  		},
   142  	} {
   143  		t.Run(name, func(t *testing.T) {
   144  			assert.Equal(t, tc.Expected, escapeForHtml(tc.In))
   145  		})
   146  	}
   147  }