Files
kjol/go/webui/signaturepad_test.go

89 lines
2.9 KiB
Go

package webui
import (
"strings"
"testing"
"kjol/vdom"
)
// The pad's value IS the markup it shows — that is the whole reason it draws into an SVG
// rather than a canvas. If the two could differ, the user would sign one thing and the
// caller would store another.
func TestSignaturePadValueIsWhatIsDrawn(t *testing.T) {
var got string
pad := NewSignaturePad(SignaturePadOptions{OnChange: func(svg string) { got = svg }})
pad.strokes.Set([]sigStroke{{{X: 10, Y: 20}, {X: 30, Y: 40}, {X: 50, Y: 20}}})
value := pad.SVG()
shown := vdom.RenderHTML(pad.Render(SignaturePadProps{}))
// Every path in the value is present in the rendered element.
paths := sigPaths(pad.strokes.Get())
if paths == "" {
t.Fatal("no path was generated for a three-point stroke")
}
if !strings.Contains(value, paths) {
t.Error("the emitted SVG does not contain the strokes it was built from")
}
if !strings.Contains(shown, `d="M10,20`) {
t.Errorf("the rendered pad is not showing the stroke:\n%s", shown)
}
_ = got
}
// An empty pad is an empty string, not a blank drawing. A caller storing the value must
// be able to ask "did they sign?" without parsing SVG.
func TestSignaturePadEmptyIsEmptyString(t *testing.T) {
pad := NewSignaturePad(SignaturePadOptions{})
if !pad.IsEmpty() {
t.Error("a fresh pad should be empty")
}
if pad.SVG() != "" {
t.Errorf("an empty pad produced %q, want \"\"", pad.SVG())
}
}
// Clear reports the emptiness to the caller. Without the callback a cleared pad would
// leave the last signature sitting in whatever the caller stored it in.
func TestSignaturePadClearNotifies(t *testing.T) {
got := "not called"
pad := NewSignaturePad(SignaturePadOptions{OnChange: func(svg string) { got = svg }})
pad.strokes.Set([]sigStroke{{{X: 1, Y: 1}, {X: 2, Y: 2}}})
pad.Clear()
if got != "" {
t.Errorf("OnChange got %q on clear, want \"\"", got)
}
if !pad.IsEmpty() {
t.Error("the pad is not empty after Clear")
}
}
// A single point is a tap, not a mark: it has no length, produces no path, and must not
// count as a signature.
func TestSignaturePadIgnoresSinglePointStrokes(t *testing.T) {
if got := sigPaths([]sigStroke{{{X: 5, Y: 5}}}); got != "" {
t.Errorf("a one-point stroke produced a path: %q", got)
}
}
// Two points are a straight line; three or more are smoothed into curves. Handwriting
// drawn as raw polylines looks like a seismograph.
func TestSignaturePadSmoothsLongStrokes(t *testing.T) {
line := sigPaths([]sigStroke{{{X: 0, Y: 0}, {X: 10, Y: 10}}})
if !strings.Contains(line, " L10,10") {
t.Errorf("a two-point stroke should be a straight line: %q", line)
}
if strings.Contains(line, "Q") {
t.Errorf("a two-point stroke has nothing to smooth: %q", line)
}
curve := sigPaths([]sigStroke{{{X: 0, Y: 0}, {X: 10, Y: 10}, {X: 20, Y: 0}}})
if !strings.Contains(curve, "Q") {
t.Errorf("a three-point stroke should be smoothed: %q", curve)
}
}