use consistent context.Context var names
This commit is contained in:
parent
61f0a8da68
commit
c109f6ebfd
16
actions.go
16
actions.go
|
@ -18,8 +18,8 @@ type Action interface {
|
||||||
type ActionFunc func(context.Context, cdp.Executor) error
|
type ActionFunc func(context.Context, cdp.Executor) error
|
||||||
|
|
||||||
// Do executes the func f using the provided context and frame handler.
|
// Do executes the func f using the provided context and frame handler.
|
||||||
func (f ActionFunc) Do(ctxt context.Context, h cdp.Executor) error {
|
func (f ActionFunc) Do(ctx context.Context, h cdp.Executor) error {
|
||||||
return f(ctxt, h)
|
return f(ctx, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tasks is a sequential list of Actions that can be used as a single Action.
|
// Tasks is a sequential list of Actions that can be used as a single Action.
|
||||||
|
@ -27,12 +27,12 @@ type Tasks []Action
|
||||||
|
|
||||||
// Do executes the list of Actions sequentially, using the provided context and
|
// Do executes the list of Actions sequentially, using the provided context and
|
||||||
// frame handler.
|
// frame handler.
|
||||||
func (t Tasks) Do(ctxt context.Context, h cdp.Executor) error {
|
func (t Tasks) Do(ctx context.Context, h cdp.Executor) error {
|
||||||
// TODO: put individual task timeouts from context here
|
// TODO: put individual task timeouts from context here
|
||||||
for _, a := range t {
|
for _, a := range t {
|
||||||
// ctxt, cancel = context.WithTimeout(ctxt, timeout)
|
// ctx, cancel = context.WithTimeout(ctx, timeout)
|
||||||
// defer cancel()
|
// defer cancel()
|
||||||
if err := a.Do(ctxt, h); err != nil {
|
if err := a.Do(ctx, h); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,11 @@ func (t Tasks) Do(ctxt context.Context, h cdp.Executor) error {
|
||||||
// be marked for deprecation in the future, after the remaining Actions have
|
// be marked for deprecation in the future, after the remaining Actions have
|
||||||
// been able to be written/tested.
|
// been able to be written/tested.
|
||||||
func Sleep(d time.Duration) Action {
|
func Sleep(d time.Duration) Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
select {
|
select {
|
||||||
case <-time.After(d):
|
case <-time.After(d):
|
||||||
case <-ctxt.Done():
|
case <-ctx.Done():
|
||||||
return ctxt.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
4
eval.go
4
eval.go
|
@ -27,7 +27,7 @@ func Evaluate(expression string, res interface{}, opts ...EvaluateOption) Action
|
||||||
panic("res cannot be nil")
|
panic("res cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
// set up parameters
|
// set up parameters
|
||||||
p := runtime.Evaluate(expression)
|
p := runtime.Evaluate(expression)
|
||||||
switch res.(type) {
|
switch res.(type) {
|
||||||
|
@ -42,7 +42,7 @@ func Evaluate(expression string, res interface{}, opts ...EvaluateOption) Action
|
||||||
}
|
}
|
||||||
|
|
||||||
// evaluate
|
// evaluate
|
||||||
v, exp, err := p.Do(ctxt, h)
|
v, exp, err := p.Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ func (t *Target) Execute(ctx context.Context, method string, params json.Marshal
|
||||||
// below are the old TargetHandler methods.
|
// below are the old TargetHandler methods.
|
||||||
|
|
||||||
// processEvent processes an incoming event.
|
// processEvent processes an incoming event.
|
||||||
func (t *Target) processEvent(ctxt context.Context, msg *cdproto.Message) error {
|
func (t *Target) processEvent(ctx context.Context, msg *cdproto.Message) error {
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
return ErrChannelClosed
|
return ErrChannelClosed
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ func (t *Target) processEvent(ctxt context.Context, msg *cdproto.Message) error
|
||||||
case *inspector.EventDetached:
|
case *inspector.EventDetached:
|
||||||
return nil
|
return nil
|
||||||
case *dom.EventDocumentUpdated:
|
case *dom.EventDocumentUpdated:
|
||||||
t.documentUpdated(ctxt)
|
t.documentUpdated(ctx)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ func (t *Target) processEvent(ctxt context.Context, msg *cdproto.Message) error
|
||||||
|
|
||||||
// documentUpdated handles the document updated event, retrieving the document
|
// documentUpdated handles the document updated event, retrieving the document
|
||||||
// root for the root frame.
|
// root for the root frame.
|
||||||
func (t *Target) documentUpdated(ctxt context.Context) {
|
func (t *Target) documentUpdated(ctx context.Context) {
|
||||||
f := t.cur
|
f := t.cur
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
@ -178,7 +178,7 @@ func (t *Target) documentUpdated(ctxt context.Context) {
|
||||||
|
|
||||||
f.Nodes = make(map[cdp.NodeID]*cdp.Node)
|
f.Nodes = make(map[cdp.NodeID]*cdp.Node)
|
||||||
var err error
|
var err error
|
||||||
f.Root, err = dom.GetDocument().WithPierce(true).Do(ctxt, t)
|
f.Root, err = dom.GetDocument().WithPierce(true).Do(ctx, t)
|
||||||
if err == context.Canceled {
|
if err == context.Canceled {
|
||||||
return // TODO: perhaps not necessary, but useful to keep the tests less noisy
|
return // TODO: perhaps not necessary, but useful to keep the tests less noisy
|
||||||
}
|
}
|
||||||
|
|
24
input.go
24
input.go
|
@ -27,7 +27,7 @@ func MouseAction(typ input.MouseType, x, y int64, opts ...MouseOption) Action {
|
||||||
// MouseClickXY sends a left mouse button click (ie, mousePressed and
|
// MouseClickXY sends a left mouse button click (ie, mousePressed and
|
||||||
// mouseReleased event) at the X, Y location.
|
// mouseReleased event) at the X, Y location.
|
||||||
func MouseClickXY(x, y int64, opts ...MouseOption) Action {
|
func MouseClickXY(x, y int64, opts ...MouseOption) Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
me := &input.DispatchMouseEventParams{
|
me := &input.DispatchMouseEventParams{
|
||||||
Type: input.MousePressed,
|
Type: input.MousePressed,
|
||||||
X: float64(x),
|
X: float64(x),
|
||||||
|
@ -41,13 +41,13 @@ func MouseClickXY(x, y int64, opts ...MouseOption) Action {
|
||||||
me = o(me)
|
me = o(me)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := me.Do(ctxt, h)
|
err := me.Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
me.Type = input.MouseReleased
|
me.Type = input.MouseReleased
|
||||||
return me.Do(ctxt, h)
|
return me.Do(ctx, h)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,14 +57,14 @@ func MouseClickXY(x, y int64, opts ...MouseOption) Action {
|
||||||
// Note that the window will be scrolled if the node is not within the window's
|
// Note that the window will be scrolled if the node is not within the window's
|
||||||
// viewport.
|
// viewport.
|
||||||
func MouseClickNode(n *cdp.Node, opts ...MouseOption) Action {
|
func MouseClickNode(n *cdp.Node, opts ...MouseOption) Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
var pos []int
|
var pos []int
|
||||||
err := EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, n.FullXPath()), &pos).Do(ctxt, h)
|
err := EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, n.FullXPath()), &pos).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
box, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctxt, h)
|
box, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func MouseClickNode(n *cdp.Node, opts ...MouseOption) Action {
|
||||||
x /= int64(c / 2)
|
x /= int64(c / 2)
|
||||||
y /= int64(c / 2)
|
y /= int64(c / 2)
|
||||||
|
|
||||||
return MouseClickXY(x, y, opts...).Do(ctxt, h)
|
return MouseClickXY(x, y, opts...).Do(ctx, h)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,10 +151,10 @@ func ClickCount(n int) MouseOption {
|
||||||
// Please see the chromedp/kb package for implementation details and the list
|
// Please see the chromedp/kb package for implementation details and the list
|
||||||
// of well-known keys.
|
// of well-known keys.
|
||||||
func KeyAction(keys string, opts ...KeyOption) Action {
|
func KeyAction(keys string, opts ...KeyOption) Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
for _, r := range keys {
|
for _, r := range keys {
|
||||||
for _, k := range kb.Encode(r) {
|
for _, k := range kb.Encode(r) {
|
||||||
if err := k.Do(ctxt, h); err != nil {
|
if err := k.Do(ctx, h); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,13 +169,13 @@ func KeyAction(keys string, opts ...KeyOption) Action {
|
||||||
|
|
||||||
// KeyActionNode dispatches a key event on a node.
|
// KeyActionNode dispatches a key event on a node.
|
||||||
func KeyActionNode(n *cdp.Node, keys string, opts ...KeyOption) Action {
|
func KeyActionNode(n *cdp.Node, keys string, opts ...KeyOption) Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
err := dom.Focus().WithNodeID(n.NodeID).Do(ctxt, h)
|
err := dom.Focus().WithNodeID(n.NodeID).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyAction(keys, opts...).Do(ctxt, h)
|
return KeyAction(keys, opts...).Do(ctx, h)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
28
nav.go
28
nav.go
|
@ -10,8 +10,8 @@ import (
|
||||||
|
|
||||||
// Navigate navigates the current frame.
|
// Navigate navigates the current frame.
|
||||||
func Navigate(urlstr string) Action {
|
func Navigate(urlstr string) Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
_, _, _, err := page.Navigate(urlstr).Do(ctxt, h)
|
_, _, _, err := page.Navigate(urlstr).Do(ctx, h)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ func NavigationEntries(currentIndex *int64, entries *[]*page.NavigationEntry) Ac
|
||||||
panic("currentIndex and entries cannot be nil")
|
panic("currentIndex and entries cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
var err error
|
var err error
|
||||||
*currentIndex, *entries, err = page.GetNavigationHistory().Do(ctxt, h)
|
*currentIndex, *entries, err = page.GetNavigationHistory().Do(ctx, h)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ func NavigateToHistoryEntry(entryID int64) Action {
|
||||||
|
|
||||||
// NavigateBack navigates the current frame backwards in its history.
|
// NavigateBack navigates the current frame backwards in its history.
|
||||||
func NavigateBack() Action {
|
func NavigateBack() Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
cur, entries, err := page.GetNavigationHistory().Do(ctxt, h)
|
cur, entries, err := page.GetNavigationHistory().Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -48,14 +48,14 @@ func NavigateBack() Action {
|
||||||
return errors.New("invalid navigation entry")
|
return errors.New("invalid navigation entry")
|
||||||
}
|
}
|
||||||
|
|
||||||
return page.NavigateToHistoryEntry(entries[cur-1].ID).Do(ctxt, h)
|
return page.NavigateToHistoryEntry(entries[cur-1].ID).Do(ctx, h)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NavigateForward navigates the current frame forwards in its history.
|
// NavigateForward navigates the current frame forwards in its history.
|
||||||
func NavigateForward() Action {
|
func NavigateForward() Action {
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
cur, entries, err := page.GetNavigationHistory().Do(ctxt, h)
|
cur, entries, err := page.GetNavigationHistory().Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ func NavigateForward() Action {
|
||||||
return errors.New("invalid navigation entry")
|
return errors.New("invalid navigation entry")
|
||||||
}
|
}
|
||||||
|
|
||||||
return page.NavigateToHistoryEntry(entries[cur+1].ID).Do(ctxt, h)
|
return page.NavigateToHistoryEntry(entries[cur+1].ID).Do(ctx, h)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,9 +86,9 @@ func CaptureScreenshot(res *[]byte) Action {
|
||||||
panic("res cannot be nil")
|
panic("res cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
var err error
|
var err error
|
||||||
*res, err = page.CaptureScreenshot().Do(ctxt, h)
|
*res, err = page.CaptureScreenshot().Do(ctx, h)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -99,9 +99,9 @@ func CaptureScreenshot(res *[]byte) Action {
|
||||||
panic("id cannot be nil")
|
panic("id cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
|
return ActionFunc(func(ctx context.Context, h cdp.Executor) error {
|
||||||
var err error
|
var err error
|
||||||
*id, err = page.AddScriptToEvaluateOnLoad(source).Do(ctxt, h)
|
*id, err = page.AddScriptToEvaluateOnLoad(source).Do(ctx, h)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
96
query.go
96
query.go
|
@ -25,7 +25,7 @@ func Nodes(sel interface{}, nodes *[]*cdp.Node, opts ...QueryOption) Action {
|
||||||
panic("nodes cannot be nil")
|
panic("nodes cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, n ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, n ...*cdp.Node) error {
|
||||||
*nodes = n
|
*nodes = n
|
||||||
return nil
|
return nil
|
||||||
}, opts...)
|
}, opts...)
|
||||||
|
@ -37,7 +37,7 @@ func NodeIDs(sel interface{}, ids *[]cdp.NodeID, opts ...QueryOption) Action {
|
||||||
panic("nodes cannot be nil")
|
panic("nodes cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
nodeIDs := make([]cdp.NodeID, len(nodes))
|
nodeIDs := make([]cdp.NodeID, len(nodes))
|
||||||
for i, n := range nodes {
|
for i, n := range nodes {
|
||||||
nodeIDs[i] = n.NodeID
|
nodeIDs[i] = n.NodeID
|
||||||
|
@ -51,24 +51,24 @@ func NodeIDs(sel interface{}, ids *[]cdp.NodeID, opts ...QueryOption) Action {
|
||||||
|
|
||||||
// Focus focuses the first node matching the selector.
|
// Focus focuses the first node matching the selector.
|
||||||
func Focus(sel interface{}, opts ...QueryOption) Action {
|
func Focus(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dom.Focus().WithNodeID(nodes[0].NodeID).Do(ctxt, h)
|
return dom.Focus().WithNodeID(nodes[0].NodeID).Do(ctx, h)
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blur unfocuses (blurs) the first node matching the selector.
|
// Blur unfocuses (blurs) the first node matching the selector.
|
||||||
func Blur(sel interface{}, opts ...QueryOption) Action {
|
func Blur(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
var res bool
|
var res bool
|
||||||
err := EvaluateAsDevTools(fmt.Sprintf(blurJS, nodes[0].FullXPath()), &res).Do(ctxt, h)
|
err := EvaluateAsDevTools(fmt.Sprintf(blurJS, nodes[0].FullXPath()), &res).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -87,12 +87,12 @@ func Dimensions(sel interface{}, model **dom.BoxModel, opts ...QueryOption) Acti
|
||||||
if model == nil {
|
if model == nil {
|
||||||
panic("model cannot be nil")
|
panic("model cannot be nil")
|
||||||
}
|
}
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
*model, err = dom.GetBoxModel().WithNodeID(nodes[0].NodeID).Do(ctxt, h)
|
*model, err = dom.GetBoxModel().WithNodeID(nodes[0].NodeID).Do(ctx, h)
|
||||||
return err
|
return err
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
@ -103,18 +103,18 @@ func Text(sel interface{}, text *string, opts ...QueryOption) Action {
|
||||||
panic("text cannot be nil")
|
panic("text cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return EvaluateAsDevTools(fmt.Sprintf(textJS, nodes[0].FullXPath()), text).Do(ctxt, h)
|
return EvaluateAsDevTools(fmt.Sprintf(textJS, nodes[0].FullXPath()), text).Do(ctx, h)
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear clears the values of any input/textarea nodes matching the selector.
|
// Clear clears the values of any input/textarea nodes matching the selector.
|
||||||
func Clear(sel interface{}, opts ...QueryOption) Action {
|
func Clear(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ func Clear(sel interface{}, opts ...QueryOption) Action {
|
||||||
|
|
||||||
a = dom.SetNodeValue(textID, "")
|
a = dom.SetNodeValue(textID, "")
|
||||||
}
|
}
|
||||||
errs[i] = a.Do(ctxt, h)
|
errs[i] = a.Do(ctx, h)
|
||||||
}(i, n)
|
}(i, n)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
@ -190,7 +190,7 @@ func Attributes(sel interface{}, attributes *map[string]string, opts ...QueryOpt
|
||||||
panic("attributes cannot be nil")
|
panic("attributes cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ func AttributesAll(sel interface{}, attributes *[]map[string]string, opts ...Que
|
||||||
panic("attributes cannot be nil")
|
panic("attributes cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ func AttributesAll(sel interface{}, attributes *[]map[string]string, opts ...Que
|
||||||
// SetAttributes sets the element attributes for the first node matching the
|
// SetAttributes sets the element attributes for the first node matching the
|
||||||
// selector.
|
// selector.
|
||||||
func SetAttributes(sel interface{}, attributes map[string]string, opts ...QueryOption) Action {
|
func SetAttributes(sel interface{}, attributes map[string]string, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return errors.New("expected at least one element")
|
return errors.New("expected at least one element")
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ func SetAttributes(sel interface{}, attributes map[string]string, opts ...QueryO
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
return dom.SetAttributesAsText(nodes[0].NodeID, strings.Join(attrs, " ")).Do(ctxt, h)
|
return dom.SetAttributesAsText(nodes[0].NodeID, strings.Join(attrs, " ")).Do(ctx, h)
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ func AttributeValue(sel interface{}, name string, value *string, ok *bool, opts
|
||||||
panic("value cannot be nil")
|
panic("value cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return errors.New("expected at least one element")
|
return errors.New("expected at least one element")
|
||||||
}
|
}
|
||||||
|
@ -295,24 +295,24 @@ func AttributeValue(sel interface{}, name string, value *string, ok *bool, opts
|
||||||
// SetAttributeValue sets the element attribute with name to value for the
|
// SetAttributeValue sets the element attribute with name to value for the
|
||||||
// first node matching the selector.
|
// first node matching the selector.
|
||||||
func SetAttributeValue(sel interface{}, name, value string, opts ...QueryOption) Action {
|
func SetAttributeValue(sel interface{}, name, value string, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dom.SetAttributeValue(nodes[0].NodeID, name, value).Do(ctxt, h)
|
return dom.SetAttributeValue(nodes[0].NodeID, name, value).Do(ctx, h)
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAttribute removes the element attribute with name from the first node
|
// RemoveAttribute removes the element attribute with name from the first node
|
||||||
// matching the selector.
|
// matching the selector.
|
||||||
func RemoveAttribute(sel interface{}, name string, opts ...QueryOption) Action {
|
func RemoveAttribute(sel interface{}, name string, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dom.RemoveAttribute(nodes[0].NodeID, name).Do(ctxt, h)
|
return dom.RemoveAttribute(nodes[0].NodeID, name).Do(ctx, h)
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,25 +322,25 @@ func JavascriptAttribute(sel interface{}, name string, res interface{}, opts ...
|
||||||
if res == nil {
|
if res == nil {
|
||||||
panic("res cannot be nil")
|
panic("res cannot be nil")
|
||||||
}
|
}
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return EvaluateAsDevTools(fmt.Sprintf(attributeJS, nodes[0].FullXPath(), name), res).Do(ctxt, h)
|
return EvaluateAsDevTools(fmt.Sprintf(attributeJS, nodes[0].FullXPath(), name), res).Do(ctx, h)
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetJavascriptAttribute sets the javascript attribute for the first node
|
// SetJavascriptAttribute sets the javascript attribute for the first node
|
||||||
// matching the selector.
|
// matching the selector.
|
||||||
func SetJavascriptAttribute(sel interface{}, name, value string, opts ...QueryOption) Action {
|
func SetJavascriptAttribute(sel interface{}, name, value string, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
var res string
|
var res string
|
||||||
err := EvaluateAsDevTools(fmt.Sprintf(setAttributeJS, nodes[0].FullXPath(), name, value), &res).Do(ctxt, h)
|
err := EvaluateAsDevTools(fmt.Sprintf(setAttributeJS, nodes[0].FullXPath(), name, value), &res).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -370,24 +370,24 @@ func InnerHTML(sel interface{}, html *string, opts ...QueryOption) Action {
|
||||||
|
|
||||||
// Click sends a mouse click event to the first node matching the selector.
|
// Click sends a mouse click event to the first node matching the selector.
|
||||||
func Click(sel interface{}, opts ...QueryOption) Action {
|
func Click(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return MouseClickNode(nodes[0]).Do(ctxt, h)
|
return MouseClickNode(nodes[0]).Do(ctx, h)
|
||||||
}, append(opts, NodeVisible)...)
|
}, append(opts, NodeVisible)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoubleClick sends a mouse double click event to the first node matching the
|
// DoubleClick sends a mouse double click event to the first node matching the
|
||||||
// selector.
|
// selector.
|
||||||
func DoubleClick(sel interface{}, opts ...QueryOption) Action {
|
func DoubleClick(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return MouseClickNode(nodes[0], ClickCount(2)).Do(ctxt, h)
|
return MouseClickNode(nodes[0], ClickCount(2)).Do(ctx, h)
|
||||||
}, append(opts, NodeVisible)...)
|
}, append(opts, NodeVisible)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ func DoubleClick(sel interface{}, opts ...QueryOption) Action {
|
||||||
// Note: when selector matches a input[type="file"] node, then dom.SetFileInputFiles
|
// Note: when selector matches a input[type="file"] node, then dom.SetFileInputFiles
|
||||||
// is used to set the upload path of the input node to v.
|
// is used to set the upload path of the input node to v.
|
||||||
func SendKeys(sel interface{}, v string, opts ...QueryOption) Action {
|
func SendKeys(sel interface{}, v string, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
@ -416,22 +416,22 @@ func SendKeys(sel interface{}, v string, opts ...QueryOption) Action {
|
||||||
|
|
||||||
// when working with input[type="file"], call dom.SetFileInputFiles
|
// when working with input[type="file"], call dom.SetFileInputFiles
|
||||||
if n.NodeName == "INPUT" && typ == "file" {
|
if n.NodeName == "INPUT" && typ == "file" {
|
||||||
return dom.SetFileInputFiles([]string{v}).WithNodeID(n.NodeID).Do(ctxt, h)
|
return dom.SetFileInputFiles([]string{v}).WithNodeID(n.NodeID).Do(ctx, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyActionNode(n, v).Do(ctxt, h)
|
return KeyActionNode(n, v).Do(ctx, h)
|
||||||
}, append(opts, NodeVisible)...)
|
}, append(opts, NodeVisible)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUploadFiles sets the files to upload (ie, for a input[type="file"] node)
|
// SetUploadFiles sets the files to upload (ie, for a input[type="file"] node)
|
||||||
// for the first node matching the selector.
|
// for the first node matching the selector.
|
||||||
func SetUploadFiles(sel interface{}, files []string, opts ...QueryOption) Action {
|
func SetUploadFiles(sel interface{}, files []string, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dom.SetFileInputFiles(files).WithNodeID(nodes[0].NodeID).Do(ctxt, h)
|
return dom.SetFileInputFiles(files).WithNodeID(nodes[0].NodeID).Do(ctx, h)
|
||||||
}, opts...)
|
}, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,13 +441,13 @@ func Screenshot(sel interface{}, picbuf *[]byte, opts ...QueryOption) Action {
|
||||||
panic("picbuf cannot be nil")
|
panic("picbuf cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get box model
|
// get box model
|
||||||
box, err := dom.GetBoxModel().WithNodeID(nodes[0].NodeID).Do(ctxt, h)
|
box, err := dom.GetBoxModel().WithNodeID(nodes[0].NodeID).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -459,13 +459,13 @@ func Screenshot(sel interface{}, picbuf *[]byte, opts ...QueryOption) Action {
|
||||||
|
|
||||||
// scroll to node position
|
// scroll to node position
|
||||||
var pos []int
|
var pos []int
|
||||||
err = EvaluateAsDevTools(fmt.Sprintf(scrollJS, int64(box.Margin[0]), int64(box.Margin[1])), &pos).Do(ctxt, h)
|
err = EvaluateAsDevTools(fmt.Sprintf(scrollJS, int64(box.Margin[0]), int64(box.Margin[1])), &pos).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// take page screenshot
|
// take page screenshot
|
||||||
buf, err := page.CaptureScreenshot().Do(ctxt, h)
|
buf, err := page.CaptureScreenshot().Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -497,13 +497,13 @@ func Screenshot(sel interface{}, picbuf *[]byte, opts ...QueryOption) Action {
|
||||||
// Submit is an action that submits the form of the first node matching the
|
// Submit is an action that submits the form of the first node matching the
|
||||||
// selector belongs to.
|
// selector belongs to.
|
||||||
func Submit(sel interface{}, opts ...QueryOption) Action {
|
func Submit(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
var res bool
|
var res bool
|
||||||
err := EvaluateAsDevTools(fmt.Sprintf(submitJS, nodes[0].FullXPath()), &res).Do(ctxt, h)
|
err := EvaluateAsDevTools(fmt.Sprintf(submitJS, nodes[0].FullXPath()), &res).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -519,13 +519,13 @@ func Submit(sel interface{}, opts ...QueryOption) Action {
|
||||||
// Reset is an action that resets the form of the first node matching the
|
// Reset is an action that resets the form of the first node matching the
|
||||||
// selector belongs to.
|
// selector belongs to.
|
||||||
func Reset(sel interface{}, opts ...QueryOption) Action {
|
func Reset(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
var res bool
|
var res bool
|
||||||
err := EvaluateAsDevTools(fmt.Sprintf(resetJS, nodes[0].FullXPath()), &res).Do(ctxt, h)
|
err := EvaluateAsDevTools(fmt.Sprintf(resetJS, nodes[0].FullXPath()), &res).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -544,12 +544,12 @@ func ComputedStyle(sel interface{}, style *[]*css.ComputedProperty, opts ...Quer
|
||||||
panic("style cannot be nil")
|
panic("style cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
computed, err := css.GetComputedStyleForNode(nodes[0].NodeID).Do(ctxt, h)
|
computed, err := css.GetComputedStyleForNode(nodes[0].NodeID).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -567,7 +567,7 @@ func MatchedStyle(sel interface{}, style **css.GetMatchedStylesForNodeReturns, o
|
||||||
panic("style cannot be nil")
|
panic("style cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
@ -576,7 +576,7 @@ func MatchedStyle(sel interface{}, style **css.GetMatchedStylesForNodeReturns, o
|
||||||
ret := &css.GetMatchedStylesForNodeReturns{}
|
ret := &css.GetMatchedStylesForNodeReturns{}
|
||||||
ret.InlineStyle, ret.AttributesStyle, ret.MatchedCSSRules,
|
ret.InlineStyle, ret.AttributesStyle, ret.MatchedCSSRules,
|
||||||
ret.PseudoElements, ret.Inherited, ret.CSSKeyframesRules,
|
ret.PseudoElements, ret.Inherited, ret.CSSKeyframesRules,
|
||||||
err = css.GetMatchedStylesForNode(nodes[0].NodeID).Do(ctxt, h)
|
err = css.GetMatchedStylesForNode(nodes[0].NodeID).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -589,13 +589,13 @@ func MatchedStyle(sel interface{}, style **css.GetMatchedStylesForNodeReturns, o
|
||||||
|
|
||||||
// ScrollIntoView scrolls the window to the first node matching the selector.
|
// ScrollIntoView scrolls the window to the first node matching the selector.
|
||||||
func ScrollIntoView(sel interface{}, opts ...QueryOption) Action {
|
func ScrollIntoView(sel interface{}, opts ...QueryOption) Action {
|
||||||
return QueryAfter(sel, func(ctxt context.Context, h *Target, nodes ...*cdp.Node) error {
|
return QueryAfter(sel, func(ctx context.Context, h *Target, nodes ...*cdp.Node) error {
|
||||||
if len(nodes) < 1 {
|
if len(nodes) < 1 {
|
||||||
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
return fmt.Errorf("selector `%s` did not return any nodes", sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
var pos []int
|
var pos []int
|
||||||
err := EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, nodes[0].FullXPath()), &pos).Do(ctxt, h)
|
err := EvaluateAsDevTools(fmt.Sprintf(scrollIntoViewJS, nodes[0].FullXPath()), &pos).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
56
sel.go
56
sel.go
|
@ -55,7 +55,7 @@ func Query(sel interface{}, opts ...QueryOption) Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do satisfies the Action interface.
|
// Do satisfies the Action interface.
|
||||||
func (s *Selector) Do(ctxt context.Context, h cdp.Executor) error {
|
func (s *Selector) Do(ctx context.Context, h cdp.Executor) error {
|
||||||
th, ok := h.(*Target)
|
th, ok := h.(*Target)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrInvalidHandler
|
return ErrInvalidHandler
|
||||||
|
@ -63,9 +63,9 @@ func (s *Selector) Do(ctxt context.Context, h cdp.Executor) error {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
select {
|
select {
|
||||||
case err = <-s.run(ctxt, th):
|
case err = <-s.run(ctx, th):
|
||||||
case <-ctxt.Done():
|
case <-ctx.Done():
|
||||||
err = ctxt.Err()
|
err = ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -74,7 +74,7 @@ func (s *Selector) Do(ctxt context.Context, h cdp.Executor) error {
|
||||||
// run runs the selector action, starting over if the original returned nodes
|
// run runs the selector action, starting over if the original returned nodes
|
||||||
// are invalidated prior to finishing the selector's by, wait, check, and after
|
// are invalidated prior to finishing the selector's by, wait, check, and after
|
||||||
// funcs.
|
// funcs.
|
||||||
func (s *Selector) run(ctxt context.Context, h *Target) chan error {
|
func (s *Selector) run(ctx context.Context, h *Target) chan error {
|
||||||
ch := make(chan error, 1)
|
ch := make(chan error, 1)
|
||||||
h.waitQueue <- func(cur *cdp.Frame) bool {
|
h.waitQueue <- func(cur *cdp.Frame) bool {
|
||||||
cur.RLock()
|
cur.RLock()
|
||||||
|
@ -86,17 +86,17 @@ func (s *Selector) run(ctxt context.Context, h *Target) chan error {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
ids, err := s.by(ctxt, h, root)
|
ids, err := s.by(ctx, h, root)
|
||||||
if err != nil || len(ids) < s.exp {
|
if err != nil || len(ids) < s.exp {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
nodes, err := s.wait(ctxt, h, cur, ids...)
|
nodes, err := s.wait(ctx, h, cur, ids...)
|
||||||
// if nodes==nil, we're not yet ready
|
// if nodes==nil, we're not yet ready
|
||||||
if nodes == nil || err != nil {
|
if nodes == nil || err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if s.after != nil {
|
if s.after != nil {
|
||||||
if err := s.after(ctxt, h, nodes...); err != nil {
|
if err := s.after(ctx, h, nodes...); err != nil {
|
||||||
ch <- err
|
ch <- err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,8 +135,8 @@ func ByFunc(f func(context.Context, *Target, *cdp.Node) ([]cdp.NodeID, error)) Q
|
||||||
// ByQuery is a query option to select a single element using
|
// ByQuery is a query option to select a single element using
|
||||||
// DOM.querySelector.
|
// DOM.querySelector.
|
||||||
func ByQuery(s *Selector) {
|
func ByQuery(s *Selector) {
|
||||||
ByFunc(func(ctxt context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
ByFunc(func(ctx context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
||||||
nodeID, err := dom.QuerySelector(n.NodeID, s.selAsString()).Do(ctxt, h)
|
nodeID, err := dom.QuerySelector(n.NodeID, s.selAsString()).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -151,8 +151,8 @@ func ByQuery(s *Selector) {
|
||||||
|
|
||||||
// ByQueryAll is a query option to select elements by DOM.querySelectorAll.
|
// ByQueryAll is a query option to select elements by DOM.querySelectorAll.
|
||||||
func ByQueryAll(s *Selector) {
|
func ByQueryAll(s *Selector) {
|
||||||
ByFunc(func(ctxt context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
ByFunc(func(ctx context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
||||||
return dom.QuerySelectorAll(n.NodeID, s.selAsString()).Do(ctxt, h)
|
return dom.QuerySelectorAll(n.NodeID, s.selAsString()).Do(ctx, h)
|
||||||
})(s)
|
})(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +165,8 @@ func ByID(s *Selector) {
|
||||||
// BySearch is a query option via DOM.performSearch (works with both CSS and
|
// BySearch is a query option via DOM.performSearch (works with both CSS and
|
||||||
// XPath queries).
|
// XPath queries).
|
||||||
func BySearch(s *Selector) {
|
func BySearch(s *Selector) {
|
||||||
ByFunc(func(ctxt context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
ByFunc(func(ctx context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
||||||
id, count, err := dom.PerformSearch(s.selAsString()).Do(ctxt, h)
|
id, count, err := dom.PerformSearch(s.selAsString()).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ func BySearch(s *Selector) {
|
||||||
return []cdp.NodeID{}, nil
|
return []cdp.NodeID{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes, err := dom.GetSearchResults(id, 0, count).Do(ctxt, h)
|
nodes, err := dom.GetSearchResults(id, 0, count).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -191,9 +191,9 @@ func ByNodeID(s *Selector) {
|
||||||
panic("ByNodeID can only work on []cdp.NodeID")
|
panic("ByNodeID can only work on []cdp.NodeID")
|
||||||
}
|
}
|
||||||
|
|
||||||
ByFunc(func(ctxt context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
ByFunc(func(ctx context.Context, h *Target, n *cdp.Node) ([]cdp.NodeID, error) {
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
err := dom.RequestChildNodes(id).WithPierce(true).Do(ctxt, h)
|
err := dom.RequestChildNodes(id).WithPierce(true).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ func ByNodeID(s *Selector) {
|
||||||
|
|
||||||
// waitReady waits for the specified nodes to be ready.
|
// waitReady waits for the specified nodes to be ready.
|
||||||
func (s *Selector) waitReady(check func(context.Context, *Target, *cdp.Node) error) func(context.Context, *Target, *cdp.Frame, ...cdp.NodeID) ([]*cdp.Node, error) {
|
func (s *Selector) waitReady(check func(context.Context, *Target, *cdp.Node) error) func(context.Context, *Target, *cdp.Frame, ...cdp.NodeID) ([]*cdp.Node, error) {
|
||||||
return func(ctxt context.Context, h *Target, cur *cdp.Frame, ids ...cdp.NodeID) ([]*cdp.Node, error) {
|
return func(ctx context.Context, h *Target, cur *cdp.Frame, ids ...cdp.NodeID) ([]*cdp.Node, error) {
|
||||||
nodes := make([]*cdp.Node, len(ids))
|
nodes := make([]*cdp.Node, len(ids))
|
||||||
cur.RLock()
|
cur.RLock()
|
||||||
for i, id := range ids {
|
for i, id := range ids {
|
||||||
|
@ -225,7 +225,7 @@ func (s *Selector) waitReady(check func(context.Context, *Target, *cdp.Node) err
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(i int, n *cdp.Node) {
|
go func(i int, n *cdp.Node) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
errs[i] = check(ctxt, h, n)
|
errs[i] = check(ctx, h, n)
|
||||||
}(i, n)
|
}(i, n)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
@ -255,9 +255,9 @@ func NodeReady(s *Selector) {
|
||||||
|
|
||||||
// NodeVisible is a query option to wait until the element is visible.
|
// NodeVisible is a query option to wait until the element is visible.
|
||||||
func NodeVisible(s *Selector) {
|
func NodeVisible(s *Selector) {
|
||||||
WaitFunc(s.waitReady(func(ctxt context.Context, h *Target, n *cdp.Node) error {
|
WaitFunc(s.waitReady(func(ctx context.Context, h *Target, n *cdp.Node) error {
|
||||||
// check box model
|
// check box model
|
||||||
_, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctxt, h)
|
_, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if isCouldNotComputeBoxModelError(err) {
|
if isCouldNotComputeBoxModelError(err) {
|
||||||
return ErrNotVisible
|
return ErrNotVisible
|
||||||
|
@ -268,7 +268,7 @@ func NodeVisible(s *Selector) {
|
||||||
|
|
||||||
// check offsetParent
|
// check offsetParent
|
||||||
var res bool
|
var res bool
|
||||||
err = EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctxt, h)
|
err = EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -281,9 +281,9 @@ func NodeVisible(s *Selector) {
|
||||||
|
|
||||||
// NodeNotVisible is a query option to wait until the element is not visible.
|
// NodeNotVisible is a query option to wait until the element is not visible.
|
||||||
func NodeNotVisible(s *Selector) {
|
func NodeNotVisible(s *Selector) {
|
||||||
WaitFunc(s.waitReady(func(ctxt context.Context, h *Target, n *cdp.Node) error {
|
WaitFunc(s.waitReady(func(ctx context.Context, h *Target, n *cdp.Node) error {
|
||||||
// check box model
|
// check box model
|
||||||
_, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctxt, h)
|
_, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if isCouldNotComputeBoxModelError(err) {
|
if isCouldNotComputeBoxModelError(err) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -294,7 +294,7 @@ func NodeNotVisible(s *Selector) {
|
||||||
|
|
||||||
// check offsetParent
|
// check offsetParent
|
||||||
var res bool
|
var res bool
|
||||||
err = EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctxt, h)
|
err = EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctx, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ func NodeNotVisible(s *Selector) {
|
||||||
|
|
||||||
// NodeEnabled is a query option to wait until the element is enabled.
|
// NodeEnabled is a query option to wait until the element is enabled.
|
||||||
func NodeEnabled(s *Selector) {
|
func NodeEnabled(s *Selector) {
|
||||||
WaitFunc(s.waitReady(func(ctxt context.Context, h *Target, n *cdp.Node) error {
|
WaitFunc(s.waitReady(func(ctx context.Context, h *Target, n *cdp.Node) error {
|
||||||
n.RLock()
|
n.RLock()
|
||||||
defer n.RUnlock()
|
defer n.RUnlock()
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ func NodeEnabled(s *Selector) {
|
||||||
|
|
||||||
// NodeSelected is a query option to wait until the element is selected.
|
// NodeSelected is a query option to wait until the element is selected.
|
||||||
func NodeSelected(s *Selector) {
|
func NodeSelected(s *Selector) {
|
||||||
WaitFunc(s.waitReady(func(ctxt context.Context, h *Target, n *cdp.Node) error {
|
WaitFunc(s.waitReady(func(ctx context.Context, h *Target, n *cdp.Node) error {
|
||||||
n.RLock()
|
n.RLock()
|
||||||
defer n.RUnlock()
|
defer n.RUnlock()
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ func NodeSelected(s *Selector) {
|
||||||
// matching the selector.
|
// matching the selector.
|
||||||
func NodeNotPresent(s *Selector) {
|
func NodeNotPresent(s *Selector) {
|
||||||
s.exp = 0
|
s.exp = 0
|
||||||
WaitFunc(func(ctxt context.Context, h *Target, cur *cdp.Frame, ids ...cdp.NodeID) ([]*cdp.Node, error) {
|
WaitFunc(func(ctx context.Context, h *Target, cur *cdp.Frame, ids ...cdp.NodeID) ([]*cdp.Node, error) {
|
||||||
if len(ids) != 0 {
|
if len(ids) != 0 {
|
||||||
return nil, ErrHasResults
|
return nil, ErrHasResults
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user