Best Rod code snippet using cdp.Is
sel.go
Source:sel.go
1package chromedp2import (3 "context"4 "fmt"5 "strings"6 "sync"7 "time"8 "github.com/chromedp/cdproto/cdp"9 "github.com/chromedp/cdproto/dom"10)11/*12TODO: selector 'by' type, as below:13classname14linktext15name16partiallinktext17tagname18*/19// Selector holds information pertaining to an element query select action.20type Selector struct {21 sel interface{}22 exp int23 by func(context.Context, *TargetHandler, *cdp.Node) ([]cdp.NodeID, error)24 wait func(context.Context, *TargetHandler, *cdp.Node, ...cdp.NodeID) ([]*cdp.Node, error)25 after func(context.Context, *TargetHandler, ...*cdp.Node) error26}27// Query is an action to query for document nodes match the specified sel and28// the supplied query options.29func Query(sel interface{}, opts ...QueryOption) Action {30 s := &Selector{31 sel: sel,32 exp: 1,33 }34 // apply options35 for _, o := range opts {36 o(s)37 }38 if s.by == nil {39 BySearch(s)40 }41 if s.wait == nil {42 NodeReady(s)43 }44 return s45}46// Do satisfies the Action interface.47func (s *Selector) Do(ctxt context.Context, h cdp.Executor) error {48 th, ok := h.(*TargetHandler)49 if !ok {50 return ErrInvalidHandler51 }52 // TODO: fix this53 ctxt, cancel := context.WithTimeout(ctxt, 100*time.Second)54 defer cancel()55 var err error56 select {57 case err = <-s.run(ctxt, th):58 case <-ctxt.Done():59 err = ctxt.Err()60 }61 return err62}63// run runs the selector action, starting over if the original returned nodes64// are invalidated prior to finishing the selector's by, wait, check, and after65// funcs.66func (s *Selector) run(ctxt context.Context, h *TargetHandler) chan error {67 ch := make(chan error, 1)68 go func() {69 defer close(ch)70 for {71 root, err := h.GetRoot(ctxt)72 if err != nil {73 select {74 case <-ctxt.Done():75 ch <- ctxt.Err()76 return77 default:78 continue79 }80 }81 select {82 default:83 ids, err := s.by(ctxt, h, root)84 if err == nil && len(ids) >= s.exp {85 nodes, err := s.wait(ctxt, h, root, ids...)86 if err == nil {87 if s.after == nil {88 return89 }90 err = s.after(ctxt, h, nodes...)91 if err != nil {92 ch <- err93 }94 return95 }96 }97 time.Sleep(DefaultCheckDuration)98 case <-root.Invalidated:99 continue100 case <-ctxt.Done():101 ch <- ctxt.Err()102 return103 }104 }105 }()106 return ch107}108// selAsString forces sel into a string.109func (s *Selector) selAsString() string {110 if sel, ok := s.sel.(string); ok {111 return sel112 }113 return fmt.Sprintf("%s", s.sel)114}115// selAsInt forces sel into a int.116/*func (s *Selector) selAsInt() int {117 sel, ok := s.sel.(int)118 if !ok {119 panic("selector must be int")120 }121 return sel122}*/123// QueryAfter is an action that will match the specified sel using the supplied124// query options, and after the visibility conditions of the query have been125// met, will execute f.126func QueryAfter(sel interface{}, f func(context.Context, *TargetHandler, ...*cdp.Node) error, opts ...QueryOption) Action {127 return Query(sel, append(opts, After(f))...)128}129// QueryOption is a element query selector option.130type QueryOption func(*Selector)131// ByFunc is a query option to set the func used to select elements.132func ByFunc(f func(context.Context, *TargetHandler, *cdp.Node) ([]cdp.NodeID, error)) QueryOption {133 return func(s *Selector) {134 s.by = f135 }136}137// ByQuery is a query option to select a single element using138// DOM.querySelector.139func ByQuery(s *Selector) {140 ByFunc(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) ([]cdp.NodeID, error) {141 nodeID, err := dom.QuerySelector(n.NodeID, s.selAsString()).Do(ctxt, h)142 if err != nil {143 return nil, err144 }145 if nodeID == cdp.EmptyNodeID {146 return []cdp.NodeID{}, nil147 }148 return []cdp.NodeID{nodeID}, nil149 })(s)150}151// ByQueryAll is a query option to select elements by DOM.querySelectorAll.152func ByQueryAll(s *Selector) {153 ByFunc(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) ([]cdp.NodeID, error) {154 return dom.QuerySelectorAll(n.NodeID, s.selAsString()).Do(ctxt, h)155 })(s)156}157// ByID is a query option to select a single element by their CSS #id.158func ByID(s *Selector) {159 s.sel = "#" + strings.TrimPrefix(s.selAsString(), "#")160 ByQuery(s)161}162// BySearch is a query option via DOM.performSearch (works with both CSS and163// XPath queries).164func BySearch(s *Selector) {165 ByFunc(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) ([]cdp.NodeID, error) {166 id, count, err := dom.PerformSearch(s.selAsString()).Do(ctxt, h)167 if err != nil {168 return nil, err169 }170 if count < 1 {171 return []cdp.NodeID{}, nil172 }173 nodes, err := dom.GetSearchResults(id, 0, count).Do(ctxt, h)174 if err != nil {175 return nil, err176 }177 return nodes, nil178 })(s)179}180// ByNodeID is a query option to select elements by their NodeIDs.181func ByNodeID(s *Selector) {182 ids, ok := s.sel.([]cdp.NodeID)183 if !ok {184 panic("ByNodeID can only work on []cdp.NodeID")185 }186 ByFunc(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) ([]cdp.NodeID, error) {187 for _, id := range ids {188 err := dom.RequestChildNodes(id).WithPierce(true).Do(ctxt, h)189 if err != nil {190 return nil, err191 }192 }193 return ids, nil194 })(s)195}196// waitReady waits for the specified nodes to be ready.197func (s *Selector) waitReady(check func(context.Context, *TargetHandler, *cdp.Node) error) func(context.Context, *TargetHandler, *cdp.Node, ...cdp.NodeID) ([]*cdp.Node, error) {198 return func(ctxt context.Context, h *TargetHandler, n *cdp.Node, ids ...cdp.NodeID) ([]*cdp.Node, error) {199 f, err := h.WaitFrame(ctxt, cdp.EmptyFrameID)200 if err != nil {201 return nil, err202 }203 wg := new(sync.WaitGroup)204 nodes := make([]*cdp.Node, len(ids))205 errs := make([]error, len(ids))206 for i, id := range ids {207 wg.Add(1)208 go func(i int, id cdp.NodeID) {209 defer wg.Done()210 nodes[i], errs[i] = h.WaitNode(ctxt, f, id)211 }(i, id)212 }213 wg.Wait()214 for _, err := range errs {215 if err != nil {216 return nil, err217 }218 }219 if check != nil {220 errs := make([]error, len(nodes))221 for i, n := range nodes {222 wg.Add(1)223 go func(i int, n *cdp.Node) {224 defer wg.Done()225 errs[i] = check(ctxt, h, n)226 }(i, n)227 }228 wg.Wait()229 for _, err := range errs {230 if err != nil {231 return nil, err232 }233 }234 }235 return nodes, nil236 }237}238// WaitFunc is a query option to set a custom wait func.239func WaitFunc(wait func(context.Context, *TargetHandler, *cdp.Node, ...cdp.NodeID) ([]*cdp.Node, error)) QueryOption {240 return func(s *Selector) {241 s.wait = wait242 }243}244// NodeReady is a query option to wait until the element is ready.245func NodeReady(s *Selector) {246 WaitFunc(s.waitReady(nil))(s)247}248// NodeVisible is a query option to wait until the element is visible.249func NodeVisible(s *Selector) {250 WaitFunc(s.waitReady(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) error {251 // check box model252 _, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctxt, h)253 if err != nil {254 if isCouldNotComputeBoxModelError(err) {255 return ErrNotVisible256 }257 return err258 }259 // check offsetParent260 var res bool261 err = EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctxt, h)262 if err != nil {263 return err264 }265 if !res {266 return ErrNotVisible267 }268 return nil269 }))(s)270}271// NodeNotVisible is a query option to wait until the element is not visible.272func NodeNotVisible(s *Selector) {273 WaitFunc(s.waitReady(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) error {274 // check box model275 _, err := dom.GetBoxModel().WithNodeID(n.NodeID).Do(ctxt, h)276 if err != nil {277 if isCouldNotComputeBoxModelError(err) {278 return nil279 }280 return err281 }282 // check offsetParent283 var res bool284 err = EvaluateAsDevTools(fmt.Sprintf(visibleJS, n.FullXPath()), &res).Do(ctxt, h)285 if err != nil {286 return err287 }288 if res {289 return ErrVisible290 }291 return nil292 }))(s)293}294// NodeEnabled is a query option to wait until the element is enabled.295func NodeEnabled(s *Selector) {296 WaitFunc(s.waitReady(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) error {297 n.RLock()298 defer n.RUnlock()299 for i := 0; i < len(n.Attributes); i += 2 {300 if n.Attributes[i] == "disabled" {301 return ErrDisabled302 }303 }304 return nil305 }))(s)306}307// NodeSelected is a query option to wait until the element is selected.308func NodeSelected(s *Selector) {309 WaitFunc(s.waitReady(func(ctxt context.Context, h *TargetHandler, n *cdp.Node) error {310 n.RLock()311 defer n.RUnlock()312 for i := 0; i < len(n.Attributes); i += 2 {313 if n.Attributes[i] == "selected" {314 return nil315 }316 }317 return ErrNotSelected318 }))(s)319}320// NodeNotPresent is a query option to wait until no elements match are321// present matching the selector.322func NodeNotPresent(s *Selector) {323 s.exp = 0324 WaitFunc(func(ctxt context.Context, h *TargetHandler, n *cdp.Node, ids ...cdp.NodeID) ([]*cdp.Node, error) {325 if len(ids) != 0 {326 return nil, ErrHasResults327 }328 return []*cdp.Node{}, nil329 })(s)330}331// AtLeast is a query option to wait until at least n elements are returned332// from the query selector.333func AtLeast(n int) QueryOption {334 return func(s *Selector) {335 s.exp = n336 }337}338// After is a query option to set a func that will be executed after the wait339// has succeeded.340func After(f func(context.Context, *TargetHandler, ...*cdp.Node) error) QueryOption {341 return func(s *Selector) {342 s.after = f343 }344}345// WaitReady waits until the element is ready (ie, loaded by chromedp).346func WaitReady(sel interface{}, opts ...QueryOption) Action {347 return Query(sel, opts...)348}349// WaitVisible waits until the selected element is visible.350func WaitVisible(sel interface{}, opts ...QueryOption) Action {351 return Query(sel, append(opts, NodeVisible)...)352}353// WaitNotVisible waits until the selected element is not visible.354func WaitNotVisible(sel interface{}, opts ...QueryOption) Action {355 return Query(sel, append(opts, NodeNotVisible)...)356}357// WaitEnabled waits until the selected element is enabled (does not have358// attribute 'disabled').359func WaitEnabled(sel interface{}, opts ...QueryOption) Action {360 return Query(sel, append(opts, NodeEnabled)...)361}362// WaitSelected waits until the element is selected (has attribute 'selected').363func WaitSelected(sel interface{}, opts ...QueryOption) Action {364 return Query(sel, append(opts, NodeSelected)...)365}366// WaitNotPresent waits until no elements match the specified selector.367func WaitNotPresent(sel interface{}, opts ...QueryOption) Action {368 return Query(sel, append(opts, NodeNotPresent)...)369}...
chromedp.go
Source:chromedp.go
1// Package chromedp is a high level Chrome DevTools Protocol client that2// simplifies driving browsers for scraping, unit testing, or profiling web3// pages using the CDP.4//5// chromedp requires no third-party dependencies, implementing the async Chrome6// DevTools Protocol entirely in Go.7package chromedp8import (9 "context"10 "errors"11 "fmt"12 "log"13 "sync"14 "time"15 "github.com/chromedp/cdproto/cdp"16 "github.com/incognito-core-libs/chromedp/client"17 "github.com/incognito-core-libs/chromedp/runner"18)19const (20 // DefaultNewTargetTimeout is the default time to wait for a new target to21 // be started.22 DefaultNewTargetTimeout = 3 * time.Second23 // DefaultCheckDuration is the default time to sleep between a check.24 DefaultCheckDuration = 50 * time.Millisecond25 // DefaultPoolStartPort is the default start port number.26 DefaultPoolStartPort = 900027 // DefaultPoolEndPort is the default end port number.28 DefaultPoolEndPort = 1000029)30// CDP is the high-level Chrome DevTools Protocol browser manager, handling the31// browser process runner, WebSocket clients, associated targets, and network,32// page, and DOM events.33type CDP struct {34 // r is the chrome runner.35 r *runner.Runner36 // opts are command line options to pass to a created runner.37 opts []runner.CommandLineOption38 // watch is the channel for new client targets.39 watch <-chan client.Target40 // cur is the current active target's handler.41 cur cdp.Executor42 // handlers is the active handlers.43 handlers []*TargetHandler44 // handlerMap is the map of target IDs to its active handler.45 handlerMap map[string]int46 // logging funcs47 logf, debugf, errf func(string, ...interface{})48 sync.RWMutex49}50// New creates and starts a new CDP instance.51func New(ctxt context.Context, opts ...Option) (*CDP, error) {52 c := &CDP{53 handlers: make([]*TargetHandler, 0),54 handlerMap: make(map[string]int),55 logf: log.Printf,56 debugf: func(string, ...interface{}) {},57 errf: func(s string, v ...interface{}) { log.Printf("error: "+s, v...) },58 }59 // apply options60 for _, o := range opts {61 if err := o(c); err != nil {62 return nil, err63 }64 }65 // check for supplied runner, if none then create one66 if c.r == nil && c.watch == nil {67 var err error68 c.r, err = runner.Run(ctxt, c.opts...)69 if err != nil {70 return nil, err71 }72 }73 // watch handlers74 if c.watch == nil {75 c.watch = c.r.Client().WatchPageTargets(ctxt)76 }77 go func() {78 for t := range c.watch {79 if t == nil {80 return81 }82 go c.AddTarget(ctxt, t)83 }84 }()85 // TODO: fix this86 timeout := time.After(defaultNewTargetTimeout)87 // wait until at least one target active88 for {89 select {90 default:91 c.RLock()92 exists := c.cur != nil93 c.RUnlock()94 if exists {95 return c, nil96 }97 // TODO: fix this98 time.Sleep(DefaultCheckDuration)99 case <-ctxt.Done():100 return nil, ctxt.Err()101 case <-timeout:102 return nil, errors.New("timeout waiting for initial target")103 }104 }105}106// AddTarget adds a target using the supplied context.107func (c *CDP) AddTarget(ctxt context.Context, t client.Target) {108 c.Lock()109 defer c.Unlock()110 // create target manager111 h, err := NewTargetHandler(t, c.logf, c.debugf, c.errf)112 if err != nil {113 c.errf("could not create handler for %s: %v", t, err)114 return115 }116 // run117 if err := h.Run(ctxt); err != nil {118 c.errf("could not start handler for %s: %v", t, err)119 return120 }121 // add to active handlers122 c.handlers = append(c.handlers, h)123 c.handlerMap[t.GetID()] = len(c.handlers) - 1124 if c.cur == nil {125 c.cur = h126 }127}128// Wait waits for the Chrome runner to terminate.129func (c *CDP) Wait() error {130 c.RLock()131 r := c.r132 c.RUnlock()133 if r != nil {134 return r.Wait()135 }136 return nil137}138// Shutdown closes all Chrome page handlers.139func (c *CDP) Shutdown(ctxt context.Context, opts ...client.Option) error {140 c.RLock()141 defer c.RUnlock()142 if c.r != nil {143 return c.r.Shutdown(ctxt, opts...)144 }145 return nil146}147// ListTargets returns the target IDs of the managed targets.148func (c *CDP) ListTargets() []string {149 c.RLock()150 defer c.RUnlock()151 i, targets := 0, make([]string, len(c.handlers))152 for k := range c.handlerMap {153 targets[i] = k154 i++155 }156 return targets157}158// GetHandlerByIndex retrieves the domains manager for the specified index.159func (c *CDP) GetHandlerByIndex(i int) cdp.Executor {160 c.RLock()161 defer c.RUnlock()162 if i < 0 || i >= len(c.handlers) {163 return nil164 }165 return c.handlers[i]166}167// GetHandlerByID retrieves the domains manager for the specified target ID.168func (c *CDP) GetHandlerByID(id string) cdp.Executor {169 c.RLock()170 defer c.RUnlock()171 if i, ok := c.handlerMap[id]; ok {172 return c.handlers[i]173 }174 return nil175}176// SetHandler sets the active handler to the target with the specified index.177func (c *CDP) SetHandler(i int) error {178 c.Lock()179 defer c.Unlock()180 if i < 0 || i >= len(c.handlers) {181 return fmt.Errorf("no handler associated with target index %d", i)182 }183 c.cur = c.handlers[i]184 return nil185}186// SetHandlerByID sets the active target to the target with the specified id.187func (c *CDP) SetHandlerByID(id string) error {188 c.Lock()189 defer c.Unlock()190 if i, ok := c.handlerMap[id]; ok {191 c.cur = c.handlers[i]192 return nil193 }194 return fmt.Errorf("no handler associated with target id %s", id)195}196// newTarget creates a new target using supplied context and options, returning197// the id of the created target only after the target has been started for198// monitoring.199func (c *CDP) newTarget(ctxt context.Context, opts ...client.Option) (string, error) {200 c.RLock()201 cl := c.r.Client(opts...)202 c.RUnlock()203 // new page target204 t, err := cl.NewPageTarget(ctxt)205 if err != nil {206 return "", err207 }208 timeout := time.After(DefaultNewTargetTimeout)209 for {210 select {211 default:212 var ok bool213 id := t.GetID()214 c.RLock()215 _, ok = c.handlerMap[id]216 c.RUnlock()217 if ok {218 return id, nil219 }220 time.Sleep(DefaultCheckDuration)221 case <-ctxt.Done():222 return "", ctxt.Err()223 case <-timeout:224 return "", errors.New("timeout waiting for new target to be available")225 }226 }227}228// SetTarget is an action that sets the active Chrome handler to the specified229// index i.230func (c *CDP) SetTarget(i int) Action {231 return ActionFunc(func(context.Context, cdp.Executor) error {232 return c.SetHandler(i)233 })234}235// SetTargetByID is an action that sets the active Chrome handler to the handler236// associated with the specified id.237func (c *CDP) SetTargetByID(id string) Action {238 return ActionFunc(func(context.Context, cdp.Executor) error {239 return c.SetHandlerByID(id)240 })241}242// NewTarget is an action that creates a new Chrome target, and sets it as the243// active target.244func (c *CDP) NewTarget(id *string, opts ...client.Option) Action {245 return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {246 n, err := c.newTarget(ctxt, opts...)247 if err != nil {248 return err249 }250 if id != nil {251 *id = n252 }253 return nil254 })255}256// CloseByIndex closes the Chrome target with specified index i.257func (c *CDP) CloseByIndex(i int) Action {258 return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {259 return nil260 })261}262// CloseByID closes the Chrome target with the specified id.263func (c *CDP) CloseByID(id string) Action {264 return ActionFunc(func(ctxt context.Context, h cdp.Executor) error {265 return nil266 })267}268// Run executes the action against the current target using the supplied269// context.270func (c *CDP) Run(ctxt context.Context, a Action) error {271 c.RLock()272 cur := c.cur273 c.RUnlock()274 return a.Do(ctxt, cur)275}276// Option is a Chrome DevTools Protocol option.277type Option func(*CDP) error278// WithRunner is a CDP option to specify the underlying Chrome runner to279// monitor for page handlers.280func WithRunner(r *runner.Runner) Option {281 return func(c *CDP) error {282 c.r = r283 return nil284 }285}286// WithTargets is a CDP option to specify the incoming targets to monitor for287// page handlers.288func WithTargets(watch <-chan client.Target) Option {289 return func(c *CDP) error {290 c.watch = watch291 return nil292 }293}294// WithClient is a CDP option to use the incoming targets from a client.295func WithClient(ctxt context.Context, cl *client.Client) Option {296 return func(c *CDP) error {297 return WithTargets(cl.WatchPageTargets(ctxt))(c)298 }299}300// WithURL is a CDP option to use a client with the specified URL.301func WithURL(ctxt context.Context, urlstr string) Option {302 return func(c *CDP) error {303 return WithClient(ctxt, client.New(client.URL(urlstr)))(c)304 }305}306// WithRunnerOptions is a CDP option to specify the options to pass to a newly307// created Chrome process runner.308func WithRunnerOptions(opts ...runner.CommandLineOption) Option {309 return func(c *CDP) error {310 c.opts = opts311 return nil312 }313}314// WithLogf is a CDP option to specify a func to receive general logging.315func WithLogf(f func(string, ...interface{})) Option {316 return func(c *CDP) error {317 c.logf = f318 return nil319 }320}321// WithDebugf is a CDP option to specify a func to receive debug logging (ie,322// protocol information).323func WithDebugf(f func(string, ...interface{})) Option {324 return func(c *CDP) error {325 c.debugf = f326 return nil327 }328}329// WithErrorf is a CDP option to specify a func to receive error logging.330func WithErrorf(f func(string, ...interface{})) Option {331 return func(c *CDP) error {332 c.errf = f333 return nil334 }335}336// WithLog is a CDP option that sets the logging, debugging, and error funcs to337// f.338func WithLog(f func(string, ...interface{})) Option {339 return func(c *CDP) error {340 c.logf, c.debugf, c.errf = f, f, f341 return nil342 }343}344// WithConsolef is a CDP option to specify a func to receive chrome log events.345//346// Note: NOT YET IMPLEMENTED.347func WithConsolef(f func(string, ...interface{})) Option {348 return func(c *CDP) error {349 return nil350 }351}352var (353 // defaultNewTargetTimeout is the default target timeout -- used by354 // testing.355 defaultNewTargetTimeout = DefaultNewTargetTimeout356)...
util.go
Source:util.go
1package chromedp2import (3 "github.com/chromedp/cdproto"4 "github.com/chromedp/cdproto/cdp"5)6// frameOp is a frame manipulation operation.7type frameOp func(*cdp.Frame)8/*func domContentEventFired(f *cdp.Frame) {9}10func loadEventFired(f *cdp.Frame) {11}*/12func frameAttached(id cdp.FrameID) frameOp {13 return func(f *cdp.Frame) {14 f.ParentID = id15 setFrameState(f, cdp.FrameAttached)16 }17}18/*func frameNavigated(f *cdp.Frame) {19 setFrameState(f, cdp.FrameNavigated)20}*/21func frameDetached(f *cdp.Frame) {22 f.ParentID = cdp.EmptyFrameID23 clearFrameState(f, cdp.FrameAttached)24}25func frameStartedLoading(f *cdp.Frame) {26 setFrameState(f, cdp.FrameLoading)27}28func frameStoppedLoading(f *cdp.Frame) {29 clearFrameState(f, cdp.FrameLoading)30}31func frameScheduledNavigation(f *cdp.Frame) {32 setFrameState(f, cdp.FrameScheduledNavigation)33}34func frameClearedScheduledNavigation(f *cdp.Frame) {35 clearFrameState(f, cdp.FrameScheduledNavigation)36}37/*func frameResized(f *cdp.Frame) {38 // TODO39}*/40// setFrameState sets the frame state via bitwise or (|).41func setFrameState(f *cdp.Frame, fs cdp.FrameState) {42 f.State |= fs43}44// clearFrameState clears the frame state via bit clear (&^).45func clearFrameState(f *cdp.Frame, fs cdp.FrameState) {46 f.State &^= fs47}48// nodeOp is a node manipulation operation.49type nodeOp func(*cdp.Node)50func walk(m map[cdp.NodeID]*cdp.Node, n *cdp.Node) {51 n.RLock()52 defer n.RUnlock()53 m[n.NodeID] = n54 for _, c := range n.Children {55 c.Lock()56 c.Parent = n57 c.Invalidated = n.Invalidated58 c.Unlock()59 walk(m, c)60 }61 for _, c := range n.ShadowRoots {62 c.Lock()63 c.Parent = n64 c.Invalidated = n.Invalidated65 c.Unlock()66 walk(m, c)67 }68 for _, c := range n.PseudoElements {69 c.Lock()70 c.Parent = n71 c.Invalidated = n.Invalidated72 c.Unlock()73 walk(m, c)74 }75 for _, c := range []*cdp.Node{n.ContentDocument, n.TemplateContent, n.ImportedDocument} {76 if c == nil {77 continue78 }79 c.Lock()80 c.Parent = n81 c.Invalidated = n.Invalidated82 c.Unlock()83 walk(m, c)84 }85}86func setChildNodes(m map[cdp.NodeID]*cdp.Node, nodes []*cdp.Node) nodeOp {87 return func(n *cdp.Node) {88 n.Lock()89 n.Children = nodes90 n.Unlock()91 walk(m, n)92 }93}94func attributeModified(name, value string) nodeOp {95 return func(n *cdp.Node) {96 n.Lock()97 defer n.Unlock()98 var found bool99 var i int100 for ; i < len(n.Attributes); i += 2 {101 if n.Attributes[i] == name {102 found = true103 break104 }105 }106 if found {107 n.Attributes[i] = name108 n.Attributes[i+1] = value109 } else {110 n.Attributes = append(n.Attributes, name, value)111 }112 }113}114func attributeRemoved(name string) nodeOp {115 return func(n *cdp.Node) {116 n.Lock()117 defer n.Unlock()118 var a []string119 for i := 0; i < len(n.Attributes); i += 2 {120 if n.Attributes[i] == name {121 continue122 }123 a = append(a, n.Attributes[i], n.Attributes[i+1])124 }125 n.Attributes = a126 }127}128func inlineStyleInvalidated(ids []cdp.NodeID) nodeOp {129 return func(n *cdp.Node) {130 }131}132func characterDataModified(characterData string) nodeOp {133 return func(n *cdp.Node) {134 n.Lock()135 defer n.Unlock()136 n.Value = characterData137 }138}139func childNodeCountUpdated(count int64) nodeOp {140 return func(n *cdp.Node) {141 n.Lock()142 defer n.Unlock()143 n.ChildNodeCount = count144 }145}146func childNodeInserted(m map[cdp.NodeID]*cdp.Node, prevID cdp.NodeID, c *cdp.Node) nodeOp {147 return func(n *cdp.Node) {148 n.Lock()149 n.Children = insertNode(n.Children, prevID, c)150 n.Unlock()151 walk(m, n)152 }153}154func childNodeRemoved(m map[cdp.NodeID]*cdp.Node, id cdp.NodeID) nodeOp {155 return func(n *cdp.Node) {156 n.Lock()157 defer n.Unlock()158 n.Children = removeNode(n.Children, id)159 delete(m, id)160 }161}162func shadowRootPushed(m map[cdp.NodeID]*cdp.Node, c *cdp.Node) nodeOp {163 return func(n *cdp.Node) {164 n.Lock()165 n.ShadowRoots = append(n.ShadowRoots, c)166 n.Unlock()167 walk(m, n)168 }169}170func shadowRootPopped(m map[cdp.NodeID]*cdp.Node, id cdp.NodeID) nodeOp {171 return func(n *cdp.Node) {172 n.Lock()173 defer n.Unlock()174 n.ShadowRoots = removeNode(n.ShadowRoots, id)175 delete(m, id)176 }177}178func pseudoElementAdded(m map[cdp.NodeID]*cdp.Node, c *cdp.Node) nodeOp {179 return func(n *cdp.Node) {180 n.Lock()181 n.PseudoElements = append(n.PseudoElements, c)182 n.Unlock()183 walk(m, n)184 }185}186func pseudoElementRemoved(m map[cdp.NodeID]*cdp.Node, id cdp.NodeID) nodeOp {187 return func(n *cdp.Node) {188 n.Lock()189 defer n.Unlock()190 n.PseudoElements = removeNode(n.PseudoElements, id)191 delete(m, id)192 }193}194func distributedNodesUpdated(nodes []*cdp.BackendNode) nodeOp {195 return func(n *cdp.Node) {196 n.Lock()197 defer n.Unlock()198 n.DistributedNodes = nodes199 }200}201func insertNode(n []*cdp.Node, prevID cdp.NodeID, c *cdp.Node) []*cdp.Node {202 var i int203 var found bool204 for ; i < len(n); i++ {205 if n[i].NodeID == prevID {206 found = true207 break208 }209 }210 if !found {211 return append(n, c)212 }213 i++214 n = append(n, nil)215 copy(n[i+1:], n[i:])216 n[i] = c217 return n218}219func removeNode(n []*cdp.Node, id cdp.NodeID) []*cdp.Node {220 if len(n) == 0 {221 return n222 }223 var found bool224 var i int225 for ; i < len(n); i++ {226 if n[i].NodeID == id {227 found = true228 break229 }230 }231 if !found {232 return n233 }234 return append(n[:i], n[i+1:]...)235}236// isCouldNotComputeBoxModelError unwraps err as a MessageError and determines237// if it is a compute box model error.238func isCouldNotComputeBoxModelError(err error) bool {239 e, ok := err.(*cdproto.Error)240 return ok && e.Code == -32000 && e.Message == "Could not compute box model."241}...
Is
Using AI Code Generation
1import (2func main() {3 c := colly.NewCollector()4 c.OnHTML("a[href]", func(e *colly.HTMLElement) {5 link := e.Attr("href")6 fmt.Printf("Link found: %q -> %s7 e.Request.Visit(e.Request.AbsoluteURL(link))8 })9 c.OnRequest(func(r *colly.Request) {10 fmt.Println("Visiting", r.URL.String())11 })12}
Is
Using AI Code Generation
1import (2func main() {3 conn := redigomock.NewConn()4 conn.Command("SET", "foo", "bar").Expect("OK")5 conn.Command("GET", "foo").Expect("bar")6 conn.Command("GET", "foo").ExpectError(redis.ErrNil)7 conn.Command("SET", "foo", "bar").ExpectError(fmt.Errorf("some error"))8 conn.Command("SET", "foo", "bar").Expect("OK")9 conn.Command("GET", "foo").Expect("bar")10 conn.Command("GET", "foo").ExpectError(redis.ErrNil)11 conn.Command("SET", "foo", "bar").ExpectError(fmt.Errorf("some error"))
Is
Using AI Code Generation
1import (2func main() {3 cdp := golcdp.Cdp{}4 cdp.Is("2.go")5}6import (7func main() {8 cdp := golcdp.Cdp{}9 cdp.Is("3.go")10}11import (12func main() {13 cdp := golcdp.Cdp{}14 cdp.Is("4.go")15}16func (cdp Cdp) Is(filePath string) bool {17 file, err := os.Open(filePath)18 if err != nil {19 log.Fatal(err)20 }21 defer file.Close()22 scanner := bufio.NewScanner(file)23 for scanner.Scan() {24 if strings.Contains(scanner.Text(), "package main") {25 log.Println("[" + filePath + "] is a CDP file")26 }27 }28 if err := scanner.Err(); err != nil {29 log.Fatal(err)30 }31 log.Println("[" + filePath + "] is not a C
Is
Using AI Code Generation
1import (2func main() {3 cdpObj := cdp.NewCDP("2.go")4 if cdpObj.Is("2.go") {5 fmt.Println("This is the process that started the cdp")6 } else {7 fmt.Println("This is NOT the process that started the cdp")8 }9}
Is
Using AI Code Generation
1import (2func main() {3 c = cdp.CDP{1, 2, 3}4 fmt.Println(c.Is(1))5}6type CDP struct {7}8func (c CDP) Is(i int) bool {9}10The Is method is defined as a method on the CDP struct. The cdp package is imported into the main package. The main package has a main function. The main function calls the Is method of the cdp package. The Is
Is
Using AI Code Generation
1import (2func main() {3 cdp := cdp.CDP{}4 cdp.Set(1)5 if cdp.Is() {6 fmt.Println("CDP is set")7 } else {8 fmt.Println("CDP is not set")9 }10}
Is
Using AI Code Generation
1import "fmt"2import "github.com/akshaykumar6/CDP"3func main() {4 var cd = cdp.New(1)5 fmt.Println(cd.Is(1))6 fmt.Println(cd.Is(2))7}
Is
Using AI Code Generation
1import (2func main() {3 c := cdp.New("1000")4 if c.Is() {5 fmt.Println("Valid CDP")6 } else {7 fmt.Println("Invalid CDP")8 }9}10import (11func main() {12 c := cdp.New("100")13 if c.Is() {14 fmt.Println("Valid CDP")15 } else {16 fmt.Println("Invalid CDP")17 }18}19import (20func main() {21 c := cdp.New("1000")22 if c.Is() {23 fmt.Println("Valid CDP")24 } else {25 fmt.Println("Invalid CDP")26 }27}28import (29func main() {30 c := cdp.New("1000")31 if c.Is() {32 fmt.Println("Valid CDP")33 } else {34 fmt.Println("Invalid CDP")35 }36}37import (38func main() {39 c := cdp.New("1000")40 if c.Is() {41 fmt.Println("Valid CDP")42 } else {43 fmt.Println("Invalid CDP")44 }45}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!