// Copyright 2022 E99p1ant. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package templates import ( gotemplate "html/template" "regexp" "testing" "github.com/flamego/template" templatepkg "github.com/tamakyi/TamaBox/internal/template" ) // TestTemplatesParse 复刻生产环境(internal/route/route.go 中 // template.Templater + templatepkg.FuncMap())的模板加载逻辑: // 逐个模板注册 FuncMap 并解析,任一文件解析失败即报错。 func TestTemplatesParse(t *testing.T) { fs, err := template.EmbedFS(FS, ".", []string{".html"}) if err != nil { t.Fatalf("EmbedFS: %v", err) } tpl := gotemplate.New("Flamego.Template") for _, f := range fs.Files() { tt := tpl.New(f.Name()) for _, funcMap := range templatepkg.FuncMap() { tt.Funcs(funcMap) } data, err := f.Data() if err != nil { t.Fatalf("get data of %q: %v", f.Name(), err) } if _, err := tt.Parse(string(data)); err != nil { t.Errorf("parse %q: %v", f.Name(), err) } } } var ( // definePattern 匹配 {{define "x"}} / {{block "x" ...}}:定义模板。 definePattern = regexp.MustCompile(`\{\{\s*(?:define|block)\s+"([^"]+)"`) // refPattern 匹配 {{template "x" ...}}:引用模板。 refPattern = regexp.MustCompile(`\{\{\s*template\s+"([^"]+)"`) ) // TestTemplateCrossReferences 检查所有 {{template "x"}} 引用的目标模板 // 是否真实存在(文件名或 define/block 定义),避免运行时 "no such template"。 func TestTemplateCrossReferences(t *testing.T) { fs, err := template.EmbedFS(FS, ".", []string{".html"}) if err != nil { t.Fatalf("EmbedFS: %v", err) } // 集合 = 所有模板文件名 + 文件内 define/block 定义的名称 names := make(map[string]bool) fileData := make(map[string][]byte) for _, f := range fs.Files() { names[f.Name()] = true data, err := f.Data() if err != nil { t.Fatalf("get data of %q: %v", f.Name(), err) } fileData[f.Name()] = data } for _, data := range fileData { for _, m := range definePattern.FindAllStringSubmatch(string(data), -1) { names[m[1]] = true } } // 检查所有引用是否落在集合内 for name, data := range fileData { for _, m := range refPattern.FindAllStringSubmatch(string(data), -1) { if !names[m[1]] { t.Errorf("%s: 引用了未定义的模板 %q", name, m[1]) } } } }