From e4317ec4fd22cf26be4cc68edf8f4a8e225035b0 Mon Sep 17 00:00:00 2001 From: noe Date: Sun, 6 Apr 2025 22:27:42 -0700 Subject: [PATCH] fix template test renderer, add category --- roleypoly/fiber.go | 11 ++-- templates/components/blank.html | 1 + templates/components/category.go | 16 ++++++ templates/components/category.html | 14 ++++++ templates/components/category_test.go | 43 ++++++++++++++++ templates/components/role.go | 4 +- templates/components/role.html | 3 +- templates/components/role_test.go | 23 +++++---- templates/layouts/main_test.go | 4 +- templates/templatetesting/templates.go | 56 +++------------------ templates/templatetesting/templates_test.go | 16 ------ templates/tests/picker.html | 24 ++++++--- testing/testing.go | 36 ++++++++++--- utils/template_fns.go | 18 ++++--- utils/template_fns_test.go | 5 +- 15 files changed, 171 insertions(+), 103 deletions(-) create mode 100644 templates/components/blank.html create mode 100644 templates/components/category.go create mode 100644 templates/components/category.html create mode 100644 templates/components/category_test.go delete mode 100644 templates/templatetesting/templates_test.go diff --git a/roleypoly/fiber.go b/roleypoly/fiber.go index 88d3bb7..65afd6a 100644 --- a/roleypoly/fiber.go +++ b/roleypoly/fiber.go @@ -19,19 +19,24 @@ import ( "git.sapphic.engineer/roleypoly/v4/templates" "git.sapphic.engineer/roleypoly/v4/testing" "git.sapphic.engineer/roleypoly/v4/types" + "git.sapphic.engineer/roleypoly/v4/utils" ) func CreateFiberApp() *fiber.App { - viewEngine := html.NewFileSystem(http.FS(templates.FS), ".html") - app := fiber.New(fiber.Config{ - Views: viewEngine, + Views: CreateViewEngine(), ViewsLayout: "layouts/main", }) return app } +func CreateViewEngine() *html.Engine { + viewEngine := html.NewFileSystem(http.FS(templates.FS), ".html") + viewEngine.AddFuncMap(utils.TemplateFuncs()) + return viewEngine +} + func oneStatic(c fiber.Ctx) error { path := strings.Replace(c.OriginalURL(), "/", "", 1) f, err := staticfs.FS.Open(path) diff --git a/templates/components/blank.html b/templates/components/blank.html new file mode 100644 index 0000000..b448801 --- /dev/null +++ b/templates/components/blank.html @@ -0,0 +1 @@ +

hello world

diff --git a/templates/components/category.go b/templates/components/category.go new file mode 100644 index 0000000..93923f2 --- /dev/null +++ b/templates/components/category.go @@ -0,0 +1,16 @@ +package components + +import ( + "git.sapphic.engineer/roleypoly/v4/types" +) + +type CategoryTemplateData struct { + ID string + Name string + Type types.CategoryType + Roles []RoleTemplateData +} + +func Category(cat *types.Category, roles []*types.Role) CategoryTemplateData { + return CategoryTemplateData{} +} diff --git a/templates/components/category.html b/templates/components/category.html new file mode 100644 index 0000000..6f7dc93 --- /dev/null +++ b/templates/components/category.html @@ -0,0 +1,14 @@ +
+

{{.Name}}

+
+ {{ range $_, $role := .Roles }} {{template "components/role" $role}} {{end}} + {{ if eq .Type "single" }} + + + {{ end }} +
+
diff --git a/templates/components/category_test.go b/templates/components/category_test.go new file mode 100644 index 0000000..639a2e8 --- /dev/null +++ b/templates/components/category_test.go @@ -0,0 +1,43 @@ +package components_test + +import ( + "fmt" + "testing" + + "git.sapphic.engineer/roleypoly/v4/templates/components" + "git.sapphic.engineer/roleypoly/v4/templates/templatetesting" + "git.sapphic.engineer/roleypoly/v4/types" + "git.sapphic.engineer/roleypoly/v4/types/fixtures" + "git.sapphic.engineer/roleypoly/v4/utils" + "github.com/stretchr/testify/assert" +) + +func TestCategoryTemplate(t *testing.T) { + c := components.CategoryTemplateData{ + ID: "123", + Name: "Multi", + Type: types.CategoryMultiple, + Roles: []components.RoleTemplateData{ + components.Role(&fixtures.CategoryMulti, &fixtures.RoleWithDarkColor, true, true), + }, + } + html := templatetesting.Template(t, "components/category", c) + assert.Contains(t, html, "

Multi

", "has header") + assert.Contains(t, html, `data-testid="category-123"`, "has testid") + assert.NotContains(t, html, `Single", "has header") + assert.Contains(t, html, `data-testid="category-456"`, "has testid") + assert.NotContains(t, html, ` + "radio"}}name="category_group_{{.CategoryID}}"{{end}} {{if not + .Safe}}disabled="disabled"{{end}}/> diff --git a/templates/components/role_test.go b/templates/components/role_test.go index c52437e..c46a0ce 100644 --- a/templates/components/role_test.go +++ b/templates/components/role_test.go @@ -14,39 +14,44 @@ import ( func TestRoleTemplate(t *testing.T) { c := &fixtures.CategoryMulti r := &fixtures.RoleWithDarkColor - data := components.Role(c, r, true) + data := components.Role(c, r, true, true) html := templatetesting.Template(t, "components/role", data) assert.Contains(t, html, "--role-color: #a20000;", "role color is set") assert.Contains(t, html, `type="checkbox"`, "multi has input type=checkbox") assert.Contains(t, html, fmt.Sprintf("--contrast-color: %s;", utils.RgbToString(utils.AltColor(162, 0, 0))), "contrast color is set") - assert.Contains(t, html, fmt.Sprintf(`id="%s"`, utils.RoleInputID(c, r)), "input has ID attr") - assert.Contains(t, html, fmt.Sprintf(`for="%s"`, utils.RoleInputID(c, r)), "label has for attr") - assert.NotContains(t, html, fmt.Sprintf(`name="%s"`, utils.RoleInputName(c)), "multi has no name attr") + assert.Contains(t, html, fmt.Sprintf(`id="%s"`, utils.RoleInputID(c.ID, r.ID)), "input has ID attr") + assert.Contains(t, html, fmt.Sprintf(`for="%s"`, utils.RoleInputID(c.ID, r.ID)), "label has for attr") + assert.NotContains(t, html, fmt.Sprintf(`name="%s"`, utils.RoleInputName(c.ID)), "multi has no name attr") // TODO: selected? c = &fixtures.CategorySingle r = &fixtures.RoleWithLightColor - data = components.Role(c, r, false) + data = components.Role(c, r, false, true) html = templatetesting.Template(t, "components/role", data) assert.Contains(t, html, `type="radio"`, "single has input type=radio") assert.Contains(t, html, fmt.Sprintf("--contrast-color: %s;", utils.RgbToString(utils.AltColor(0xff, 0xaa, 0x88))), "contrast color") - assert.Contains(t, html, fmt.Sprintf(`name="%s"`, utils.RoleInputName(c)), "single has name attr") + assert.Contains(t, html, fmt.Sprintf(`name="%s"`, utils.RoleInputName(c.ID)), "single has name attr") + + data = components.Role(c, r, false, false) + html = templatetesting.Template(t, "components/role", data) + assert.Contains(t, html, `disabled="disabled"`) } func TestRole(t *testing.T) { - r := components.Role(&fixtures.CategoryMulti, &fixtures.RoleWithDarkColor, true) + r := components.Role(&fixtures.CategoryMulti, &fixtures.RoleWithDarkColor, true, true) assert.Equal(t, fixtures.RoleWithDarkColor.ID, r.ID) assert.Equal(t, fixtures.RoleWithDarkColor.Name, r.Name) assert.Equal(t, components.InputCheckbox, r.InputType) assert.Equal(t, "#a20000", r.Colors.Main) assert.True(t, r.Selected) - r = components.Role(&fixtures.CategorySingle, &fixtures.RoleWithDarkColor, false) + r = components.Role(&fixtures.CategorySingle, &fixtures.RoleWithDarkColor, false, true) assert.Equal(t, components.InputRadio, r.InputType) assert.False(t, r.Selected) - r = components.Role(&fixtures.CategorySingle, &fixtures.RoleWithLightColor, true) + r = components.Role(&fixtures.CategorySingle, &fixtures.RoleWithLightColor, true, false) assert.True(t, r.Selected) + assert.False(t, r.Safe) } func TestNewRoleColors(t *testing.T) { diff --git a/templates/layouts/main_test.go b/templates/layouts/main_test.go index 374d0a2..9e6df5e 100644 --- a/templates/layouts/main_test.go +++ b/templates/layouts/main_test.go @@ -8,9 +8,9 @@ import ( ) func TestMainLayout(t *testing.T) { - r := templatetesting.Template(t, "layouts/main", struct{ HeadTitle string }{HeadTitle: "roleypoly"}) - assert.Contains(t, r, "%%EMBED%%", "has {{embed}}") + r := templatetesting.Template(t, "components/blank", struct{ HeadTitle string }{HeadTitle: "roleypoly"}, "layouts/main") assert.Contains(t, r, "", "loaded navigation (close)") assert.Contains(t, r, "roleypoly", "sets title") + assert.Contains(t, r, "

hello world

", "has {{embed}}") } diff --git a/templates/templatetesting/templates.go b/templates/templatetesting/templates.go index d9f0ac6..ecbe18c 100644 --- a/templates/templatetesting/templates.go +++ b/templates/templatetesting/templates.go @@ -3,64 +3,20 @@ package templatetesting import ( "bytes" - "html/template" - "io/fs" - "strings" "testing" - "git.sapphic.engineer/roleypoly/v4/templates" + "git.sapphic.engineer/roleypoly/v4/roleypoly" + "github.com/stretchr/testify/assert" ) var ( - funcMap = template.FuncMap{ - "embed": func() string { - return "%%EMBED%%" - }, - } - Templates *template.Template = template.New("index").Funcs(funcMap) + viewEngine = roleypoly.CreateViewEngine() ) -func init() { - fs.WalkDir(templates.FS, ".", func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - - if d.IsDir() { - return nil - } - - fiberName := strings.Replace(path, ".html", "", 1) - f, err := templates.FS.ReadFile(path) - if err != nil { - return err - } - - if fiberName == "index" { - Templates, err = Templates.Parse(string(f)) - } else { - _, err = Templates.New(fiberName).Parse(string(f)) - } - - return err - }, - ) - -} - -func Template(t *testing.T, name string, data interface{}) string { +func Template(t *testing.T, name string, data interface{}, layout ...string) string { buf := bytes.Buffer{} - err := Templates.ExecuteTemplate(&buf, name, data) - if err != nil { - debugTemplates(t) - t.Fatal("failed to render: ", err) - } + err := viewEngine.Render(&buf, name, data, layout...) + assert.NoError(t, err) return buf.String() } - -func debugTemplates(t *testing.T) { - for i, tmpl := range Templates.Templates() { - t.Logf("template %d: name=%s", i, tmpl.Name()) - } -} diff --git a/templates/templatetesting/templates_test.go b/templates/templatetesting/templates_test.go deleted file mode 100644 index 295b65d..0000000 --- a/templates/templatetesting/templates_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package templatetesting_test - -import ( - "testing" - - "git.sapphic.engineer/roleypoly/v4/templates/templatetesting" - "github.com/stretchr/testify/assert" -) - -func TestRender(t *testing.T) { - for _, template := range templatetesting.Templates.Templates() { - assert.NotPanicsf(t, func() { - templatetesting.Template(t, template.Name(), nil) - }, "rendering %s", template.Name()) - } -} diff --git a/templates/tests/picker.html b/templates/tests/picker.html index 16575b0..cbe3716 100644 --- a/templates/tests/picker.html +++ b/templates/tests/picker.html @@ -5,12 +5,24 @@
-
- {{ template "components/role" .TestRole }} {{ template "components/role" - .TestRole2 }} {{ template "components/role" .TestRole3 }} +
+

Multi

+ {{ range $_, $r := .Category1 }} {{ template "components/role" $r }} {{ end + }}
-
- {{ template "components/role" .TestRole4 }} {{ template "components/role" - .TestRole5 }} {{ template "components/role" .TestRole6 }} +
+

Single

+ {{ range $_, $r := .Category2 }} {{ template "components/role" $r }} {{ end + }} +
+
+

Bad

+ {{ range $_, $r := .Category3 }} {{ template "components/role" $r }} {{ end + }} +
+
+

Hmm

+ {{ range $_, $r := .Category4 }} {{ template "components/role" $r }} {{ end + }}
diff --git a/testing/testing.go b/testing/testing.go index 71d4f82..cea9f71 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -38,13 +38,37 @@ func (t *TestingController) TestTemplate(c fiber.Ctx) error { which := c.Params("which") cat1 := fixtures.Category(fixtures.CategoryMulti) cat2 := fixtures.Category(fixtures.CategorySingle) + cat3 := fixtures.Category(fixtures.CategoryMulti) + cat4 := fixtures.Category(fixtures.CategorySingle) return c.Render("tests/"+which, fiber.Map{ - "TestRole": components.Role(cat1, &fixtures.RoleWithDarkColor, false), - "TestRole2": components.Role(cat1, &fixtures.RoleWithDarkMediumColor, false), - "TestRole3": components.Role(cat1, &fixtures.RoleWithLightColor, true), - "TestRole4": components.Role(cat1, &fixtures.RoleWithDarkColor, false), - "TestRole5": components.Role(cat2, &fixtures.RoleWithLightColor, true), - "TestRole6": components.Role(cat1, &fixtures.RoleWithLightMediumColor, false), + // multi + "Category1": []components.RoleTemplateData{ + components.Role(cat1, &fixtures.RoleWithDarkColor, true, true), + components.Role(cat1, &fixtures.RoleWithDarkMediumColor, true, true), + components.Role(cat1, &fixtures.RoleWithLightMediumColor, true, true), + components.Role(cat1, &fixtures.RoleWithLightColor, true, true), + }, + // single + "Category2": []components.RoleTemplateData{ + components.Role(cat2, &fixtures.RoleWithDarkColor, true, true), + components.Role(cat2, &fixtures.RoleWithDarkMediumColor, true, true), + components.Role(cat2, &fixtures.RoleWithLightMediumColor, true, true), + components.Role(cat2, &fixtures.RoleWithLightColor, true, true), + }, + // unsafe + "Category3": []components.RoleTemplateData{ + components.Role(cat3, &fixtures.RoleWithDarkColor, true, false), + components.Role(cat3, &fixtures.RoleWithDarkMediumColor, false, false), + components.Role(cat3, &fixtures.RoleWithLightMediumColor, false, false), + components.Role(cat3, &fixtures.RoleWithLightColor, true, false), + }, + // unselected + "Category4": []components.RoleTemplateData{ + components.Role(cat4, &fixtures.RoleWithDarkColor, true, true), + components.Role(cat4, &fixtures.RoleWithDarkMediumColor, false, true), + components.Role(cat4, &fixtures.RoleWithLightMediumColor, false, true), + components.Role(cat4, &fixtures.RoleWithLightColor, false, true), + }, }, "layouts/main") } diff --git a/utils/template_fns.go b/utils/template_fns.go index fbe7cc8..cd4ac8b 100644 --- a/utils/template_fns.go +++ b/utils/template_fns.go @@ -2,14 +2,20 @@ package utils import ( "fmt" - - "git.sapphic.engineer/roleypoly/v4/types" + "html/template" ) -func RoleInputID(c *types.Category, r *types.Role) string { - return fmt.Sprintf("category-%s_role-%s", c.ID, r.ID) +func RoleInputID(c string, r string) string { + return fmt.Sprintf("category-%s_role-%s", c, r) } -func RoleInputName(c *types.Category) string { - return fmt.Sprintf("category_group_%s", c.ID) +func RoleInputName(c string) string { + return fmt.Sprintf("category_group_%s", c) +} + +func TemplateFuncs() template.FuncMap { + return template.FuncMap{ + "roleInputID": RoleInputID, + "roleInputName": RoleInputName, + } } diff --git a/utils/template_fns_test.go b/utils/template_fns_test.go index 00d7131..3b2fe41 100644 --- a/utils/template_fns_test.go +++ b/utils/template_fns_test.go @@ -3,15 +3,14 @@ package utils_test import ( "testing" - "git.sapphic.engineer/roleypoly/v4/types" "git.sapphic.engineer/roleypoly/v4/utils" "github.com/stretchr/testify/assert" ) func TestRoleInputID(t *testing.T) { - assert.Equal(t, "category-123_role-456", utils.RoleInputID(&types.Category{ID: "123"}, &types.Role{ID: "456"})) + assert.Equal(t, "category-123_role-456", utils.RoleInputID("123", "456")) } func TestRoleInputName(t *testing.T) { - assert.Equal(t, "category_group_123", utils.RoleInputName(&types.Category{ID: "123"})) + assert.Equal(t, "category_group_123", utils.RoleInputName("123")) }