Skip to content

Commit 86fb723

Browse files
committed
Adding 1.13 support; specifically, I am using errors.As for passed in errors to ensure that wrapped errors still work
1 parent dfe0cd9 commit 86fb723

File tree

3 files changed

+89
-5
lines changed

3 files changed

+89
-5
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ language: go
22

33
go:
44
- master
5-
- "1.10"
5+
- "1.13"

builder.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
package form
88

99
import (
10+
"errors"
11+
"fmt"
1012
"html/template"
1113
"strings"
1214
)
@@ -81,7 +83,7 @@ func (b *Builder) Inputs(v interface{}, errs ...error) (template.HTML, error) {
8183
return "", err
8284
}
8385
fields := fields(v)
84-
errors := errors(errs)
86+
errors := fieldErrors(errs)
8587
var html template.HTML
8688
for _, field := range fields {
8789
var sb strings.Builder
@@ -180,11 +182,12 @@ type fieldError interface {
180182
// Any errors that implement this interface are then used to build the
181183
// slice of errors for the field, meaning you can provide multiple
182184
// errors for the same field and all will be utilized.
183-
func errors(errs []error) map[string][]string {
185+
func fieldErrors(errs []error) map[string][]string {
184186
ret := make(map[string][]string)
185187
for _, err := range errs {
186-
fe, ok := err.(fieldError)
187-
if !ok {
188+
var fe fieldError
189+
if !errors.As(err, &fe) {
190+
fmt.Println(err, "isnt field error")
188191
continue
189192
}
190193
field, fieldErr := fe.FieldError()

builder_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package form
22

33
import (
4+
"errors"
5+
"fmt"
46
"html/template"
57
"reflect"
68
"strings"
@@ -49,3 +51,82 @@ func TestBuilder_Inputs(t *testing.T) {
4951
})
5052
}
5153
}
54+
55+
type testFieldError struct {
56+
field, err string
57+
}
58+
59+
func (e testFieldError) Error() string {
60+
return fmt.Sprintf("invalid field: %v", e.field)
61+
}
62+
63+
func (e testFieldError) FieldError() (field, err string) {
64+
return e.field, e.err
65+
}
66+
67+
func TestBuilder_Inputs_errors(t *testing.T) {
68+
// Sanity check on our test type first
69+
tfe := testFieldError{
70+
field: "field",
71+
err: "err",
72+
}
73+
var fe fieldError
74+
if !errors.As(tfe, &fe) {
75+
t.Fatalf("As(testFieldError, fieldError) = false")
76+
}
77+
if !errors.As(fmt.Errorf("wrapped: %w", tfe), &fe) {
78+
t.Fatalf("As(wrapped, fieldError) = false")
79+
}
80+
81+
tpl := template.Must(template.New("").Funcs(FuncMap()).Parse(strings.TrimSpace(`
82+
<label>{{.Label}}</label>{{range errors}}<p>{{.}}</p>{{end}}
83+
`)))
84+
tests := []struct {
85+
name string
86+
tpl *template.Template
87+
arg interface{}
88+
errors []error
89+
want template.HTML
90+
}{
91+
{
92+
name: "label and input",
93+
tpl: tpl,
94+
arg: struct {
95+
Name string
96+
Email string `form:"type=email;[email protected]"`
97+
}{
98+
Name: "Michael Scott",
99+
},
100+
errors: []error{
101+
fmt.Errorf("wrapped: %w", testFieldError{
102+
field: "Name",
103+
err: "is required",
104+
}),
105+
fmt.Errorf("first: %w", fmt.Errorf("second: %w", testFieldError{
106+
field: "Email",
107+
err: "is taken",
108+
})),
109+
},
110+
want: template.HTML(strings.Join([]string{
111+
strings.TrimSpace(`
112+
<label>Name</label><p>is required</p>`),
113+
strings.TrimSpace(`
114+
<label>Email</label><p>is taken</p>`),
115+
}, "")),
116+
},
117+
}
118+
for _, tc := range tests {
119+
t.Run(tc.name, func(t *testing.T) {
120+
b := &Builder{
121+
InputTemplate: tc.tpl,
122+
}
123+
got, err := b.Inputs(tc.arg, tc.errors...)
124+
if err != nil {
125+
t.Errorf("Builder.Inputs() err = %v, want %v", err, nil)
126+
}
127+
if !reflect.DeepEqual(got, tc.want) {
128+
t.Errorf("Builder.Inputs() = %v, want %v", got, tc.want)
129+
}
130+
})
131+
}
132+
}

0 commit comments

Comments
 (0)