Skip to content

Commit

Permalink
Refactor away goja from dispatch event
Browse files Browse the repository at this point in the history
This is a necessary fix to remove passing Goja values to
ExecutionContext.
  • Loading branch information
inancgumus committed Jan 25, 2024
1 parent 323e7c2 commit ddc9841
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 71 deletions.
110 changes: 65 additions & 45 deletions browser/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,29 +62,35 @@ func mapLocator(vu moduleVU, lo *common.Locator) mapping {
return nil, lo.Click(popts) //nolint:wrapcheck
}), nil
},
"dblclick": lo.Dblclick,
"check": lo.Check,
"uncheck": lo.Uncheck,
"isChecked": lo.IsChecked,
"isEditable": lo.IsEditable,
"isEnabled": lo.IsEnabled,
"isDisabled": lo.IsDisabled,
"isVisible": lo.IsVisible,
"isHidden": lo.IsHidden,
"fill": lo.Fill,
"focus": lo.Focus,
"getAttribute": lo.GetAttribute,
"innerHTML": lo.InnerHTML,
"innerText": lo.InnerText,
"textContent": lo.TextContent,
"inputValue": lo.InputValue,
"selectOption": lo.SelectOption,
"press": lo.Press,
"type": lo.Type,
"hover": lo.Hover,
"tap": lo.Tap,
"dispatchEvent": lo.DispatchEvent,
"waitFor": lo.WaitFor,
"dblclick": lo.Dblclick,
"check": lo.Check,
"uncheck": lo.Uncheck,
"isChecked": lo.IsChecked,
"isEditable": lo.IsEditable,
"isEnabled": lo.IsEnabled,
"isDisabled": lo.IsDisabled,
"isVisible": lo.IsVisible,
"isHidden": lo.IsHidden,
"fill": lo.Fill,
"focus": lo.Focus,
"getAttribute": lo.GetAttribute,
"innerHTML": lo.InnerHTML,
"innerText": lo.InnerText,
"textContent": lo.TextContent,
"inputValue": lo.InputValue,
"selectOption": lo.SelectOption,
"press": lo.Press,
"type": lo.Type,
"hover": lo.Hover,
"tap": lo.Tap,
"dispatchEvent": func(typ string, eventInit, opts goja.Value) error {
popts := common.NewFrameDispatchEventOptions(lo.DefaultTimeout())
if err := popts.Parse(vu.Context(), opts); err != nil {
return fmt.Errorf("parsing locator dispatch event options: %w", err)
}
return lo.DispatchEvent(typ, eventInit.Export(), popts) //nolint:wrapcheck
},
"waitFor": lo.WaitFor,
}
}

