|
1 | 1 | package form
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "errors" |
| 5 | + "fmt" |
4 | 6 | "html/template"
|
5 | 7 | "reflect"
|
6 | 8 | "strings"
|
@@ -49,3 +51,82 @@ func TestBuilder_Inputs(t *testing.T) {
|
49 | 51 | })
|
50 | 52 | }
|
51 | 53 | }
|
| 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