Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mouse #1318

Merged
merged 3 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions common/mouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package common

import (
"context"
"fmt"
"time"

"github.com/grafana/xk6-browser/k6ext"

"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/cdproto/input"
"github.com/dop251/goja"

"github.com/grafana/xk6-browser/k6ext"
)

// Mouse represents a mouse input device.
Expand Down Expand Up @@ -41,7 +42,7 @@ func (m *Mouse) click(x float64, y float64, opts *MouseClickOptions) error {
return err
}
for i := 0; i < int(mouseDownUpOpts.ClickCount); i++ {
if err := m.down(x, y, mouseDownUpOpts); err != nil {
if err := m.down(mouseDownUpOpts); err != nil {
return err
}
if opts.Delay != 0 {
Expand All @@ -52,28 +53,29 @@ func (m *Mouse) click(x float64, y float64, opts *MouseClickOptions) error {
case <-t.C:
}
}
if err := m.up(x, y, mouseDownUpOpts); err != nil {
if err := m.up(mouseDownUpOpts); err != nil {
return err
}
}

return nil
}

func (m *Mouse) down(x float64, y float64, opts *MouseDownUpOptions) error {
func (m *Mouse) down(opts *MouseDownUpOptions) error {
m.button = input.MouseButton(opts.Button)
action := input.DispatchMouseEvent(input.MousePressed, m.x, m.y).
WithButton(input.MouseButton(opts.Button)).
WithModifiers(input.Modifier(m.keyboard.modifiers)).
WithClickCount(opts.ClickCount)
if err := action.Do(cdp.WithExecutor(m.ctx, m.session)); err != nil {
return err
return fmt.Errorf("mouse down: %w", err)
}
return nil
}

func (m *Mouse) move(x float64, y float64, opts *MouseMoveOptions) error {
var fromX float64 = m.x
var fromY float64 = m.y
fromX := m.x
fromY := m.y
m.x = x
m.y = y
for i := int64(1); i <= opts.Steps; i++ {
Expand All @@ -83,21 +85,23 @@ func (m *Mouse) move(x float64, y float64, opts *MouseMoveOptions) error {
WithButton(m.button).
WithModifiers(input.Modifier(m.keyboard.modifiers))
if err := action.Do(cdp.WithExecutor(m.ctx, m.session)); err != nil {
return err
return fmt.Errorf("mouse move: %w", err)
}
}

return nil
}

func (m *Mouse) up(x float64, y float64, opts *MouseDownUpOptions) error {
func (m *Mouse) up(opts *MouseDownUpOptions) error {
m.button = input.None
action := input.DispatchMouseEvent(input.MouseReleased, m.x, m.y).
WithButton(input.MouseButton(opts.Button)).
WithModifiers(input.Modifier(m.keyboard.modifiers)).
WithClickCount(opts.ClickCount)
if err := action.Do(cdp.WithExecutor(m.ctx, m.session)); err != nil {
return err
return fmt.Errorf("mouse up: %w", err)
}

return nil
}

Expand All @@ -112,6 +116,7 @@ func (m *Mouse) Click(x float64, y float64, opts goja.Value) {
}
}

// DblClick will trigger Click twice in quick succession.
func (m *Mouse) DblClick(x float64, y float64, opts goja.Value) {
mouseOpts := NewMouseDblClickOptions()
if err := mouseOpts.Parse(m.ctx, opts); err != nil {
Expand All @@ -123,35 +128,35 @@ func (m *Mouse) DblClick(x float64, y float64, opts goja.Value) {
}

// Down will trigger a MouseDown event in the browser.
func (m *Mouse) Down(x float64, y float64, opts goja.Value) {
func (m *Mouse) Down(opts goja.Value) {
mouseOpts := NewMouseDownUpOptions()
if err := mouseOpts.Parse(m.ctx, opts); err != nil {
k6ext.Panic(m.ctx, "parsing mouse down options: %w", err)
}
if err := m.down(x, y, mouseOpts); err != nil {
k6ext.Panic(m.ctx, "pressing the mouse button on x:%f y:%f: %w", x, y, err)
if err := m.down(mouseOpts); err != nil {
k6ext.Panic(m.ctx, "pressing the mouse button on x:%f y:%f: %w", m.x, m.y, err)
}
}

// Move will trigger a MouseMoved event in the browser.
func (m *Mouse) Move(x float64, y float64, opts goja.Value) {
mouseOpts := NewMouseDownUpOptions()
mouseOpts := NewMouseMoveOptions()
if err := mouseOpts.Parse(m.ctx, opts); err != nil {
k6ext.Panic(m.ctx, "parsing mouse move options: %w", err)
}
if err := m.down(x, y, mouseOpts); err != nil {
if err := m.move(x, y, mouseOpts); err != nil {
k6ext.Panic(m.ctx, "moving the mouse pointer to x:%f y:%f: %w", x, y, err)
}
}

// Up will trigger a MouseUp event in the browser.
func (m *Mouse) Up(x float64, y float64, opts goja.Value) {
func (m *Mouse) Up(opts goja.Value) {
mouseOpts := NewMouseDownUpOptions()
if err := mouseOpts.Parse(m.ctx, opts); err != nil {
k6ext.Panic(m.ctx, "parsing mouse up options: %w", err)
}
if err := m.up(x, y, mouseOpts); err != nil {
k6ext.Panic(m.ctx, "releasing the mouse button on x:%f y:%f: %w", x, y, err)
if err := m.up(mouseOpts); err != nil {
k6ext.Panic(m.ctx, "releasing the mouse button on x:%f y:%f: %w", m.x, m.y, err)
}
}

Expand Down
129 changes: 107 additions & 22 deletions tests/mouse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,115 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/grafana/xk6-browser/common"
)

func TestMouseDblClick(t *testing.T) {
func TestMouseActions(t *testing.T) {
t.Parallel()

b := newTestBrowser(t, withFileServer())
p := b.NewPage(nil)
opts := &common.FrameGotoOptions{
Timeout: common.DefaultTimeout,
}
_, err := p.Goto(
b.staticURL("dbl_click.html"),
opts,
)
require.NoError(t, err)

p.Mouse.DblClick(35, 17, nil)

v := p.Evaluate(`() => window.dblclick`)
bv := asBool(t, v)
assert.True(t, bv, "failed to double click the link")

got := p.InnerText("#counter", nil)
assert.Equal(t, "2", got)
t.Run("click", func(t *testing.T) {
t.Parallel()

tb := newTestBrowser(t)
p := tb.NewPage(nil)
m := p.GetMouse()

// Set up a page with a button that changes text when clicked
buttonHTML := `
<button onclick="this.innerHTML='Clicked!'">Click me</button>
`
p.SetContent(buttonHTML, nil)
button, err := p.Query("button")
require.NoError(t, err)

// Simulate a click at the button coordinates
box := button.BoundingBox()
m.Click(box.X, box.Y, nil)

// Verify the button's text changed
assert.Equal(t, "Clicked!", button.TextContent())
})

t.Run("double_click", func(t *testing.T) {
ankur22 marked this conversation as resolved.
Show resolved Hide resolved
t.Parallel()

tb := newTestBrowser(t)
p := tb.NewPage(nil)
m := p.GetMouse()

// Set up a page with a button that changes text on double click and also counts clicks
buttonHTML := `
<script>window.clickCount = 0;</script>
<button
onclick="document.getElementById('clicks').innerHTML = ++window.clickCount;"
ondblclick="this.innerHTML='Double Clicked!';">Click me</button>
<div id="clicks"></div>
`
p.SetContent(buttonHTML, nil)
button, err := p.Query("button")
require.NoError(t, err)

// Get the button's bounding box for accurate clicking
box := button.BoundingBox()

// Simulate a double click at the button coordinates
m.DblClick(box.X, box.Y, nil)

// Verify the button's text changed
assert.Equal(t, "Double Clicked!", button.TextContent())

// Also verify that the element was clicked twice
clickCountDiv, err := p.Query("div#clicks")
require.NoError(t, err)
assert.Equal(t, "2", clickCountDiv.TextContent())
})

t.Run("move", func(t *testing.T) {
t.Parallel()

tb := newTestBrowser(t)
p := tb.NewPage(nil)
m := p.GetMouse()

// Set up a page with an area that detects mouse move
areaHTML := `
<div
onmousemove="this.innerHTML='Mouse Moved';"
style="width:100px;height:100px;"
></div>
`
p.SetContent(areaHTML, nil)
area, err := p.Query("div")
require.NoError(t, err)

// Simulate mouse move within the div
box := area.BoundingBox()
m.Move(box.X+50, box.Y+50, nil) // Move to the center of the div
assert.Equal(t, "Mouse Moved", area.TextContent())
})

t.Run("move_down_up", func(t *testing.T) {
t.Parallel()

tb := newTestBrowser(t)
p := tb.NewPage(nil)
m := p.GetMouse()

// Set up a page with a button that tracks mouse down and up
buttonHTML := `
<button
onmousedown="this.innerHTML='Mouse Down';"
onmouseup="this.innerHTML='Mouse Up';"
>Mouse</button>
`
p.SetContent(buttonHTML, nil)
button, err := p.Query("button")
require.NoError(t, err)

box := button.BoundingBox()
m.Move(box.X, box.Y, nil)
m.Down(nil)
assert.Equal(t, "Mouse Down", button.TextContent())
m.Up(nil)
assert.Equal(t, "Mouse Up", button.TextContent())
})
}
26 changes: 0 additions & 26 deletions tests/static/dbl_click.html

This file was deleted.

Loading