Expand Down Expand Up @@ -249,21 +255,23 @@ func mapElementHandle(vu moduleVU, eh *common.ElementHandle) mapping {
}
return mapFrame(vu, f), nil
},
"dblclick": eh.Dblclick,
"dispatchEvent": eh.DispatchEvent,
"fill": eh.Fill,
"focus": eh.Focus,
"getAttribute": eh.GetAttribute,
"hover": eh.Hover,
"innerHTML": eh.InnerHTML,
"innerText": eh.InnerText,
"inputValue": eh.InputValue,
"isChecked": eh.IsChecked,
"isDisabled": eh.IsDisabled,
"isEditable": eh.IsEditable,
"isEnabled": eh.IsEnabled,
"isHidden": eh.IsHidden,
"isVisible": eh.IsVisible,
"dblclick": eh.Dblclick,
"dispatchEvent": func(typ string, eventInit goja.Value) error {
return eh.DispatchEvent(typ, eventInit.Export()) //nolint:wrapcheck
},
"fill": eh.Fill,
"focus": eh.Focus,
"getAttribute": eh.GetAttribute,
"hover": eh.Hover,
"innerHTML": eh.InnerHTML,
"innerText": eh.InnerText,
"inputValue": eh.InputValue,
"isChecked": eh.IsChecked,
"isDisabled": eh.IsDisabled,
"isEditable": eh.IsEditable,
"isEnabled": eh.IsEnabled,
"isHidden": eh.IsHidden,
"isVisible": eh.IsVisible,
"ownerFrame": func() (mapping, error) {
f, err := eh.OwnerFrame()
if err != nil {
Expand Down Expand Up @@ -355,9 +363,15 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping {
return nil, err //nolint:wrapcheck
}), nil
},
"content": f.Content,
"dblclick": f.Dblclick,
"dispatchEvent": f.DispatchEvent,
"content": f.Content,
"dblclick": f.Dblclick,
"dispatchEvent": func(selector, typ string, eventInit, opts goja.Value) error {
popts := common.NewFrameDispatchEventOptions(f.Timeout())
if err := popts.Parse(vu.Context(), opts); err != nil {
return fmt.Errorf("parsing frame dispatch event options: %w", err)
}
return f.DispatchEvent(selector, typ, eventInit.Export(), popts) //nolint:wrapcheck
},
"evaluate": func(pageFunction goja.Value, gargs ...goja.Value) any {
args := make([]any, 0, len(gargs))
for _, a := range gargs {
Expand Down Expand Up @@ -518,10 +532,16 @@ func mapPage(vu moduleVU, p *common.Page) mapping {

return p.Close(opts) //nolint:wrapcheck
},
"content": p.Content,
"context": p.Context,
"dblclick": p.Dblclick,
"dispatchEvent": p.DispatchEvent,
"content": p.Content,
"context": p.Context,
"dblclick": p.Dblclick,
"dispatchEvent": func(selector, typ string, eventInit, opts goja.Value) error {
popts := common.NewFrameDispatchEventOptions(p.Timeout())
if err := popts.Parse(vu.Context(), opts); err != nil {
return fmt.Errorf("parsing page dispatch event options: %w", err)
}
return p.DispatchEvent(selector, typ, eventInit.Export(), popts) //nolint:wrapcheck
},
"dragAndDrop": p.DragAndDrop,
"emulateMedia": p.EmulateMedia,
"emulateVisionDeficiency": p.EmulateVisionDeficiency,
Expand Down
10 changes: 7 additions & 3 deletions common/element_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func (h *ElementHandle) defaultTimeout() time.Duration {
return h.frame.manager.timeoutSettings.timeout()
}

func (h *ElementHandle) dispatchEvent(_ context.Context, typ string, eventInit goja.Value) (any, error) {
func (h *ElementHandle) dispatchEvent(_ context.Context, typ string, eventInit any) (any, error) {
fn := `
(node, injected, type, eventInit) => {
injected.dispatchEvent(node, type, eventInit);
Expand Down Expand Up @@ -774,17 +774,21 @@ func (h *ElementHandle) Dblclick(opts goja.Value) {
applySlowMo(h.ctx)
}

func (h *ElementHandle) DispatchEvent(typ string, eventInit goja.Value) {
// DispatchEvent dispatches a DOM event to the element.
func (h *ElementHandle) DispatchEvent(typ string, eventInit any) error {
fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return handle.dispatchEvent(apiCtx, typ, eventInit)
}
opts := NewElementHandleBaseOptions(h.defaultTimeout())
actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout)
_, err := call(h.ctx, actFn, opts.Timeout)
if err != nil {
k6ext.Panic(h.ctx, "dispatching element event: %w", err)
return fmt.Errorf("dispatching element event %q: %w", typ, err)
}

applySlowMo(h.ctx)

return nil
}

func (h *ElementHandle) Fill(value string, opts goja.Value) {
Expand Down
1 change: 1 addition & 0 deletions common/execution_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ func (e *ExecutionContext) Eval(apiCtx context.Context, js string, args ...any)
for _, a := range args {
evalArgs = append(evalArgs, a)
}

return e.eval(apiCtx, opts, js, evalArgs...)
}

Expand Down
14 changes: 6 additions & 8 deletions common/frame.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,22 +719,20 @@ func (f *Frame) dblclick(selector string, opts *FrameDblclickOptions) error {
}

// DispatchEvent dispatches an event for the first element matching the selector.
func (f *Frame) DispatchEvent(selector, typ string, eventInit, opts goja.Value) {
func (f *Frame) DispatchEvent(selector, typ string, eventInit any, opts *FrameDispatchEventOptions) error {
f.log.Debugf("Frame:DispatchEvent", "fid:%s furl:%q sel:%q typ:%q", f.ID(), f.URL(), selector, typ)

popts := NewFrameDispatchEventOptions(f.defaultTimeout())
if err := popts.Parse(f.ctx, opts); err != nil {
k6ext.Panic(f.ctx, "parsing dispatch event options: %w", err)
}
if err := f.dispatchEvent(selector, typ, eventInit, popts); err != nil {
k6ext.Panic(f.ctx, "dispatching event %q to %q: %w", typ, selector, err)
if err := f.dispatchEvent(selector, typ, eventInit, opts); err != nil {
return fmt.Errorf("dispatching frame event %q to %q: %w", typ, selector, err)
}
applySlowMo(f.ctx)

return nil
}

// dispatchEvent is like DispatchEvent but takes parsed options and neither throws
// an error, or applies slow motion.
func (f *Frame) dispatchEvent(selector, typ string, eventInit goja.Value, opts *FrameDispatchEventOptions) error {
func (f *Frame) dispatchEvent(selector, typ string, eventInit any, opts *FrameDispatchEventOptions) error {
dispatchEvent := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return handle.dispatchEvent(apiCtx, typ, eventInit)
}
Expand Down
22 changes: 12 additions & 10 deletions common/locator.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ func (l *Locator) tap(opts *FrameTapOptions) error {

// DispatchEvent dispatches an event for the element matching the
// locator's selector with strict mode on.
func (l *Locator) DispatchEvent(typ string, eventInit, opts goja.Value) {
func (l *Locator) DispatchEvent(typ string, eventInit any, opts *FrameDispatchEventOptions) error {
l.log.Debugf(
"Locator:DispatchEvent", "fid:%s furl:%q sel:%q typ:%q eventInit:%+v opts:%+v",
l.frame.ID(), l.frame.URL(), l.selector, typ, eventInit, opts,
Expand All @@ -594,18 +594,14 @@ func (l *Locator) DispatchEvent(typ string, eventInit, opts goja.Value) {
var err error
defer func() { panicOrSlowMo(l.ctx, err) }()

popts := NewFrameDispatchEventOptions(l.frame.defaultTimeout())
if err = popts.Parse(l.ctx, opts); err != nil {
err = fmt.Errorf("parsing dispatch event options: %w", err)
return
}
if err = l.dispatchEvent(typ, eventInit, popts); err != nil {
err = fmt.Errorf("dispatching event %q to %q: %w", typ, l.selector, err)
return
if err = l.dispatchEvent(typ, eventInit, opts); err != nil {
return fmt.Errorf("dispatching locator event %q to %q: %w", typ, l.selector, err)
}

return nil
}

func (l *Locator) dispatchEvent(typ string, eventInit goja.Value, opts *FrameDispatchEventOptions) error {
func (l *Locator) dispatchEvent(typ string, eventInit any, opts *FrameDispatchEventOptions) error {
opts.Strict = true
return l.frame.dispatchEvent(l.selector, typ, eventInit, opts)
}
Expand All @@ -627,3 +623,9 @@ func (l *Locator) waitFor(opts *FrameWaitForSelectorOptions) error {
opts.Strict = true
return l.frame.waitFor(l.selector, opts)
}

// DefaultTimeout returns the default timeout for the locator.
// This is an internal API and should not be used by users.
func (l *Locator) DefaultTimeout() time.Duration {
return l.frame.defaultTimeout()
}
5 changes: 3 additions & 2 deletions common/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,11 @@ func (p *Page) Dblclick(selector string, opts goja.Value) {
p.MainFrame().Dblclick(selector, opts)
}

func (p *Page) DispatchEvent(selector string, typ string, eventInit goja.Value, opts goja.Value) {
// DispatchEvent dispatches an event on the page to the element that matches the provided selector.
func (p *Page) DispatchEvent(selector string, typ string, eventInit any, opts *FrameDispatchEventOptions) error {
p.logger.Debugf("Page:DispatchEvent", "sid:%v selector:%s", p.sessionID(), selector)

p.MainFrame().DispatchEvent(selector, typ, eventInit, opts)
return p.MainFrame().DispatchEvent(selector, typ, eventInit, opts)
}

// DragAndDrop is not implemented.
Expand Down
13 changes: 10 additions & 3 deletions tests/locator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ type jsFrameWaitForSelectorOpts struct {

func TestLocator(t *testing.T) {
t.Parallel()
t.Skip("TODO: fix goja escape")

tests := []struct {
name string
Expand Down Expand Up @@ -91,7 +90,11 @@ func TestLocator(t *testing.T) {
return asBool(t, v)
}
require.False(t, result(), "should not be clicked first")
p.Locator("#link", nil).DispatchEvent("click", tb.toGojaValue("mouseevent"), nil)
opts := &common.FrameDispatchEventOptions{
FrameBaseOptions: &common.FrameBaseOptions{},
}
err := p.Locator("#link", nil).DispatchEvent("click", "mouseevent", opts)
require.NoError(t, err)
require.True(t, result(), "cannot not dispatch event")
},
},
Expand Down Expand Up @@ -280,7 +283,11 @@ func TestLocator(t *testing.T) {
},
{
"DispatchEvent", func(l *common.Locator, tb *testBrowser) {
l.DispatchEvent("click", tb.toGojaValue("mouseevent"), timeout(tb))
err := l.DispatchEvent("click", "mouseevent", common.NewFrameDispatchEventOptions(100*time.Millisecond))
if err != nil {
// TODO: remove panic and update tests when all locator methods return error.
panic(err)
}
},
},
{
Expand Down

0 comments on commit ddc9841

Please sign in to comment.