Skip to content
This repository has been archived by the owner on Jan 30, 2025. It is now read-only.

Commit

Permalink
Fix type assertions and remove nolint
Browse files Browse the repository at this point in the history
This commit properly type asserts and removes nolint directives. There
are new helpers to reduce code bloat and possible error messages
refactoring work:
+ asGojaValue: returns a given value as a goja value or panics.
+ gojaValueToString: returns a given a value as string or panics.

This commit also refactors tests to remove nolint directives.

Fixes: #417
  • Loading branch information
inancgumus committed Jun 30, 2022
1 parent 6baeca0 commit fc34711
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 72 deletions.
10 changes: 7 additions & 3 deletions common/browser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,17 @@ func TestBrowserNewPageInContext(t *testing.T) {
ctx context.Context, method string, params easyjson.Marshaler, res easyjson.Unmarshaler,
) error {
require.Equal(t, target.CommandCreateTarget, method)
tp := params.(*target.CreateTargetParams) //nolint:forcetypeassert
require.IsType(t, params, &target.CreateTargetParams{})
tp, _ := params.(*target.CreateTargetParams)
require.Equal(t, "about:blank", tp.URL)
require.Equal(t, browserContextID, tp.BrowserContextID)

// newPageInContext event handler will catch this target ID, and compare it to
// the new page's target ID to detect whether the page is loaded.
res.(*target.CreateTargetReturns).TargetID = targetID //nolint:forcetypeassert
// the new page's target ID to detect whether the page
// is loaded.
require.IsType(t, res, &target.CreateTargetReturns{})
v, _ := res.(*target.CreateTargetReturns)
v.TargetID = targetID

// for the event handler to work, there needs to be an event called
// EventBrowserContextPage to be fired. this normally happens when the browser's
Expand Down
91 changes: 58 additions & 33 deletions common/element_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,13 @@ func (h *ElementHandle) boundingBox() (*Rect, error) {
func (h *ElementHandle) checkHitTargetAt(apiCtx context.Context, point Position) (bool, error) {
frame := h.ownerFrame(apiCtx)
if frame != nil && frame.parentFrame != nil {
element := h.frame.FrameElement().(*ElementHandle) //nolint:forcetypeassert
var (
el = h.frame.FrameElement()
element, ok = el.(*ElementHandle)
)
if !ok {
return false, fmt.Errorf("unexpected type %T", el)
}
box, err := element.boundingBox()
if err != nil {
return false, err
Expand Down Expand Up @@ -91,9 +97,11 @@ func (h *ElementHandle) checkHitTargetAt(apiCtx context.Context, point Position)

// Either we're done or an error happened (returned as "error:..." from JS)
const done = "done"
//nolint:forcetypeassert
value := result.(goja.Value)
if value.ExportType().Kind() != reflect.String {
v, ok := result.(goja.Value)
if !ok {
return false, fmt.Errorf("unexpected type %T", result)
}
if v.ExportType().Kind() != reflect.String {
// We got a { hitTargetDescription: ... } result
// Meaning: Another element is preventing pointer events.
//
Expand All @@ -102,14 +110,14 @@ func (h *ElementHandle) checkHitTargetAt(apiCtx context.Context, point Position)
// because we don't need any more functionality from this JS function
// right now.
return false, errorFromDOMError("error:intercept")
} else if value.String() != done {
return false, errorFromDOMError(value.String())
} else if v.String() != done {
return false, errorFromDOMError(v.String())
}

return true, nil
}

func (h *ElementHandle) checkElementState(apiCtx context.Context, state string) (*bool, error) {
func (h *ElementHandle) checkElementState(_ context.Context, state string) (*bool, error) {
fn := `
(node, injected, state) => {
return injected.checkElementState(node, state);
Expand All @@ -123,16 +131,20 @@ func (h *ElementHandle) checkElementState(apiCtx context.Context, state string)
if err != nil {
return nil, err
}

value := result.(goja.Value)
switch value.ExportType().Kind() {
v, ok := result.(goja.Value)
if !ok {
return nil, fmt.Errorf("unexpected type %T", result)
}
//nolint:exhaustive
switch v.ExportType().Kind() {
case reflect.String: // An error happened (returned as "error:..." from JS)
return nil, errorFromDOMError(value.String())
return nil, errorFromDOMError(v.String())
case reflect.Bool:
returnVal := new(bool)
*returnVal = value.ToBoolean()
*returnVal = v.ToBoolean()
return returnVal, nil
}

return nil, fmt.Errorf("cannot check state %q of element: %q", state, reflect.TypeOf(result))
}

Expand Down Expand Up @@ -263,11 +275,11 @@ func (h *ElementHandle) fill(_ context.Context, value string) error {
if err != nil {
return err
}
r, ok := result.(goja.Value)
v, ok := result.(goja.Value)
if !ok {
return fmt.Errorf("expected goja value; got %T", result)
return fmt.Errorf("unexpected type %T", result)
}
if s := r.String(); s != resultDone {
if s := v.String(); s != resultDone {
// Either we're done or an error happened (returned as "error:..." from JS)
return errorFromDOMError(s)
}
Expand Down Expand Up @@ -642,7 +654,9 @@ func (h *ElementHandle) waitAndScrollIntoViewIfNeeded(apiCtx context.Context, fo
return nil
}

func (h *ElementHandle) waitForElementState(apiCtx context.Context, states []string, timeout time.Duration) (bool, error) {
func (h *ElementHandle) waitForElementState(
apiCtx context.Context, states []string, timeout time.Duration,
) (bool, error) {
fn := `
(node, injected, states, timeout) => {
return injected.waitForElementStates(node, states, timeout);
Expand All @@ -656,17 +670,21 @@ func (h *ElementHandle) waitForElementState(apiCtx context.Context, states []str
if err != nil {
return false, errorFromDOMError(err.Error())
}

value := result.(goja.Value)
switch value.ExportType().Kind() {
v, ok := result.(goja.Value)
if !ok {
return false, fmt.Errorf("unexpected type %T", result)
}
//nolint:exhaustive
switch v.ExportType().Kind() {
case reflect.String: // Either we're done or an error happened (returned as "error:..." from JS)
if value.String() == "done" {
if v.String() == "done" {
return true, nil
}
return false, errorFromDOMError(value.String())
return false, errorFromDOMError(v.String())
case reflect.Bool:
return value.ToBoolean(), nil
return v.ToBoolean(), nil
}

return false, fmt.Errorf("cannot check states %v of element: %q", states, reflect.TypeOf(result))
}

Expand Down Expand Up @@ -815,12 +833,13 @@ func (h *ElementHandle) GetAttribute(name string) goja.Value {
}
opts := NewElementHandleBaseOptions(h.defaultTimeout())
actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout)
value, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
v, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
if err != nil {
k6ext.Panic(h.ctx, "cannot get attribute of %q: %q", name, err)
}
applySlowMo(h.ctx)
return value.(goja.Value)

return asGojaValue(h.ctx, v)
}

// Hover scrolls element into view and hovers over its center point.
Expand All @@ -847,12 +866,13 @@ func (h *ElementHandle) InnerHTML() string {
}
opts := NewElementHandleBaseOptions(h.defaultTimeout())
actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout)
value, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
v, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
if err != nil {
k6ext.Panic(h.ctx, "cannot get element's inner HTML: %w", err)
}
applySlowMo(h.ctx)
return value.(goja.Value).String()

return gojaValueToString(h.ctx, v)
}

// InnerText returns the inner text of the element.
Expand All @@ -862,12 +882,13 @@ func (h *ElementHandle) InnerText() string {
}
opts := NewElementHandleBaseOptions(h.defaultTimeout())
actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout)
value, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
v, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
if err != nil {
k6ext.Panic(h.ctx, "cannot get element's inner text: %w", err)
}
applySlowMo(h.ctx)
return value.(goja.Value).String()

return gojaValueToString(h.ctx, v)
}

func (h *ElementHandle) InputValue(opts goja.Value) string {
Expand All @@ -879,12 +900,13 @@ func (h *ElementHandle) InputValue(opts goja.Value) string {
return handle.inputValue(apiCtx)
}
actFn := h.newAction([]string{}, fn, actionOpts.Force, actionOpts.NoWaitAfter, actionOpts.Timeout)
value, err := callApiWithTimeout(h.ctx, actFn, actionOpts.Timeout)
v, err := callApiWithTimeout(h.ctx, actFn, actionOpts.Timeout)
if err != nil {
k6ext.Panic(h.ctx, "cannot get element's input value: %w", err)
}
applySlowMo(h.ctx)
return value.(goja.Value).String()

return gojaValueToString(h.ctx, v)
}

// IsChecked checks if a checkbox or radio is checked.
Expand Down Expand Up @@ -1180,10 +1202,12 @@ func (h *ElementHandle) SelectOption(values goja.Value, opts goja.Value) []strin
k6ext.Panic(h.ctx, "cannot handle element select option: %w", err)
}
var returnVal []string
if err := rt.ExportTo(selectedOptions.(goja.Value), &returnVal); err != nil {
if err := rt.ExportTo(asGojaValue(h.ctx, selectedOptions), &returnVal); err != nil {
k6ext.Panic(h.ctx, "cannot unpack options in element select option: %w", err)
}

applySlowMo(h.ctx)

return returnVal
}

Expand Down Expand Up @@ -1232,12 +1256,13 @@ func (h *ElementHandle) TextContent() string {
}
opts := NewElementHandleBaseOptions(h.defaultTimeout())
actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout)
value, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
v, err := callApiWithTimeout(h.ctx, actFn, opts.Timeout)
if err != nil {
k6ext.Panic(h.ctx, "cannot get text content of element: %w", err)
}
applySlowMo(h.ctx)
return value.(goja.Value).String()

return gojaValueToString(h.ctx, v)
}

// Type scrolls element into view, focuses element and types text.
Expand Down
34 changes: 14 additions & 20 deletions common/frame.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,23 +817,17 @@ func (f *Frame) Content() string {

rt := f.vu.Runtime()
js := `() => {
let content = '';
if (document.doctype) {
content = new XMLSerializer().serializeToString(document.doctype);
}
if (document.documentElement) {
content += document.documentElement.outerHTML;
}
return content;
}`

c := f.Evaluate(rt.ToValue(js))
content, ok := c.(goja.Value)
if !ok {
k6ext.Panic(f.ctx, "unexpected content() value type: %T", c)
}
let content = '';
if (document.doctype) {
content = new XMLSerializer().serializeToString(document.doctype);
}
if (document.documentElement) {
content += document.documentElement.outerHTML;
}
return content;
}`

return content.ToString().String()
return gojaValueToString(f.ctx, f.Evaluate(rt.ToValue(js)))
}

// Dblclick double clicks an element matching provided selector.
Expand Down Expand Up @@ -1113,7 +1107,7 @@ func (f *Frame) innerHTML(selector string, opts *FrameInnerHTMLOptions) (string,
return "", fmt.Errorf("unexpected type %T", v)
}

return gv.ToString().String(), nil
return gv.String(), nil
}

// InnerText returns the inner text of the first element found
Expand Down Expand Up @@ -1155,7 +1149,7 @@ func (f *Frame) innerText(selector string, opts *FrameInnerTextOptions) (string,
return "", fmt.Errorf("unexpected type %T", v)
}

return gv.ToString().String(), nil
return gv.String(), nil
}

// InputValue returns the input value of the first element found
Expand Down Expand Up @@ -1192,7 +1186,7 @@ func (f *Frame) inputValue(selector string, opts *FrameInputValueOptions) (strin
return "", fmt.Errorf("unexpected type %T", v)
}

return gv.ToString().String(), nil
return gv.String(), nil
}

// IsDetached returns whether the frame is detached or not.
Expand Down Expand Up @@ -1669,7 +1663,7 @@ func (f *Frame) textContent(selector string, opts *FrameTextContentOptions) (str
return "", fmt.Errorf("unexpected type %T", v)
}

return gv.ToString().String(), nil
return gv.String(), nil
}

func (f *Frame) Title() string {
Expand Down
6 changes: 5 additions & 1 deletion common/frame_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,11 @@ func (fs *FrameSession) onTargetCrashed(event *inspector.EventTargetCrashed) {
fs.logger.Debugf("FrameSession:onTargetCrashed", "sid:%v tid:%v", fs.session.ID(), fs.targetID)

// TODO:?
fs.session.(*Session).markAsCrashed() //nolint:forcetypeassert
s, ok := fs.session.(*Session)
if !ok {
k6ext.Panic(fs.ctx, "unexpected type %T", fs.session)
}
s.markAsCrashed()
fs.page.didCrash()
}

Expand Down
16 changes: 16 additions & 0 deletions common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,19 @@ func TrimQuotes(s string) string {
func gojaValueExists(v goja.Value) bool {
return v != nil && !goja.IsUndefined(v) && !goja.IsNull(v)
}

// asGojaValue return v as a goja value.
// panics if v is not a goja value.
func asGojaValue(ctx context.Context, v interface{}) goja.Value {
gv, ok := v.(goja.Value)
if !ok {
k6ext.Panic(ctx, "unexpected type %T", v)
}
return gv
}

// gojaValueToString returns v as string.
// panics if v is not a goja value.
func gojaValueToString(ctx context.Context, v interface{}) string {
return asGojaValue(ctx, v).String()
}
5 changes: 2 additions & 3 deletions common/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -814,9 +814,8 @@ func (p *Page) TextContent(selector string, opts goja.Value) string {
func (p *Page) Title() string {
p.logger.Debugf("Page:Title", "sid:%v", p.sessionID())

rt := p.vu.Runtime()
js := `() => document.title`
return p.Evaluate(rt.ToValue(js)).(goja.Value).String()
v := p.vu.Runtime().ToValue(`() => document.title`)
return gojaValueToString(p.ctx, p.Evaluate(v))
}

func (p *Page) Type(selector string, text string, opts goja.Value) {
Expand Down
5 changes: 4 additions & 1 deletion common/page_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

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

// TestPageLocator can be removed later on when we add integration
Expand All @@ -23,7 +24,9 @@ func TestPageLocator(t *testing.T) {
mainFrame: &Frame{id: wantMainFrameID, ctx: ctx},
},
}
l := p.Locator(wantSelector, nil).(*Locator) //nolint:forcetypeassert
v := p.Locator(wantSelector, nil)
require.IsType(t, v, &Locator{})
l, _ := v.(*Locator)
assert.Equal(t, wantSelector, l.selector)
assert.Equal(t, wantMainFrameID, string(l.frame.id))

Expand Down
7 changes: 4 additions & 3 deletions common/screenshotter.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ func (s *screenshotter) fullPageSize(p *Page) (*Size, error) {
if err != nil {
return nil, err
}
r, ok := result.(goja.Value)
v, ok := result.(goja.Value)
if !ok {
return nil, fmt.Errorf("cannot convert result to goja value")
return nil, fmt.Errorf("unexpected type %T", result)
}
o := r.ToObject(rt)
o := v.ToObject(rt)

return &Size{
Width: o.Get("width").ToFloat(),
Height: o.Get("height").ToFloat(),
Expand Down
Loading

0 comments on commit fc34711

Please sign in to comment.