1package ui
2
3import (
4 "reflect"
5 "testing"
6)
7
8type orderedIME struct {
9 calls []string
10 active bool
11}
12
13func (i *orderedIME) Enable() {
14 if i.active {
15 panic("IME enable before disable")
16 }
17 i.active = true
18 i.calls = append(i.calls, "enable")
19}
20func (i *orderedIME) Disable() {
21 if !i.active {
22 panic("IME double disable")
23 }
24 i.active = false
25 i.calls = append(i.calls, "disable")
26}
27func (i *orderedIME) Surrounding(string, int, int) {}
28func (i *orderedIME) CursorRect(float64, float64, float64, float64) {}
29func (i *orderedIME) ContentType(bool, bool) {}
30
31type recordingIME struct {
32 surrounding []string
33 password bool
34}
35
36func (i *recordingIME) Enable() {}
37func (i *recordingIME) Disable() {}
38func (i *recordingIME) Surrounding(text string, _, _ int) {
39 i.surrounding = append(i.surrounding, text)
40}
41func (i *recordingIME) CursorRect(float64, float64, float64, float64) {}
42func (i *recordingIME) ContentType(password, _ bool) { i.password = password }
43
44func TestPasswordEditorNeverSendsSecretToIME(t *testing.T) {
45 r := newRuntime()
46 ime := &recordingIME{}
47 r.ime = ime
48 value := "hunter2"
49 view := func(f *Frame) { f.Root().Input("secret", &value, Key("secret"), Password(true)) }
50 r.Build(view)
51 r.route(key("Tab"))
52 r.Build(view)
53 if !ime.password {
54 t.Fatal("password content type not sent")
55 }
56 if len(ime.surrounding) == 0 {
57 t.Fatal("no surrounding text update")
58 }
59 for _, s := range ime.surrounding {
60 if s != "" {
61 t.Fatalf("surrounding text leaked %q", s)
62 }
63 }
64}
65
66func TestIMEFocusTransferDisablesBeforeEnable(t *testing.T) {
67 r := newRuntime()
68 ime := &orderedIME{}
69 r.ime = ime
70 a, b := "one", "two"
71 view := func(f *Frame) { root := f.Root(); root.Input("a", &a, Key("a")); root.Textarea("b", &b, Key("b")) }
72 r.Build(view)
73 r.route(key("Tab"))
74 r.Build(view)
75 r.route(key("Tab"))
76 r.Build(view)
77 r.route(key("Tab"))
78 r.Build(view)
79 if want := []string{"enable", "disable", "enable", "disable", "enable"}; !reflect.DeepEqual(ime.calls, want) {
80 t.Fatalf("focus transition calls %v want %v", ime.calls, want)
81 }
82 if !r.edits[idKey(r.Target(0))].IMEActive() || r.edits[idKey(r.Target(1))].IMEActive() {
83 t.Fatal("wrong active editor")
84 }
85}