test(16.2-06): full unit coverage of the plugin field type framework
- pact: FormFieldError message joining, nil pointer, funcs never serialized - cabana: registry and option boot rules, compile (option kinds, general and core keys, CompileForm vs CompileFormWithTypes, settings and relation refusal), decode 422/500 split, localized and capped notices, Load, ListValue with the request ctx, field writes, field-types and upload routes - TestFieldTypeSavePostgres (Docker host): create, show, untouched and changed update, refused update, upload in and out of the record scope
This commit is contained in:
88
modules/pact/field_type_test.go
Normal file
88
modules/pact/field_type_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package pact
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormFieldErrorMessage(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
messages []string
|
||||
want string
|
||||
}{
|
||||
{nil, ""},
|
||||
{[]string{}, ""},
|
||||
{[]string{"acme.demo::lang.bad"}, "acme.demo::lang.bad"},
|
||||
{[]string{"first", "second", "third"}, "first; second; third"},
|
||||
} {
|
||||
err := &FormFieldError{Messages: tc.messages}
|
||||
if got := err.Error(); got != tc.want {
|
||||
t.Fatalf("Error(%q) = %q, want %q", tc.messages, got, tc.want)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("a nil pointer does not panic", func(t *testing.T) {
|
||||
var err *FormFieldError
|
||||
if got := err.Error(); got != "" {
|
||||
t.Fatalf("nil Error() = %q", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("it is found through a wrapped error", func(t *testing.T) {
|
||||
wrapped := fmt.Errorf("decode: %w", &FormFieldError{Messages: []string{"a", "b"}})
|
||||
var refused *FormFieldError
|
||||
if !errors.As(wrapped, &refused) || refused.Error() != "a; b" {
|
||||
t.Fatalf("errors.As = %v, %v", refused, wrapped)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestFormFieldTypeContract pins the plugin-facing shape: the funcs are
|
||||
// never serialized, and a plugin implements HasFormFieldTypes.
|
||||
func TestFormFieldTypeContract(t *testing.T) {
|
||||
typ := FormFieldType{
|
||||
Name: "notes",
|
||||
Element: "acme-demo-notes",
|
||||
Translatable: true,
|
||||
Scripts: []string{"assets/js/notes.js"},
|
||||
Styles: []string{"assets/css/notes.css"},
|
||||
Options: []string{"rows"},
|
||||
CheckOptions: func(map[string]any) error { return nil },
|
||||
Decode: func(context.Context, FormFieldValue) (FormFieldDecoded, error) {
|
||||
return FormFieldDecoded{}, nil
|
||||
},
|
||||
Load: func(context.Context, FormFieldValue) (any, error) { return nil, nil },
|
||||
ListValue: func(context.Context, any) string { return "" },
|
||||
Upload: func(context.Context, FormFieldUpload) (FormFieldUploadResult, error) {
|
||||
return FormFieldUploadResult{}, nil
|
||||
},
|
||||
}
|
||||
raw, err := json.Marshal(typ)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var keys map[string]any
|
||||
if err := json.Unmarshal(raw, &keys); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, fn := range []string{"CheckOptions", "Decode", "Load", "ListValue", "Upload"} {
|
||||
if _, ok := keys[fn]; ok {
|
||||
t.Fatalf("%s is serialized: %s", fn, raw)
|
||||
}
|
||||
}
|
||||
if keys["Name"] != "notes" || keys["Element"] != "acme-demo-notes" || keys["Translatable"] != true {
|
||||
t.Fatalf("json = %s", raw)
|
||||
}
|
||||
|
||||
var src HasFormFieldTypes = fieldTypePlugin{types: []FormFieldType{typ}}
|
||||
if got := src.FormFieldTypes(); len(got) != 1 || got[0].Name != "notes" {
|
||||
t.Fatalf("FormFieldTypes() = %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
type fieldTypePlugin struct{ types []FormFieldType }
|
||||
|
||||
func (p fieldTypePlugin) FormFieldTypes() []FormFieldType { return p.types }
|
||||
Reference in New Issue
Block a user