From 0b3e4f4b019337dc6ac7432357a4df53dc9d33bf Mon Sep 17 00:00:00 2001 From: Johan Lindh Date: Wed, 28 Feb 2024 12:29:44 +0100 Subject: [PATCH] add StringGetter --- stringgetter.go | 38 +++++++++++++++++++ stringgetter_test.go | 88 ++++++++++++++++++++++++++++++++++++++++++++ stringsetter.go | 18 +++++---- stringsetter_test.go | 62 ++++++++++++++++++++++++++++--- uiimg.go | 10 ++--- 5 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 stringgetter.go create mode 100644 stringgetter_test.go diff --git a/stringgetter.go b/stringgetter.go new file mode 100644 index 0000000..7ce22b2 --- /dev/null +++ b/stringgetter.go @@ -0,0 +1,38 @@ +package jaws + +import ( + "fmt" + "html/template" +) + +type StringGetter interface { + JawsGetString(e *Element) string +} + +type stringGetter struct{ v string } + +func (g stringGetter) JawsGetString(e *Element) string { + return g.v +} + +func (g stringGetter) JawsSetString(*Element, string) error { + return ErrValueNotSettable +} + +func (g stringGetter) JawsGetTag(rq *Request) any { + return nil +} + +func makeStringGetter(v any) StringGetter { + switch v := v.(type) { + case StringGetter: + return v + case string: + return stringGetter{v} + case template.HTML: + return stringGetter{string(v)} + case template.HTMLAttr: + return stringGetter{string(v)} + } + panic(fmt.Errorf("expected jaws.StringGetter or string, not %T", v)) +} diff --git a/stringgetter_test.go b/stringgetter_test.go new file mode 100644 index 0000000..42504f0 --- /dev/null +++ b/stringgetter_test.go @@ -0,0 +1,88 @@ +package jaws + +import ( + "html/template" + "reflect" + "strings" + "testing" +) + +var _ StringGetter = (*testSetter[string])(nil) + +func Test_makeStringGetter_panic(t *testing.T) { + defer func() { + if x := recover(); x != nil { + if err, ok := x.(error); ok { + if strings.Contains(err.Error(), "uint32") { + return + } + } + } + t.Fail() + }() + makeStringGetter(uint32(42)) +} + +func Test_makeStringGetter(t *testing.T) { + val := "" + ts := newTestSetter(val) + + tests := []struct { + name string + v any + want StringGetter + out string + err error + tag any + }{ + { + name: "StringGetter", + v: ts, + want: ts, + out: val, + tag: ts, + }, + { + name: "string", + v: val, + want: stringGetter{val}, + out: val, + err: ErrValueNotSettable, + tag: nil, + }, + { + name: "template.HTML", + v: template.HTML(val), + want: stringGetter{val}, + out: val, + err: ErrValueNotSettable, + tag: nil, + }, + { + name: "template.HTMLAttr", + v: template.HTMLAttr(val), + want: stringGetter{val}, + out: val, + err: ErrValueNotSettable, + tag: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := makeStringGetter(tt.v) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("makeStringGetter() = %v, want %v", got, tt.want) + } + if out := got.JawsGetString(nil); out != tt.out { + t.Errorf("makeStringGetter().JawsGetString() = %v, want %v", out, tt.out) + } + gotTag := any(got) + if tg, ok := got.(TagGetter); ok { + gotTag = tg.JawsGetTag(nil) + } + if gotTag != tt.tag { + t.Errorf("makeStringGetter().tag = %v, want %v", gotTag, tt.tag) + } + }) + } +} diff --git a/stringsetter.go b/stringsetter.go index 1083421..9cedf9c 100644 --- a/stringsetter.go +++ b/stringsetter.go @@ -7,32 +7,34 @@ import ( ) type StringSetter interface { - JawsGetString(e *Element) string + StringGetter JawsSetString(e *Element, v string) (err error) } -type stringGetter struct{ v string } - -func (g stringGetter) JawsGetString(e *Element) string { - return g.v +type stringSetter struct { + StringGetter } -func (g stringGetter) JawsSetString(*Element, string) error { +func (stringSetter) JawsSetString(e *Element, v string) (err error) { return ErrValueNotSettable } -func (g stringGetter) JawsGetTag(rq *Request) any { - return nil +func (g stringSetter) JawsGetTag(rq *Request) any { + return g.StringGetter } func makeStringSetter(v any) StringSetter { switch v := v.(type) { case StringSetter: return v + case StringGetter: + return stringSetter{v} case string: return stringGetter{v} case template.HTML: return stringGetter{string(v)} + case template.HTMLAttr: + return stringGetter{string(v)} case *atomic.Value: return atomicSetter{v} } diff --git a/stringsetter_test.go b/stringsetter_test.go index ec9a9cb..c33c865 100644 --- a/stringsetter_test.go +++ b/stringsetter_test.go @@ -24,12 +24,36 @@ func Test_makeStringSetter_panic(t *testing.T) { makeStringSetter(uint32(42)) } +type simpleGetter struct { + Value string +} + +func (g simpleGetter) JawsGetString(e *Element) string { + return g.Value +} + +type simpleNotagGetter struct { + v string +} + +func (g simpleNotagGetter) JawsGetString(e *Element) string { + return g.v +} + +func (g simpleNotagGetter) JawsGetTag(rq *Request) any { + return nil +} + func Test_makeStringSetter(t *testing.T) { val := "" var av atomic.Value av.Store(val) ts := newTestSetter(val) + sg := simpleGetter{Value: val} + + sng := simpleNotagGetter{v: val} + tests := []struct { name string v any @@ -38,6 +62,14 @@ func Test_makeStringSetter(t *testing.T) { err error tag any }{ + { + name: "StringGetter_untagged", + v: sng, + want: stringSetter{sng}, + out: val, + err: ErrValueNotSettable, + tag: nil, + }, { name: "StringSetter", v: ts, @@ -45,6 +77,14 @@ func Test_makeStringSetter(t *testing.T) { out: val, tag: ts, }, + { + name: "StringGetter", + v: sg, + want: stringSetter{sg}, + out: val, + err: ErrValueNotSettable, + tag: sg, + }, { name: "string", v: val, @@ -61,6 +101,14 @@ func Test_makeStringSetter(t *testing.T) { err: ErrValueNotSettable, tag: nil, }, + { + name: "template.HTMLAttr", + v: template.HTMLAttr(val), + want: stringGetter{val}, + out: val, + err: ErrValueNotSettable, + tag: nil, + }, { name: "*atomic.Value", v: &av, @@ -81,12 +129,14 @@ func Test_makeStringSetter(t *testing.T) { if err := got.JawsSetString(nil, "str"); err != tt.err { t.Errorf("makeStringSetter().JawsSetString() = %v, want %v", err, tt.err) } - gotTag := any(got) - if tg, ok := got.(TagGetter); ok { - gotTag = tg.JawsGetTag(nil) - } - if gotTag != tt.tag { - t.Errorf("makeStringSetter().tag = %v, want %v", gotTag, tt.tag) + + gotTag := MustTagExpand(nil, got) + if len(gotTag) == 1 { + if gotTag[0] != tt.tag { + t.Errorf("makeStringSetter().tag = %v, want %v", gotTag, tt.tag) + } + } else if tt.tag != nil { + t.Error(len(gotTag)) } }) } diff --git a/uiimg.go b/uiimg.go index cbad1fc..8ae410f 100644 --- a/uiimg.go +++ b/uiimg.go @@ -8,11 +8,11 @@ import ( type UiImg struct { UiHtml - StringSetter + StringGetter } func (ui *UiImg) JawsRender(e *Element, w io.Writer, params []any) error { - ui.parseGetter(e, ui.StringSetter) + ui.parseGetter(e, ui.StringGetter) srcattr := template.HTMLAttr("src=" + strconv.Quote(ui.JawsGetString(e))) // #nosec G203 attrs := append(e.ParseParams(params), srcattr) return WriteHtmlInner(w, e.Jid(), "img", "", "", attrs...) @@ -22,12 +22,12 @@ func (ui *UiImg) JawsUpdate(e *Element) { e.SetAttr("src", ui.JawsGetString(e)) } -func NewUiImg(g StringSetter) *UiImg { +func NewUiImg(g StringGetter) *UiImg { return &UiImg{ - StringSetter: g, + StringGetter: g, } } func (rq RequestWriter) Img(imageSrc any, params ...any) error { - return rq.UI(NewUiImg(makeStringSetter(imageSrc)), params...) + return rq.UI(NewUiImg(makeStringGetter(imageSrc)), params...) }