chromedp/input_test.go
Daniel Martí 97e80a00d5 make NewAllocator's cancel func block on Wait
This way, the simple examples and tests don't need to do that
separately. Practically all users will want this cleanup work to be
synchronous, and practically all Go APIs are synchronous by default, so
this makes chromedp easier to use.
2019-04-06 22:13:40 +02:00

266 lines
6.1 KiB
Go

package chromedp
import (
"fmt"
"strconv"
"testing"
"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/cdproto/input"
)
// inViewportJS is a javascript snippet that will get the specified node
// position relative to the viewport and returns true if the specified node
// is within the window's viewport.
const inViewportJS = `(function(a) {
var r = a[0].getBoundingClientRect();
return r.top >= 0 && r.left >= 0 && r.bottom <= window.innerHeight && r.right <= window.innerWidth;
})($x('%s'))`
func TestMouseClickXY(t *testing.T) {
t.Parallel()
ctx, cancel := testAllocate(t, "input.html")
defer cancel()
if err := Run(ctx, WaitVisible(`#input1`, ByID)); err != nil {
t.Fatal(err)
}
tests := []struct {
x, y int64
}{
{100, 100},
{0, 0},
{9999, 100},
{100, 9999},
}
for i, test := range tests {
var xstr, ystr string
if err := Run(ctx,
MouseClickXY(test.x, test.y),
Value("#input1", &xstr, ByID),
); err != nil {
t.Fatalf("test %d got error: %v", i, err)
}
x, err := strconv.ParseInt(xstr, 10, 64)
if err != nil {
t.Fatalf("test %d got error: %v", i, err)
}
if x != test.x {
t.Fatalf("test %d expected x to be: %d, got: %d", i, test.x, x)
}
if err := Run(ctx, Value("#input2", &ystr, ByID)); err != nil {
t.Fatalf("test %d got error: %v", i, err)
}
y, err := strconv.ParseInt(ystr, 10, 64)
if err != nil {
t.Fatalf("test %d got error: %v", i, err)
}
if y != test.y {
t.Fatalf("test %d expected y to be: %d, got: %d", i, test.y, y)
}
}
}
func TestMouseClickNode(t *testing.T) {
t.Parallel()
tests := []struct {
sel, exp string
opt MouseOption
by QueryOption
}{
{"button2", "foo", ButtonType(input.ButtonNone), ByID},
{"button2", "bar", ButtonType(input.ButtonLeft), ByID},
{"button2", "bar-middle", ButtonType(input.ButtonMiddle), ByID},
{"input3", "foo", ButtonModifiers(input.ModifierNone), ByID},
{"input3", "bar-right", ButtonType(input.ButtonRight), ByID},
{"input3", "bar-right", Button("right"), ByID},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
test := test
t.Parallel()
ctx, cancel := testAllocate(t, "input.html")
defer cancel()
var nodes []*cdp.Node
if err := Run(ctx, Nodes(test.sel, &nodes, test.by)); err != nil {
t.Fatalf("got error: %v", err)
}
if len(nodes) != 1 {
t.Fatalf("expected nodes to have exactly 1 element, got: %d", len(nodes))
}
var value string
if err := Run(ctx,
MouseClickNode(nodes[0], test.opt),
Value("#input3", &value, ByID),
); err != nil {
t.Fatalf("got error: %v", err)
}
if value != test.exp {
t.Fatalf("expected to have value %s, got: %s", test.exp, value)
}
})
}
}
func TestMouseClickOffscreenNode(t *testing.T) {
t.Parallel()
tests := []struct {
sel string
exp int
by QueryOption
}{
{"#button3", 0, ByID},
{"#button3", 2, ByID},
{"#button3", 10, ByID},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
test := test
t.Parallel()
ctx, cancel := testAllocate(t, "input.html")
defer cancel()
var nodes []*cdp.Node
if err := Run(ctx, Nodes(test.sel, &nodes, test.by)); err != nil {
t.Fatalf("got error: %v", err)
}
if len(nodes) != 1 {
t.Fatalf("expected nodes to have exactly 1 element, got: %d", len(nodes))
}
var ok bool
if err := Run(ctx, EvaluateAsDevTools(fmt.Sprintf(inViewportJS, nodes[0].FullXPath()), &ok)); err != nil {
t.Fatalf("got error: %v", err)
}
if ok {
t.Fatal("expected node to be offscreen")
}
for i := test.exp; i > 0; i-- {
if err := Run(ctx, MouseClickNode(nodes[0])); err != nil {
t.Fatalf("got error: %v", err)
}
}
var value int
if err := Run(ctx, Evaluate("window.document.test_i", &value)); err != nil {
t.Fatalf("got error: %v", err)
}
if value != test.exp {
t.Fatalf("expected to have value %d, got: %d", test.exp, value)
}
})
}
}
func TestKeyAction(t *testing.T) {
t.Parallel()
tests := []struct {
sel, exp string
by QueryOption
}{
{"#input4", "foo", ByID},
{"#input4", "foo and bar", ByID},
{"#input4", "1234567890", ByID},
{"#input4", "~!@#$%^&*()_+=[];'", ByID},
{"#input4", "你", ByID},
{"#input4", "\n\nfoo\n\nbar\n\n", ByID},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
test := test
t.Parallel()
ctx, cancel := testAllocate(t, "input.html")
defer cancel()
var nodes []*cdp.Node
if err := Run(ctx, Nodes(test.sel, &nodes, test.by)); err != nil {
t.Fatalf("got error: %v", err)
}
if len(nodes) != 1 {
t.Fatalf("expected nodes to have exactly 1 element, got: %d", len(nodes))
}
if err := Run(ctx,
Focus(test.sel, test.by),
KeyAction(test.exp),
); err != nil {
t.Fatalf("got error: %v", err)
}
var value string
if err := Run(ctx, Value(test.sel, &value, test.by)); err != nil {
t.Fatalf("got error: %v", err)
}
if value != test.exp {
t.Fatalf("expected to have value %s, got: %s", test.exp, value)
}
})
}
}
func TestKeyActionNode(t *testing.T) {
t.Parallel()
tests := []struct {
sel, exp string
by QueryOption
}{
{"#input4", "foo", ByID},
{"#input4", "foo and bar", ByID},
{"#input4", "1234567890", ByID},
{"#input4", "~!@#$%^&*()_+=[];'", ByID},
{"#input4", "你", ByID},
{"#input4", "\n\nfoo\n\nbar\n\n", ByID},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
test := test
t.Parallel()
ctx, cancel := testAllocate(t, "input.html")
defer cancel()
var nodes []*cdp.Node
if err := Run(ctx, Nodes(test.sel, &nodes, test.by)); err != nil {
t.Fatalf("got error: %v", err)
}
if len(nodes) != 1 {
t.Fatalf("expected nodes to have exactly 1 element, got: %d", len(nodes))
}
var value string
if err := Run(ctx,
KeyActionNode(nodes[0], test.exp),
Value(test.sel, &value, test.by),
); err != nil {
t.Fatalf("got error: %v", err)
}
if value != test.exp {
t.Fatalf("expected to have value %s, got: %s", test.exp, value)
}
})
}
}