github.com/wangyougui/gf/v2@v2.6.5/os/gview/gview_z_unit_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/wangyougui/gf.
     6  
     7  package gview_test
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"os"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/wangyougui/gf/v2/encoding/ghtml"
    18  	"github.com/wangyougui/gf/v2/frame/g"
    19  	"github.com/wangyougui/gf/v2/os/gctx"
    20  	"github.com/wangyougui/gf/v2/os/gfile"
    21  	"github.com/wangyougui/gf/v2/os/gres"
    22  	"github.com/wangyougui/gf/v2/os/gtime"
    23  	"github.com/wangyougui/gf/v2/os/gview"
    24  	"github.com/wangyougui/gf/v2/test/gtest"
    25  	"github.com/wangyougui/gf/v2/text/gstr"
    26  	"github.com/wangyougui/gf/v2/util/gconv"
    27  	"github.com/wangyougui/gf/v2/util/gmode"
    28  	"github.com/wangyougui/gf/v2/util/guid"
    29  )
    30  
    31  func init() {
    32  	os.Setenv("GF_GVIEW_ERRORPRINT", "false")
    33  }
    34  
    35  func Test_Basic(t *testing.T) {
    36  	gtest.C(t, func(t *gtest.T) {
    37  		str := `hello {{.name}},version:{{.version}};hello {{GetName}},version:{{GetVersion}};{{.other}}`
    38  		pwd := gfile.Pwd()
    39  		view := gview.New()
    40  		view.SetDelimiters("{{", "}}")
    41  		view.AddPath(pwd)
    42  		view.SetPath(pwd)
    43  		view.Assign("name", "gf")
    44  		view.Assigns(g.Map{"version": "1.7.0"})
    45  		view.BindFunc("GetName", func() string { return "gf" })
    46  		view.BindFuncMap(gview.FuncMap{"GetVersion": func() string { return "1.7.0" }})
    47  		result, err := view.ParseContent(context.TODO(), str, g.Map{"other": "that's all"})
    48  		t.Assert(err != nil, false)
    49  		t.Assert(result, "hello gf,version:1.7.0;hello gf,version:1.7.0;that's all")
    50  
    51  		// 测试api方法
    52  		str = `hello {{.name}}`
    53  		result, err = gview.ParseContent(context.TODO(), str, g.Map{"name": "gf"})
    54  		t.Assert(err != nil, false)
    55  		t.Assert(result, "hello gf")
    56  
    57  		// 测试instance方法
    58  		result, err = gview.Instance().ParseContent(context.TODO(), str, g.Map{"name": "gf"})
    59  		t.Assert(err != nil, false)
    60  		t.Assert(result, "hello gf")
    61  	})
    62  }
    63  
    64  func Test_Func(t *testing.T) {
    65  	gtest.C(t, func(t *gtest.T) {
    66  		str := `{{eq 1 1}};{{eq 1 2}};{{eq "A" "B"}}`
    67  		result, err := gview.ParseContent(context.TODO(), str, nil)
    68  		t.Assert(err != nil, false)
    69  		t.Assert(result, `true;false;false`)
    70  
    71  		str = `{{ne 1 2}};{{ne 1 1}};{{ne "A" "B"}}`
    72  		result, err = gview.ParseContent(context.TODO(), str, nil)
    73  		t.Assert(err != nil, false)
    74  		t.Assert(result, `true;false;true`)
    75  
    76  		str = `{{lt 1 2}};{{lt 1 1}};{{lt 1 0}};{{lt "A" "B"}}`
    77  		result, err = gview.ParseContent(context.TODO(), str, nil)
    78  		t.Assert(err != nil, false)
    79  		t.Assert(result, `true;false;false;true`)
    80  
    81  		str = `{{le 1 2}};{{le 1 1}};{{le 1 0}};{{le "A" "B"}}`
    82  		result, err = gview.ParseContent(context.TODO(), str, nil)
    83  		t.Assert(err != nil, false)
    84  		t.Assert(result, `true;true;false;true`)
    85  
    86  		str = `{{gt 1 2}};{{gt 1 1}};{{gt 1 0}};{{gt "A" "B"}}`
    87  		result, err = gview.ParseContent(context.TODO(), str, nil)
    88  		t.Assert(err != nil, false)
    89  		t.Assert(result, `false;false;true;false`)
    90  
    91  		str = `{{ge 1 2}};{{ge 1 1}};{{ge 1 0}};{{ge "A" "B"}}`
    92  		result, err = gview.ParseContent(context.TODO(), str, nil)
    93  		t.Assert(err != nil, false)
    94  		t.Assert(result, `false;true;true;false`)
    95  
    96  		str = `{{"<div>测试</div>"|text}}`
    97  		result, err = gview.ParseContent(context.TODO(), str, nil)
    98  		t.Assert(err != nil, false)
    99  		t.Assert(result, `测试`)
   100  
   101  		str = `{{"<div>测试</div>"|html}}`
   102  		result, err = gview.ParseContent(context.TODO(), str, nil)
   103  		t.Assert(err != nil, false)
   104  		t.Assert(result, `&lt;div&gt;测试&lt;/div&gt;`)
   105  
   106  		str = `{{"<div>测试</div>"|htmlencode}}`
   107  		result, err = gview.ParseContent(context.TODO(), str, nil)
   108  		t.Assert(err != nil, false)
   109  		t.Assert(result, `&lt;div&gt;测试&lt;/div&gt;`)
   110  
   111  		str = `{{"&lt;div&gt;测试&lt;/div&gt;"|htmldecode}}`
   112  		result, err = gview.ParseContent(context.TODO(), str, nil)
   113  		t.Assert(err != nil, false)
   114  		t.Assert(result, `<div>测试</div>`)
   115  
   116  		str = `{{"https://goframe.org"|url}}`
   117  		result, err = gview.ParseContent(context.TODO(), str, nil)
   118  		t.Assert(err != nil, false)
   119  		t.Assert(result, `https%3A%2F%2Fgoframe.org`)
   120  
   121  		str = `{{"https://goframe.org"|urlencode}}`
   122  		result, err = gview.ParseContent(context.TODO(), str, nil)
   123  		t.Assert(err != nil, false)
   124  		t.Assert(result, `https%3A%2F%2Fgoframe.org`)
   125  
   126  		str = `{{"https%3A%2F%2Fgoframe.org"|urldecode}}`
   127  		result, err = gview.ParseContent(context.TODO(), str, nil)
   128  		t.Assert(err != nil, false)
   129  		t.Assert(result, `https://goframe.org`)
   130  		str = `{{"https%3NA%2F%2Fgoframe.org"|urldecode}}`
   131  		result, err = gview.ParseContent(context.TODO(), str, nil)
   132  		t.Assert(err != nil, false)
   133  		t.Assert(gstr.Contains(result, "invalid URL escape"), true)
   134  
   135  		str = `{{1540822968 | date "Y-m-d"}}`
   136  		result, err = gview.ParseContent(context.TODO(), str, nil)
   137  		t.Assert(err != nil, false)
   138  		t.Assert(result, `2018-10-29`)
   139  		str = `{{date "Y-m-d"}}`
   140  		result, err = gview.ParseContent(context.TODO(), str, nil)
   141  		t.Assert(err != nil, false)
   142  
   143  		str = `{{"我是中国人" | substr 2 -1}};{{"我是中国人" | substr 2  2}}`
   144  		result, err = gview.ParseContent(context.TODO(), str, nil)
   145  		t.Assert(err != nil, false)
   146  		t.Assert(result, `中国;中国`)
   147  
   148  		str = `{{"我是中国人" | strlimit 2  "..."}}`
   149  		result, err = gview.ParseContent(context.TODO(), str, nil)
   150  		t.Assert(err != nil, false)
   151  		t.Assert(result, `我是...`)
   152  
   153  		str = `{{"I'm中国人" | replace "I'm" "我是"}}`
   154  		result, err = gview.ParseContent(context.TODO(), str, nil)
   155  		t.Assert(err != nil, false)
   156  		t.Assert(result, `我是中国人`)
   157  
   158  		str = `{{compare "A" "B"}};{{compare "1" "2"}};{{compare 2 1}};{{compare 1 1}}`
   159  		result, err = gview.ParseContent(context.TODO(), str, nil)
   160  		t.Assert(err != nil, false)
   161  		t.Assert(result, `-1;-1;1;0`)
   162  
   163  		str = `{{"热爱GF热爱生活" | hidestr 20  "*"}};{{"热爱GF热爱生活" | hidestr 50  "*"}}`
   164  		result, err = gview.ParseContent(context.TODO(), str, nil)
   165  		t.Assert(err != nil, false)
   166  		t.Assert(result, `热爱GF*爱生活;热爱****生活`)
   167  
   168  		str = `{{"热爱GF热爱生活" | highlight "GF" "red"}}`
   169  		result, err = gview.ParseContent(context.TODO(), str, nil)
   170  		t.Assert(err != nil, false)
   171  		t.Assert(result, `热爱<span style="color:red;">GF</span>热爱生活`)
   172  
   173  		str = `{{"gf" | toupper}};{{"GF" | tolower}}`
   174  		result, err = gview.ParseContent(context.TODO(), str, nil)
   175  		t.Assert(err != nil, false)
   176  		t.Assert(result, `GF;gf`)
   177  
   178  		str = `{{concat "I" "Love" "GoFrame"}}`
   179  		result, err = gview.ParseContent(context.TODO(), str, nil)
   180  		t.AssertNil(err)
   181  		t.Assert(result, `ILoveGoFrame`)
   182  	})
   183  	// eq: multiple values.
   184  	gtest.C(t, func(t *gtest.T) {
   185  		str := `{{eq 1 2 1 3 4 5}}`
   186  		result, err := gview.ParseContent(context.TODO(), str, nil)
   187  		t.Assert(err != nil, false)
   188  		t.Assert(result, `true`)
   189  	})
   190  	gtest.C(t, func(t *gtest.T) {
   191  		str := `{{eq 6 2 1 3 4 5}}`
   192  		result, err := gview.ParseContent(context.TODO(), str, nil)
   193  		t.Assert(err != nil, false)
   194  		t.Assert(result, `false`)
   195  	})
   196  }
   197  
   198  func Test_FuncNl2Br(t *testing.T) {
   199  	gtest.C(t, func(t *gtest.T) {
   200  		str := `{{"Go\nFrame" | nl2br}}`
   201  		result, err := gview.ParseContent(context.TODO(), str, nil)
   202  		t.AssertNil(err)
   203  		t.Assert(result, `Go<br>Frame`)
   204  	})
   205  	gtest.C(t, func(t *gtest.T) {
   206  		s := ""
   207  		for i := 0; i < 3000; i++ {
   208  			s += "Go\nFrame\n中文"
   209  		}
   210  		str := `{{.content | nl2br}}`
   211  		result, err := gview.ParseContent(context.TODO(), str, g.Map{
   212  			"content": s,
   213  		})
   214  		t.AssertNil(err)
   215  		t.Assert(result, strings.Replace(s, "\n", "<br>", -1))
   216  	})
   217  }
   218  
   219  func Test_FuncInclude(t *testing.T) {
   220  	gtest.C(t, func(t *gtest.T) {
   221  		var (
   222  			header = `<h1>HEADER</h1>`
   223  			main   = `<h1>hello gf</h1>`
   224  			footer = `<h1>FOOTER</h1>`
   225  			layout = `{{include "header.html" .}}
   226  {{include "main.html" .}}
   227  {{include "footer.html" .}}
   228  {{include "footer_not_exist.html" .}}
   229  {{include "" .}}`
   230  			templatePath = gfile.Temp(guid.S())
   231  		)
   232  
   233  		gfile.Mkdir(templatePath)
   234  		defer gfile.Remove(templatePath)
   235  
   236  		t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `header.html`), header))
   237  		t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `main.html`), main))
   238  		t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `footer.html`), footer))
   239  		t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `layout.html`), layout))
   240  
   241  		view := gview.New(templatePath)
   242  		result, err := view.Parse(context.TODO(), "notfound.html")
   243  		t.AssertNE(err, nil)
   244  		t.Assert(result, ``)
   245  
   246  		result, err = view.Parse(context.TODO(), "layout.html")
   247  		t.AssertNil(err)
   248  		t.Assert(result, `<h1>HEADER</h1>
   249  <h1>hello gf</h1>
   250  <h1>FOOTER</h1>
   251  template file "footer_not_exist.html" not found
   252  `)
   253  
   254  		t.AssertNil(gfile.PutContents(gfile.Join(templatePath, `notfound.html`), "notfound"))
   255  		result, err = view.Parse(context.TODO(), "notfound.html")
   256  		t.AssertNil(err)
   257  		t.Assert(result, `notfound`)
   258  	})
   259  }
   260  
   261  func Test_SetPath(t *testing.T) {
   262  	gtest.C(t, func(t *gtest.T) {
   263  		view := gview.Instance("addpath")
   264  		err := view.AddPath("tmp")
   265  		t.AssertNE(err, nil)
   266  
   267  		err = view.AddPath("gview.go")
   268  		t.AssertNE(err, nil)
   269  
   270  		os.Setenv("GF_GVIEW_PATH", "tmp")
   271  		view = gview.Instance("setpath")
   272  		err = view.SetPath("tmp")
   273  		t.AssertNE(err, nil)
   274  
   275  		err = view.SetPath("gview.go")
   276  		t.AssertNE(err, nil)
   277  
   278  		view = gview.New(gfile.Pwd())
   279  		err = view.SetPath("tmp")
   280  		t.AssertNE(err, nil)
   281  
   282  		err = view.SetPath("gview.go")
   283  		t.AssertNE(err, nil)
   284  
   285  		os.Setenv("GF_GVIEW_PATH", "template")
   286  		gfile.Mkdir(gfile.Pwd() + gfile.Separator + "template")
   287  		view = gview.New()
   288  	})
   289  }
   290  
   291  func Test_ParseContent(t *testing.T) {
   292  	gtest.C(t, func(t *gtest.T) {
   293  		str := `{{.name}}`
   294  		view := gview.New()
   295  		result, err := view.ParseContent(context.TODO(), str, g.Map{"name": func() {}})
   296  		t.Assert(err != nil, true)
   297  		t.Assert(result, ``)
   298  	})
   299  }
   300  
   301  func Test_HotReload(t *testing.T) {
   302  	gtest.C(t, func(t *gtest.T) {
   303  		dirPath := gfile.Join(
   304  			gfile.Temp(),
   305  			"testdata",
   306  			"template-"+gconv.String(gtime.TimestampNano()),
   307  		)
   308  		defer gfile.Remove(dirPath)
   309  		filePath := gfile.Join(dirPath, "test.html")
   310  
   311  		// Initialize data.
   312  		err := gfile.PutContents(filePath, "test:{{.var}}")
   313  		t.AssertNil(err)
   314  
   315  		view := gview.New(dirPath)
   316  
   317  		time.Sleep(100 * time.Millisecond)
   318  		result, err := view.Parse(context.TODO(), "test.html", g.Map{
   319  			"var": "1",
   320  		})
   321  		t.AssertNil(err)
   322  		t.Assert(result, `test:1`)
   323  
   324  		// Update data.
   325  		err = gfile.PutContents(filePath, "test2:{{.var}}")
   326  		t.AssertNil(err)
   327  
   328  		time.Sleep(100 * time.Millisecond)
   329  		result, err = view.Parse(context.TODO(), "test.html", g.Map{
   330  			"var": "2",
   331  		})
   332  		t.AssertNil(err)
   333  		t.Assert(result, `test2:2`)
   334  	})
   335  }
   336  
   337  func Test_XSS(t *testing.T) {
   338  	gtest.C(t, func(t *gtest.T) {
   339  		v := gview.New()
   340  		s := "<br>"
   341  		r, err := v.ParseContent(context.TODO(), "{{.v}}", g.Map{
   342  			"v": s,
   343  		})
   344  		t.AssertNil(err)
   345  		t.Assert(r, s)
   346  	})
   347  	gtest.C(t, func(t *gtest.T) {
   348  		v := gview.New()
   349  		v.SetAutoEncode(true)
   350  		s := "<br>"
   351  		r, err := v.ParseContent(context.TODO(), "{{.v}}", g.Map{
   352  			"v": s,
   353  		})
   354  		t.AssertNil(err)
   355  		t.Assert(r, ghtml.Entities(s))
   356  	})
   357  	// Tag "if".
   358  	gtest.C(t, func(t *gtest.T) {
   359  		v := gview.New()
   360  		v.SetAutoEncode(true)
   361  		s := "<br>"
   362  		r, err := v.ParseContent(context.TODO(), "{{if eq 1 1}}{{.v}}{{end}}", g.Map{
   363  			"v": s,
   364  		})
   365  		t.AssertNil(err)
   366  		t.Assert(r, ghtml.Entities(s))
   367  	})
   368  }
   369  
   370  type TypeForBuildInFuncMap struct {
   371  	Name  string
   372  	Score float32
   373  }
   374  
   375  func (t *TypeForBuildInFuncMap) Test() (*TypeForBuildInFuncMap, error) {
   376  	return &TypeForBuildInFuncMap{"john", 99.9}, nil
   377  }
   378  
   379  func Test_BuildInFuncMap(t *testing.T) {
   380  	gtest.C(t, func(t *gtest.T) {
   381  		v := gview.New()
   382  		v.Assign("v", new(TypeForBuildInFuncMap))
   383  		r, err := v.ParseContent(context.TODO(), "{{range $k, $v := map .v.Test}} {{$k}}:{{$v}} {{end}}")
   384  		t.AssertNil(err)
   385  		t.Assert(gstr.Contains(r, "Name:john"), true)
   386  		t.Assert(gstr.Contains(r, "Score:99.9"), true)
   387  	})
   388  
   389  	gtest.C(t, func(t *gtest.T) {
   390  		v := gview.New()
   391  		r, err := v.ParseContent(context.TODO(), "{{range $k, $v := map }} {{$k}}:{{$v}} {{end}}")
   392  		t.AssertNil(err)
   393  		t.Assert(gstr.Contains(r, "Name:john"), false)
   394  		t.Assert(gstr.Contains(r, "Score:99.9"), false)
   395  	})
   396  }
   397  
   398  type TypeForBuildInFuncMaps struct {
   399  	Name  string
   400  	Score float32
   401  }
   402  
   403  func (t *TypeForBuildInFuncMaps) Test() ([]*TypeForBuildInFuncMaps, error) {
   404  	return []*TypeForBuildInFuncMaps{
   405  		{"john", 99.9},
   406  		{"smith", 100},
   407  	}, nil
   408  }
   409  
   410  func Test_BuildInFuncMaps(t *testing.T) {
   411  	gtest.C(t, func(t *gtest.T) {
   412  		v := gview.New()
   413  		v.Assign("v", new(TypeForBuildInFuncMaps))
   414  		r, err := v.ParseContent(context.TODO(), "{{range $k, $v := maps .v.Test}} {{$k}}:{{$v.Name}} {{$v.Score}} {{end}}")
   415  		t.AssertNil(err)
   416  		t.Assert(r, ` 0:john 99.9  1:smith 100 `)
   417  	})
   418  
   419  	gtest.C(t, func(t *gtest.T) {
   420  		v := gview.New()
   421  		v.Assign("v", new(TypeForBuildInFuncMaps))
   422  		r, err := v.ParseContent(context.TODO(), "{{range $k, $v := maps }} {{$k}}:{{$v.Name}} {{$v.Score}} {{end}}")
   423  		t.AssertNil(err)
   424  		t.Assert(r, ``)
   425  	})
   426  }
   427  
   428  func Test_BuildInFuncDump(t *testing.T) {
   429  	gtest.C(t, func(t *gtest.T) {
   430  		v := gview.New()
   431  		v.Assign("v", g.Map{
   432  			"name":  "john",
   433  			"score": 100,
   434  		})
   435  		r, err := v.ParseContent(context.TODO(), "{{dump .}}")
   436  		t.AssertNil(err)
   437  		fmt.Println(r)
   438  		t.Assert(gstr.Contains(r, `"name":  "john"`), true)
   439  		t.Assert(gstr.Contains(r, `"score": 100`), true)
   440  	})
   441  
   442  	gtest.C(t, func(t *gtest.T) {
   443  		mode := gmode.Mode()
   444  		gmode.SetTesting()
   445  		defer gmode.Set(mode)
   446  		v := gview.New()
   447  		v.Assign("v", g.Map{
   448  			"name":  "john",
   449  			"score": 100,
   450  		})
   451  		r, err := v.ParseContent(context.TODO(), "{{dump .}}")
   452  		t.AssertNil(err)
   453  		fmt.Println(r)
   454  		t.Assert(gstr.Contains(r, `"name":  "john"`), false)
   455  		t.Assert(gstr.Contains(r, `"score": 100`), false)
   456  	})
   457  }
   458  
   459  func Test_BuildInFuncJson(t *testing.T) {
   460  	gtest.C(t, func(t *gtest.T) {
   461  		v := gview.New()
   462  		v.Assign("v", g.Map{
   463  			"name": "john",
   464  		})
   465  		r, err := v.ParseContent(context.TODO(), "{{json .v}}")
   466  		t.AssertNil(err)
   467  		t.Assert(r, `{"name":"john"}`)
   468  	})
   469  }
   470  
   471  func Test_BuildInFuncXml(t *testing.T) {
   472  	gtest.C(t, func(t *gtest.T) {
   473  		v := gview.New()
   474  		v.Assign("v", g.Map{
   475  			"name": "john",
   476  		})
   477  		r, err := v.ParseContent(context.TODO(), "{{xml .v}}")
   478  		t.AssertNil(err)
   479  		t.Assert(r, `<name>john</name>`)
   480  	})
   481  }
   482  
   483  func Test_BuildInFuncIni(t *testing.T) {
   484  	gtest.C(t, func(t *gtest.T) {
   485  		v := gview.New()
   486  		v.Assign("v", g.Map{
   487  			"name": "john",
   488  		})
   489  		r, err := v.ParseContent(context.TODO(), "{{ini .v}}")
   490  		t.AssertNil(err)
   491  		t.Assert(r, `name=john
   492  `)
   493  	})
   494  }
   495  
   496  func Test_BuildInFuncYaml(t *testing.T) {
   497  	gtest.C(t, func(t *gtest.T) {
   498  		v := gview.New()
   499  		v.Assign("v", g.Map{
   500  			"name": "john",
   501  		})
   502  		r, err := v.ParseContent(context.TODO(), "{{yaml .v}}")
   503  		t.AssertNil(err)
   504  		t.Assert(r, `name: john
   505  `)
   506  	})
   507  }
   508  
   509  func Test_BuildInFuncYamlIndent(t *testing.T) {
   510  	gtest.C(t, func(t *gtest.T) {
   511  		v := gview.New()
   512  		v.Assign("v", g.Map{
   513  			"name": "john",
   514  		})
   515  		r, err := v.ParseContent(context.TODO(), `{{yamli .v "####"}}`)
   516  		t.AssertNil(err)
   517  		t.Assert(r, `####name: john
   518  `)
   519  	})
   520  }
   521  
   522  func Test_BuildInFuncToml(t *testing.T) {
   523  	gtest.C(t, func(t *gtest.T) {
   524  		v := gview.New()
   525  		v.Assign("v", g.Map{
   526  			"name": "john",
   527  		})
   528  		r, err := v.ParseContent(context.TODO(), "{{toml .v}}")
   529  		t.AssertNil(err)
   530  		t.Assert(r, `name = "john"
   531  `)
   532  	})
   533  }
   534  
   535  func Test_BuildInFuncPlus(t *testing.T) {
   536  	gtest.C(t, func(t *gtest.T) {
   537  		v := gview.New()
   538  		r, err := v.ParseContent(gctx.New(), "{{plus 1 2 3}}")
   539  		t.AssertNil(err)
   540  		t.Assert(r, `6`)
   541  	})
   542  	gtest.C(t, func(t *gtest.T) {
   543  		v := gview.New()
   544  		r, err := v.ParseContent(gctx.New(), "{{1| plus 2}}")
   545  		t.AssertNil(err)
   546  		t.Assert(r, `3`)
   547  	})
   548  }
   549  
   550  func Test_BuildInFuncMinus(t *testing.T) {
   551  	gtest.C(t, func(t *gtest.T) {
   552  		v := gview.New()
   553  		r, err := v.ParseContent(gctx.New(), "{{minus 1 2 3}}")
   554  		t.AssertNil(err)
   555  		t.Assert(r, `-4`)
   556  	})
   557  	gtest.C(t, func(t *gtest.T) {
   558  		v := gview.New()
   559  		r, err := v.ParseContent(gctx.New(), "{{2 | minus 3}}")
   560  		t.AssertNil(err)
   561  		t.Assert(r, `1`)
   562  	})
   563  }
   564  
   565  func Test_BuildInFuncTimes(t *testing.T) {
   566  	gtest.C(t, func(t *gtest.T) {
   567  		v := gview.New()
   568  		r, err := v.ParseContent(gctx.New(), "{{times 1 2 3 4}}")
   569  		t.AssertNil(err)
   570  		t.Assert(r, `24`)
   571  	})
   572  	gtest.C(t, func(t *gtest.T) {
   573  		v := gview.New()
   574  		r, err := v.ParseContent(gctx.New(), "{{2 | times 3}}")
   575  		t.AssertNil(err)
   576  		t.Assert(r, `6`)
   577  	})
   578  }
   579  
   580  func Test_BuildInFuncDivide(t *testing.T) {
   581  	gtest.C(t, func(t *gtest.T) {
   582  		v := gview.New()
   583  		r, err := v.ParseContent(gctx.New(), "{{divide 8 2 2}}")
   584  		t.AssertNil(err)
   585  		t.Assert(r, `2`)
   586  	})
   587  	gtest.C(t, func(t *gtest.T) {
   588  		v := gview.New()
   589  		r, err := v.ParseContent(gctx.New(), "{{2 | divide 4}}")
   590  		t.AssertNil(err)
   591  		t.Assert(r, `2`)
   592  	})
   593  	gtest.C(t, func(t *gtest.T) {
   594  		v := gview.New()
   595  		r, err := v.ParseContent(gctx.New(), "{{divide 8 0}}")
   596  		t.AssertNil(err)
   597  		t.Assert(r, `0`)
   598  	})
   599  }
   600  
   601  func Test_Issue1416(t *testing.T) {
   602  	gtest.C(t, func(t *gtest.T) {
   603  		v := gview.New()
   604  		err := v.SetPath(gtest.DataPath("issue1416"))
   605  		t.AssertNil(err)
   606  		r, err := v.ParseOption(context.TODO(), gview.Option{
   607  			File:   "gview.tpl",
   608  			Orphan: true,
   609  			Params: map[string]interface{}{
   610  				"hello": "world",
   611  			},
   612  		})
   613  		t.AssertNil(err)
   614  		t.Assert(r, `test.tpl content, vars: world`)
   615  	})
   616  }
   617  
   618  // template/gview_test.html
   619  // name:{{.name}}
   620  func init() {
   621  	if err := gres.Add("H4sIAAAAAAAC/wrwZmYRYeBg4GBIFA0LY0ACEgycDCWpuQU5iSWp+ullmanl8SWpxSV6GSW5OaEhrAyM5o1fk095n/HdumrdNeaLW7c2MDAw/P8f4M3OoZ+9QESIgYGBj4GBAWYBA0MTmgUcSBaADSxt/JoM0o6sKMCbkUmEGeFCZKNBLoSBbY0gkqB7EcZhdw8ECDD8d0xEMg7JdaxsIAVMDEwMfQwMDAvAygEBAAD//0d6jptEAQAA"); err != nil {
   622  		panic("add binary content to resource manager failed: " + err.Error())
   623  	}
   624  }
   625  
   626  func Test_GviewInGres(t *testing.T) {
   627  	gres.Dump()
   628  	gtest.C(t, func(t *gtest.T) {
   629  		v := gview.New()
   630  		v.SetPath("template")
   631  		result, err := v.Parse(context.TODO(), "gview_test.html", g.Map{
   632  			"name": "john",
   633  		})
   634  		t.AssertNil(err)
   635  		t.Assert(result, "name:john")
   636  	})
   637  }