Skip to content

Commit e895869

Browse files
author
rj
committed
Testing for OnChange on OnEnterKey events for textarea and textinput.
1 parent ec2a4bf commit e895869

File tree

4 files changed

+167
-6
lines changed

4 files changed

+167
-6
lines changed

textarea_test.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package goey
22

33
import (
4+
"bytes"
45
"testing"
56

67
"bitbucket.org/rj/goey/base"
@@ -17,15 +18,30 @@ func TestTextAreaMount(t *testing.T) {
1718
)
1819
}
1920

20-
func TestTextAreaEvents(t *testing.T) {
21+
func TestTextAreaOnFocus(t *testing.T) {
2122
testingCheckFocusAndBlur(t,
2223
&TextArea{},
2324
&TextArea{},
2425
&TextArea{},
2526
)
2627
}
2728

28-
func TestTextAreaProps(t *testing.T) {
29+
func TestTextAreaOnChange(t *testing.T) {
30+
log := bytes.NewBuffer(nil)
31+
32+
testingTypeKeys(t, "Hello",
33+
&TextArea{OnChange: func(v string) {
34+
log.WriteString(v)
35+
log.WriteString("\x1E")
36+
}})
37+
38+
const want = "H\x1EHe\x1EHel\x1EHell\x1EHello\x1E"
39+
if got := log.String(); got != want {
40+
t.Errorf("Wanted %v, got %v", want, got)
41+
}
42+
}
43+
44+
func TestTextAreaUpdateProps(t *testing.T) {
2945
testingUpdateWidgets(t, []base.Widget{
3046
&TextArea{Value: "A", MinLines: 5},
3147
&TextArea{Value: "B", MinLines: 3, Placeholder: "..."},

textinput_test.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package goey
22

33
import (
4+
"bytes"
45
"fmt"
56
"testing"
67

@@ -64,15 +65,44 @@ func TestTextInputClose(t *testing.T) {
6465
)
6566
}
6667

67-
func TestTextInputEvents(t *testing.T) {
68+
func TestTextInputOnFocus(t *testing.T) {
6869
testingCheckFocusAndBlur(t,
6970
&TextInput{},
7071
&TextInput{},
7172
&TextInput{},
7273
)
7374
}
7475

75-
func TestTextInputProps(t *testing.T) {
76+
func TestTextInputOnChange(t *testing.T) {
77+
log := bytes.NewBuffer(nil)
78+
79+
testingTypeKeys(t, "Hello",
80+
&TextInput{OnChange: func(v string) {
81+
log.WriteString(v)
82+
log.WriteString("\x1E")
83+
}})
84+
85+
const want = "H\x1EHe\x1EHel\x1EHell\x1EHello\x1E"
86+
if got := log.String(); got != want {
87+
t.Errorf("Wanted %v, got %v", want, got)
88+
}
89+
}
90+
91+
func TestTextInputOnEnterKey(t *testing.T) {
92+
log := bytes.NewBuffer(nil)
93+
94+
testingTypeKeys(t, "Hello\n",
95+
&TextInput{OnEnterKey: func(v string) {
96+
log.WriteString(v)
97+
}})
98+
99+
const want = "Hello"
100+
if got := log.String(); got != want {
101+
t.Errorf("Wanted %v, got %v", want, got)
102+
}
103+
}
104+
105+
func TestTextInputUpdateProps(t *testing.T) {
76106
testingUpdateWidgets(t, []base.Widget{
77107
&TextInput{Value: "A"},
78108
&TextInput{Value: "B", Placeholder: "..."},

widget_test.go

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ type Focusable interface {
2323
TakeFocus() bool
2424
}
2525

26+
type Typeable interface {
27+
TypeKeys(text string) chan error
28+
}
29+
2630
func equal(t *testing.T, lhs, rhs base.Widget) bool {
2731
if runtime.GOOS == "windows" {
2832
// On windows, the message EM_GETCUEBANNER does not work unless the manifest
@@ -229,6 +233,7 @@ func testingCloseWidgets(t *testing.T, widgets ...base.Widget) {
229233

230234
func testingCheckFocusAndBlur(t *testing.T, widgets ...base.Widget) {
231235
log := bytes.NewBuffer(nil)
236+
skipFlag := false
232237

233238
for i := byte(0); i < 3; i++ {
234239
s := reflect.ValueOf(widgets[i])
@@ -259,7 +264,7 @@ func testingCheckFocusAndBlur(t *testing.T, widgets ...base.Widget) {
259264
t.Errorf("Failed to set focus on the control")
260265
}
261266
} else {
262-
t.Errorf("Control does not support TakeFocus")
267+
skipFlag = true
263268
}
264269
return nil
265270
})
@@ -285,14 +290,72 @@ func testingCheckFocusAndBlur(t *testing.T, widgets ...base.Widget) {
285290
if err != nil {
286291
t.Errorf("Failed to run GUI loop, %s", err)
287292
}
293+
if skipFlag {
294+
t.Skip("Control does not support TakeFocus")
295+
}
296+
288297
const want = "fabafbbbfcbc"
289298
if s := log.String(); s != want {
290299
t.Errorf("Incorrect log string, want %s, got log==%s", want, s)
291300
}
292301
}
293302

303+
func testingTypeKeys(t *testing.T, text string, widget base.Widget) {
304+
skipFlag := false
305+
306+
init := func() error {
307+
window, err := NewWindow(t.Name(), &VBox{Children: []base.Widget{widget}})
308+
if err != nil {
309+
t.Errorf("Failed to create window, %s", err)
310+
}
311+
312+
var typingErr chan error
313+
go func(window *Window) {
314+
err := loop.Do(func() error {
315+
child := window.child.(*vboxElement).children[0]
316+
if elem, ok := child.(Typeable); ok {
317+
typingErr = elem.TypeKeys(text)
318+
} else {
319+
skipFlag = true
320+
}
321+
return nil
322+
})
323+
if err != nil {
324+
t.Errorf("Error in Do, %s", err)
325+
}
326+
327+
// Wait for typing to complete, and check for errors
328+
if typingErr != nil {
329+
for v := range typingErr {
330+
t.Errorf("Failed to type keys on the control, %v", v)
331+
}
332+
}
333+
334+
// Close the window
335+
err = loop.Do(func() error {
336+
window.Close()
337+
return nil
338+
})
339+
if err != nil {
340+
t.Errorf("Error in Do, %s", err)
341+
}
342+
}(window)
343+
344+
return nil
345+
}
346+
347+
err := loop.Run(init)
348+
if err != nil {
349+
t.Errorf("Failed to run GUI loop, %s", err)
350+
}
351+
if skipFlag {
352+
t.Skip("Control does not support TypeKeys")
353+
}
354+
}
355+
294356
func testingCheckClick(t *testing.T, widgets ...base.Widget) {
295357
log := bytes.NewBuffer(nil)
358+
skipFlag := false
296359

297360
for i := byte(0); i < 3; i++ {
298361
letter := 'a' + i
@@ -327,7 +390,7 @@ func testingCheckClick(t *testing.T, widgets ...base.Widget) {
327390
if elem, ok := child.(Clickable); ok {
328391
elem.Click()
329392
} else {
330-
t.Errorf("Control does not support Click")
393+
skipFlag = true
331394
}
332395
return nil
333396
})
@@ -353,6 +416,10 @@ func testingCheckClick(t *testing.T, widgets ...base.Widget) {
353416
if err != nil {
354417
t.Errorf("Failed to run GUI loop, %s", err)
355418
}
419+
if skipFlag {
420+
t.Skip("Control does not support Click")
421+
}
422+
356423
const want = "cacbcc"
357424
if s := log.String(); s != want {
358425
t.Errorf("Incorrect log string, want %s, got log==%s", want, s)

widget_windows.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package goey
22

33
import (
4+
"fmt"
45
"syscall"
6+
"time"
57
"unsafe"
68

79
"bitbucket.org/rj/goey/base"
810
win2 "bitbucket.org/rj/goey/internal/syscall"
11+
"bitbucket.org/rj/goey/loop"
912
"github.com/lxn/win"
1013
)
1114

@@ -72,6 +75,51 @@ func (w *Control) TakeFocus() bool {
7275
return win.SetFocus(w.hWnd) != 0
7376
}
7477

78+
func (w *Control) TypeKeys(text string) chan error {
79+
err := make(chan error, 1)
80+
81+
go func() {
82+
defer close(err)
83+
84+
loop.Do(func() error {
85+
if !w.TakeFocus() {
86+
err <- fmt.Errorf("windows error on take focus, %x", win.GetLastError())
87+
}
88+
return nil
89+
})
90+
91+
time.Sleep(10 * time.Millisecond)
92+
for _, r := range text {
93+
inp := [2]win.KEYBD_INPUT{
94+
{win.INPUT_KEYBOARD, win.KEYBDINPUT{}},
95+
{win.INPUT_KEYBOARD, win.KEYBDINPUT{}},
96+
}
97+
98+
if r == '\n' {
99+
inp[0].Ki.WVk = win.VK_RETURN
100+
inp[1].Ki.WVk = win.VK_RETURN
101+
inp[1].Ki.DwFlags = win.KEYEVENTF_KEYUP
102+
} else {
103+
inp[0].Ki.WScan = uint16(r)
104+
inp[0].Ki.DwFlags = win.KEYEVENTF_UNICODE
105+
inp[1].Ki.WScan = uint16(r)
106+
inp[1].Ki.DwFlags = win.KEYEVENTF_UNICODE | win.KEYEVENTF_KEYUP
107+
}
108+
109+
loop.Do(func() error {
110+
rc := win.SendInput(2, unsafe.Pointer(&inp), int32(unsafe.Sizeof(inp[0])))
111+
if rc != 2 {
112+
err <- fmt.Errorf("windows error, %x", win.GetLastError())
113+
}
114+
return nil
115+
})
116+
time.Sleep(10 * time.Millisecond)
117+
}
118+
}()
119+
120+
return err
121+
}
122+
75123
// SetOrder is a call around SetWindowPos used to ensure that a window appears
76124
// in the correct order.
77125
func (w *Control) SetOrder(previous win.HWND) win.HWND {

0 commit comments

Comments
 (0)