github.com/gogf/gf@v1.16.9/os/gview/gview_unit_basic_test.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gview_test
     8  
     9  import (
    10  	"context"
    11  	"github.com/gogf/gf/encoding/ghtml"
    12  	"github.com/gogf/gf/os/gctx"
    13  	"github.com/gogf/gf/os/gtime"
    14  	"github.com/gogf/gf/util/gconv"
    15  	"io/ioutil"
    16  	"os"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/gogf/gf/frame/g"
    22  	"github.com/gogf/gf/os/gfile"
    23  	"github.com/gogf/gf/os/gview"
    24  	"github.com/gogf/gf/test/gtest"
    25  	"github.com/gogf/gf/text/gstr"
    26  )
    27  
    28  func init() {
    29  	os.Setenv("GF_GVIEW_ERRORPRINT", "false")
    30  }
    31  
    32  func Test_Basic(t *testing.T) {
    33  	gtest.C(t, func(t *gtest.T) {
    34  		str := `hello {{.name}},version:{{.version}};hello {{GetName}},version:{{GetVersion}};{{.other}}`
    35  		pwd := gfile.Pwd()
    36  		view := gview.New()
    37  		view.SetDelimiters("{{", "}}")
    38  		view.AddPath(pwd)
    39  		view.SetPath(pwd)
    40  		view.Assign("name", "gf")
    41  		view.Assigns(g.Map{"version": "1.7.0"})
    42  		view.BindFunc("GetName", func() string { return "gf" })
    43  		view.BindFuncMap(gview.FuncMap{"GetVersion": func() string { return "1.7.0" }})
    44  		result, err := view.ParseContent(context.TODO(), str, g.Map{"other": "that's all"})
    45  		t.Assert(err != nil, false)
    46  		t.Assert(result, "hello gf,version:1.7.0;hello gf,version:1.7.0;that's all")
    47  
    48  		//测试api方法
    49  		str = `hello {{.name}}`
    50  		result, err = gview.ParseContent(context.TODO(), str, g.Map{"name": "gf"})
    51  		t.Assert(err != nil, false)
    52  		t.Assert(result, "hello gf")
    53  
    54  		//测试instance方法
    55  		result, err = gview.Instance().ParseContent(context.TODO(), str, g.Map{"name": "gf"})
    56  		t.Assert(err != nil, false)
    57  		t.Assert(result, "hello gf")
    58  	})
    59  }
    60  
    61  func Test_Func(t *testing.T) {
    62  	gtest.C(t, func(t *gtest.T) {
    63  		str := `{{eq 1 1}};{{eq 1 2}};{{eq "A" "B"}}`
    64  		result, err := gview.ParseContent(context.TODO(), str, nil)
    65  		t.Assert(err != nil, false)
    66  		t.Assert(result, `true;false;false`)
    67  
    68  		str = `{{ne 1 2}};{{ne 1 1}};{{ne "A" "B"}}`
    69  		result, err = gview.ParseContent(context.TODO(), str, nil)
    70  		t.Assert(err != nil, false)
    71  		t.Assert(result, `true;false;true`)
    72  
    73  		str = `{{lt 1 2}};{{lt 1 1}};{{lt 1 0}};{{lt "A" "B"}}`
    74  		result, err = gview.ParseContent(context.TODO(), str, nil)
    75  		t.Assert(err != nil, false)
    76  		t.Assert(result, `true;false;false;true`)
    77  
    78  		str = `{{le 1 2}};{{le 1 1}};{{le 1 0}};{{le "A" "B"}}`
    79  		result, err = gview.ParseContent(context.TODO(), str, nil)
    80  		t.Assert(err != nil, false)
    81  		t.Assert(result, `true;true;false;true`)
    82  
    83  		str = `{{gt 1 2}};{{gt 1 1}};{{gt 1 0}};{{gt "A" "B"}}`
    84  		result, err = gview.ParseContent(context.TODO(), str, nil)
    85  		t.Assert(err != nil, false)
    86  		t.Assert(result, `false;false;true;false`)
    87  
    88  		str = `{{ge 1 2}};{{ge 1 1}};{{ge 1 0}};{{ge "A" "B"}}`
    89  		result, err = gview.ParseContent(context.TODO(), str, nil)
    90  		t.Assert(err != nil, false)
    91  		t.Assert(result, `false;true;true;false`)
    92  
    93  		str = `{{"<div>测试</div>"|text}}`
    94  		result, err = gview.ParseContent(context.TODO(), str, nil)
    95  		t.Assert(err != nil, false)
    96  		t.Assert(result, `测试`)
    97  
    98  		str = `{{"<div>测试</div>"|html}}`
    99  		result, err = gview.ParseContent(context.TODO(), str, nil)
   100  		t.Assert(err != nil, false)
   101  		t.Assert(result, `&lt;div&gt;测试&lt;/div&gt;`)
   102  
   103  		str = `{{"<div>测试</div>"|htmlencode}}`
   104  		result, err = gview.ParseContent(context.TODO(), str, nil)
   105  		t.Assert(err != nil, false)
   106  		t.Assert(result, `&lt;div&gt;测试&lt;/div&gt;`)
   107  
   108  		str = `{{"&lt;div&gt;测试&lt;/div&gt;"|htmldecode}}`
   109  		result, err = gview.ParseContent(context.TODO(), str, nil)
   110  		t.Assert(err != nil, false)
   111  		t.Assert(result, `<div>测试</div>`)
   112  
   113  		str = `{{"https://goframe.org"|url}}`
   114  		result, err = gview.ParseContent(context.TODO(), str, nil)
   115  		t.Assert(err != nil, false)
   116  		t.Assert(result, `https%3A%2F%2Fgoframe.org`)
   117  
   118  		str = `{{"https://goframe.org"|urlencode}}`
   119  		result, err = gview.ParseContent(context.TODO(), str, nil)
   120  		t.Assert(err != nil, false)
   121  		t.Assert(result, `https%3A%2F%2Fgoframe.org`)
   122  
   123  		str = `{{"https%3A%2F%2Fgoframe.org"|urldecode}}`
   124  		result, err = gview.ParseContent(context.TODO(), str, nil)
   125  		t.Assert(err != nil, false)
   126  		t.Assert(result, `https://goframe.org`)
   127  		str = `{{"https%3NA%2F%2Fgoframe.org"|urldecode}}`
   128  		result, err = gview.ParseContent(context.TODO(), str, nil)
   129  		t.Assert(err != nil, false)
   130  		t.Assert(gstr.Contains(result, "invalid URL escape"), true)
   131  
   132  		str = `{{1540822968 | date "Y-m-d"}}`
   133  		result, err = gview.ParseContent(context.TODO(), str, nil)
   134  		t.Assert(err != nil, false)
   135  		t.Assert(result, `2018-10-29`)
   136  		str = `{{date "Y-m-d"}}`
   137  		result, err = gview.ParseContent(context.TODO(), str, nil)
   138  		t.Assert(err != nil, false)
   139  
   140  		str = `{{"我是中国人" | substr 2 -1}};{{"我是中国人" | substr 2  2}}`
   141  		result, err = gview.ParseContent(context.TODO(), str, nil)
   142  		t.Assert(err != nil, false)
   143  		t.Assert(result, `中国人;中国`)
   144  
   145  		str = `{{"我是中国人" | strlimit 2  "..."}}`
   146  		result, err = gview.ParseContent(context.TODO(), str, nil)
   147  		t.Assert(err != nil, false)
   148  		t.Assert(result, `我是...`)
   149  
   150  		str = `{{"I'm中国人" | replace "I'm" "我是"}}`
   151  		result, err = gview.ParseContent(context.TODO(), str, nil)
   152  		t.Assert(err != nil, false)
   153  		t.Assert(result, `我是中国人`)
   154  
   155  		str = `{{compare "A" "B"}};{{compare "1" "2"}};{{compare 2 1}};{{compare 1 1}}`
   156  		result, err = gview.ParseContent(context.TODO(), str, nil)
   157  		t.Assert(err != nil, false)
   158  		t.Assert(result, `-1;-1;1;0`)
   159  
   160  		str = `{{"热爱GF热爱生活" | hidestr 20  "*"}};{{"热爱GF热爱生活" | hidestr 50  "*"}}`
   161  		result, err = gview.ParseContent(context.TODO(), str, nil)
   162  		t.Assert(err != nil, false)
   163  		t.Assert(result, `热爱GF*爱生活;热爱****生活`)
   164  
   165  		str = `{{"热爱GF热爱生活" | highlight "GF" "red"}}`
   166  		result, err = gview.ParseContent(context.TODO(), str, nil)
   167  		t.Assert(err != nil, false)
   168  		t.Assert(result, `热爱<span style="color:red;">GF</span>热爱生活`)
   169  
   170  		str = `{{"gf" | toupper}};{{"GF" | tolower}}`
   171  		result, err = gview.ParseContent(context.TODO(), str, nil)
   172  		t.Assert(err != nil, false)
   173  		t.Assert(result, `GF;gf`)
   174  
   175  		str = `{{concat "I" "Love" "GoFrame"}}`
   176  		result, err = gview.ParseContent(context.TODO(), str, nil)
   177  		t.Assert(err, nil)
   178  		t.Assert(result, `ILoveGoFrame`)
   179  	})
   180  	// eq: multiple values.
   181  	gtest.C(t, func(t *gtest.T) {
   182  		str := `{{eq 1 2 1 3 4 5}}`
   183  		result, err := gview.ParseContent(context.TODO(), str, nil)
   184  		t.Assert(err != nil, false)
   185  		t.Assert(result, `true`)
   186  	})
   187  	gtest.C(t, func(t *gtest.T) {
   188  		str := `{{eq 6 2 1 3 4 5}}`
   189  		result, err := gview.ParseContent(context.TODO(), str, nil)
   190  		t.Assert(err != nil, false)
   191  		t.Assert(result, `false`)
   192  	})
   193  }
   194  
   195  func Test_FuncNl2Br(t *testing.T) {
   196  	gtest.C(t, func(t *gtest.T) {
   197  		str := `{{"Go\nFrame" | nl2br}}`
   198  		result, err := gview.ParseContent(context.TODO(), str, nil)
   199  		t.Assert(err, nil)
   200  		t.Assert(result, `Go<br>Frame`)
   201  	})
   202  	gtest.C(t, func(t *gtest.T) {
   203  		s := ""
   204  		for i := 0; i < 3000; i++ {
   205  			s += "Go\nFrame\n中文"
   206  		}
   207  		str := `{{.content | nl2br}}`
   208  		result, err := gview.ParseContent(context.TODO(), str, g.Map{
   209  			"content": s,
   210  		})
   211  		t.Assert(err, nil)
   212  		t.Assert(result, strings.Replace(s, "\n", "<br>", -1))
   213  	})
   214  }
   215  
   216  func Test_FuncInclude(t *testing.T) {
   217  	gtest.C(t, func(t *gtest.T) {
   218  		header := `<h1>HEADER</h1>`
   219  		main := `<h1>hello gf</h1>`
   220  		footer := `<h1>FOOTER</h1>`
   221  		layout := `{{include "header.html" .}}
   222  {{include "main.html" .}}
   223  {{include "footer.html" .}}`
   224  		templatePath := gfile.Pwd() + gfile.Separator + "template"
   225  		gfile.Mkdir(templatePath)
   226  		defer gfile.Remove(templatePath)
   227  		//headerFile, _ := gfile.Create(templatePath + gfile.Separator + "header.html")
   228  		err := ioutil.WriteFile(templatePath+gfile.Separator+"header.html", []byte(header), 0644)
   229  		if err != nil {
   230  			t.Error(err)
   231  		}
   232  		ioutil.WriteFile(templatePath+gfile.Separator+"main.html", []byte(main), 0644)
   233  		ioutil.WriteFile(templatePath+gfile.Separator+"footer.html", []byte(footer), 0644)
   234  		ioutil.WriteFile(templatePath+gfile.Separator+"layout.html", []byte(layout), 0644)
   235  		view := gview.New(templatePath)
   236  		result, err := view.Parse(context.TODO(), "notfound.html")
   237  		t.Assert(err != nil, true)
   238  		t.Assert(result, ``)
   239  		result, err = view.Parse(context.TODO(), "layout.html")
   240  		t.Assert(err != nil, false)
   241  		t.Assert(result, `<h1>HEADER</h1>
   242  <h1>hello gf</h1>
   243  <h1>FOOTER</h1>`)
   244  		notfoundPath := templatePath + gfile.Separator + "template" + gfile.Separator + "notfound.html"
   245  		gfile.Mkdir(templatePath + gfile.Separator + "template")
   246  		gfile.Create(notfoundPath)
   247  		ioutil.WriteFile(notfoundPath, []byte("notfound"), 0644)
   248  		result, err = view.Parse(context.TODO(), "notfound.html")
   249  		t.Assert(err != nil, true)
   250  		t.Assert(result, ``)
   251  	})
   252  }
   253  
   254  func Test_SetPath(t *testing.T) {
   255  	gtest.C(t, func(t *gtest.T) {
   256  		view := gview.Instance("addpath")
   257  		err := view.AddPath("tmp")
   258  		t.AssertNE(err, nil)
   259  
   260  		err = view.AddPath("gview.go")
   261  		t.AssertNE(err, nil)
   262  
   263  		os.Setenv("GF_GVIEW_PATH", "tmp")
   264  		view = gview.Instance("setpath")
   265  		err = view.SetPath("tmp")
   266  		t.AssertNE(err, nil)
   267  
   268  		err = view.SetPath("gview.go")
   269  		t.AssertNE(err, nil)
   270  
   271  		view = gview.New(gfile.Pwd())
   272  		err = view.SetPath("tmp")
   273  		t.AssertNE(err, nil)
   274  
   275  		err = view.SetPath("gview.go")
   276  		t.AssertNE(err, nil)
   277  
   278  		os.Setenv("GF_GVIEW_PATH", "template")
   279  		gfile.Mkdir(gfile.Pwd() + gfile.Separator + "template")
   280  		view = gview.New()
   281  	})
   282  }
   283  
   284  func Test_ParseContent(t *testing.T) {
   285  	gtest.C(t, func(t *gtest.T) {
   286  		str := `{{.name}}`
   287  		view := gview.New()
   288  		result, err := view.ParseContent(context.TODO(), str, g.Map{"name": func() {}})
   289  		t.Assert(err != nil, true)
   290  		t.Assert(result, ``)
   291  	})
   292  }
   293  
   294  func Test_HotReload(t *testing.T) {
   295  	gtest.C(t, func(t *gtest.T) {
   296  		dirPath := gfile.Join(
   297  			gfile.TempDir(),
   298  			"testdata",
   299  			"template-"+gconv.String(gtime.TimestampNano()),
   300  		)
   301  		defer gfile.Remove(dirPath)
   302  		filePath := gfile.Join(dirPath, "test.html")
   303  
   304  		// Initialize data.
   305  		err := gfile.PutContents(filePath, "test:{{.var}}")
   306  		t.Assert(err, nil)
   307  
   308  		view := gview.New(dirPath)
   309  
   310  		time.Sleep(100 * time.Millisecond)
   311  		result, err := view.Parse(context.TODO(), "test.html", g.Map{
   312  			"var": "1",
   313  		})
   314  		t.Assert(err, nil)
   315  		t.Assert(result, `test:1`)
   316  
   317  		// Update data.
   318  		err = gfile.PutContents(filePath, "test2:{{.var}}")
   319  		t.Assert(err, nil)
   320  
   321  		time.Sleep(100 * time.Millisecond)
   322  		result, err = view.Parse(context.TODO(), "test.html", g.Map{
   323  			"var": "2",
   324  		})
   325  		t.Assert(err, nil)
   326  		t.Assert(result, `test2:2`)
   327  	})
   328  }
   329  
   330  func Test_XSS(t *testing.T) {
   331  	gtest.C(t, func(t *gtest.T) {
   332  		v := gview.New()
   333  		s := "<br>"
   334  		r, err := v.ParseContent(context.TODO(), "{{.v}}", g.Map{
   335  			"v": s,
   336  		})
   337  		t.Assert(err, nil)
   338  		t.Assert(r, s)
   339  	})
   340  	gtest.C(t, func(t *gtest.T) {
   341  		v := gview.New()
   342  		v.SetAutoEncode(true)
   343  		s := "<br>"
   344  		r, err := v.ParseContent(context.TODO(), "{{.v}}", g.Map{
   345  			"v": s,
   346  		})
   347  		t.Assert(err, nil)
   348  		t.Assert(r, ghtml.Entities(s))
   349  	})
   350  	// Tag "if".
   351  	gtest.C(t, func(t *gtest.T) {
   352  		v := gview.New()
   353  		v.SetAutoEncode(true)
   354  		s := "<br>"
   355  		r, err := v.ParseContent(context.TODO(), "{{if eq 1 1}}{{.v}}{{end}}", g.Map{
   356  			"v": s,
   357  		})
   358  		t.Assert(err, nil)
   359  		t.Assert(r, ghtml.Entities(s))
   360  	})
   361  }
   362  
   363  type TypeForBuildInFuncMap struct {
   364  	Name  string
   365  	Score float32
   366  }
   367  
   368  func (t *TypeForBuildInFuncMap) Test() (*TypeForBuildInFuncMap, error) {
   369  	return &TypeForBuildInFuncMap{"john", 99.9}, nil
   370  }
   371  
   372  func Test_BuildInFuncMap(t *testing.T) {
   373  	gtest.C(t, func(t *gtest.T) {
   374  		v := gview.New()
   375  		v.Assign("v", new(TypeForBuildInFuncMap))
   376  		r, err := v.ParseContent(context.TODO(), "{{range $k, $v := map .v.Test}} {{$k}}:{{$v}} {{end}}")
   377  		t.Assert(err, nil)
   378  		t.Assert(gstr.Contains(r, "Name:john"), true)
   379  		t.Assert(gstr.Contains(r, "Score:99.9"), true)
   380  	})
   381  }
   382  
   383  type TypeForBuildInFuncMaps struct {
   384  	Name  string
   385  	Score float32
   386  }
   387  
   388  func (t *TypeForBuildInFuncMaps) Test() ([]*TypeForBuildInFuncMaps, error) {
   389  	return []*TypeForBuildInFuncMaps{
   390  		{"john", 99.9},
   391  		{"smith", 100},
   392  	}, nil
   393  }
   394  
   395  func Test_BuildInFuncMaps(t *testing.T) {
   396  	gtest.C(t, func(t *gtest.T) {
   397  		v := gview.New()
   398  		v.Assign("v", new(TypeForBuildInFuncMaps))
   399  		r, err := v.ParseContent(context.TODO(), "{{range $k, $v := maps .v.Test}} {{$k}}:{{$v.Name}} {{$v.Score}} {{end}}")
   400  		t.Assert(err, nil)
   401  		t.Assert(r, ` 0:john 99.9  1:smith 100 `)
   402  	})
   403  }
   404  
   405  func Test_BuildInFuncDump(t *testing.T) {
   406  	gtest.C(t, func(t *gtest.T) {
   407  		v := gview.New()
   408  		v.Assign("v", g.Map{
   409  			"name":  "john",
   410  			"score": 100,
   411  		})
   412  		r, err := v.ParseContent(context.TODO(), "{{dump .}}")
   413  		t.Assert(err, nil)
   414  		t.Assert(gstr.Contains(r, `"name": "john"`), true)
   415  		t.Assert(gstr.Contains(r, `"score": 100`), true)
   416  	})
   417  }
   418  
   419  func Test_BuildInFuncJson(t *testing.T) {
   420  	gtest.C(t, func(t *gtest.T) {
   421  		v := gview.New()
   422  		v.Assign("v", g.Map{
   423  			"name": "john",
   424  		})
   425  		r, err := v.ParseContent(context.TODO(), "{{json .v}}")
   426  		t.Assert(err, nil)
   427  		t.Assert(r, `{"name":"john"}`)
   428  	})
   429  }
   430  
   431  func Test_BuildInFuncPlus(t *testing.T) {
   432  	gtest.C(t, func(t *gtest.T) {
   433  		v := gview.New()
   434  		r, err := v.ParseContent(gctx.New(), "{{plus 1 2 3}}")
   435  		t.Assert(err, nil)
   436  		t.Assert(r, `6`)
   437  	})
   438  }
   439  
   440  func Test_BuildInFuncMinus(t *testing.T) {
   441  	gtest.C(t, func(t *gtest.T) {
   442  		v := gview.New()
   443  		r, err := v.ParseContent(gctx.New(), "{{minus 1 2 3}}")
   444  		t.Assert(err, nil)
   445  		t.Assert(r, `-4`)
   446  	})
   447  }
   448  
   449  func Test_BuildInFuncTimes(t *testing.T) {
   450  	gtest.C(t, func(t *gtest.T) {
   451  		v := gview.New()
   452  		r, err := v.ParseContent(gctx.New(), "{{times 1 2 3 4}}")
   453  		t.Assert(err, nil)
   454  		t.Assert(r, `24`)
   455  	})
   456  }
   457  
   458  func Test_BuildInFuncDivide(t *testing.T) {
   459  	gtest.C(t, func(t *gtest.T) {
   460  		v := gview.New()
   461  		r, err := v.ParseContent(gctx.New(), "{{divide 8 2 2}}")
   462  		t.Assert(err, nil)
   463  		t.Assert(r, `2`)
   464  	})
   465  }