1// Copyright 2023 The Gitea Authors. All rights reserved.
2// SPDX-License-Identifier: MIT
3
4package templates
5
6import (
7 "errors"
8 "html/template"
9 "os"
10 "strings"
11 "testing"
12
13 "forgejo.org/modules/assetfs"
14
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
17)
18
19func TestExtractErrorLine(t *testing.T) {
20 cases := []struct {
21 code string
22 line int
23 pos int
24 target string
25 expect string
26 }{
27 {"hello world\nfoo bar foo bar\ntest", 2, -1, "bar", `
28foo bar foo bar
29 ^^^ ^^^
30`},
31
32 {"hello world\nfoo bar foo bar\ntest", 2, 4, "bar", `
33foo bar foo bar
34 ^
35`},
36
37 {
38 "hello world\nfoo bar foo bar\ntest", 2, 4, "",
39 `
40foo bar foo bar
41 ^
42`,
43 },
44
45 {
46 "hello world\nfoo bar foo bar\ntest", 5, 0, "",
47 `unable to find target line 5`,
48 },
49 }
50
51 for _, c := range cases {
52 actual := extractErrorLine([]byte(c.code), c.line, c.pos, c.target)
53 assert.Equal(t, strings.TrimSpace(c.expect), strings.TrimSpace(actual))
54 }
55}
56
57func TestHandleError(t *testing.T) {
58 dir := t.TempDir()
59
60 p := &templateErrorPrettier{assets: assetfs.Layered(assetfs.Local("tmp", dir))}
61
62 test := func(s string, h func(error) string, expect string) {
63 err := os.WriteFile(dir+"/test.tmpl", []byte(s), 0o644)
64 require.NoError(t, err)
65 tmpl := template.New("test")
66 _, err = tmpl.Parse(s)
67 require.Error(t, err)
68 msg := h(err)
69 assert.Equal(t, strings.TrimSpace(expect), strings.TrimSpace(msg))
70 }
71
72 test("{{", p.handleGenericTemplateError, `
73template error: tmp:test:1 : unclosed action
74----------------------------------------------------------------------
75{{
76----------------------------------------------------------------------
77`)
78
79 test("{{Func}}", p.handleFuncNotDefinedError, `
80template error: tmp:test:1 : function "Func" not defined
81----------------------------------------------------------------------
82{{Func}}
83 ^^^^
84----------------------------------------------------------------------
85`)
86
87 test("{{'x'3}}", p.handleUnexpectedOperandError, `
88template error: tmp:test:1 : unexpected "3" in operand
89----------------------------------------------------------------------
90{{'x'3}}
91 ^
92----------------------------------------------------------------------
93`)
94
95 // no idea about how to trigger such strange error, so mock an error to test it
96 err := os.WriteFile(dir+"/test.tmpl", []byte("god knows XXX"), 0o644)
97 require.NoError(t, err)
98 expectedMsg := `
99template error: tmp:test:1 : expected end; found XXX
100----------------------------------------------------------------------
101god knows XXX
102 ^^^
103----------------------------------------------------------------------
104`
105 actualMsg := p.handleExpectedEndError(errors.New("template: test:1: expected end; found XXX"))
106 assert.Equal(t, strings.TrimSpace(expectedMsg), strings.TrimSpace(actualMsg))
107}