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, `<div>测试</div>`) 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, `<div>测试</div>`) 107 108 str = `{{"<div>测试</div>"|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 }