From 0243a30b10871506324281942f9b16eeb45fdc12 Mon Sep 17 00:00:00 2001 From: Yad Smood Date: Sun, 18 Feb 2024 17:14:38 +0800 Subject: [PATCH] fix lint issues --- .golangci.yml | 106 +- browser.go | 36 +- browser_test.go | 18 +- context.go | 42 +- cspell.json | 261 +++-- dev_helpers.go | 32 +- element.go | 76 +- element_test.go | 31 +- error.go | 144 +-- examples_test.go | 10 +- hijack.go | 42 +- hijack_test.go | 10 +- input.go | 46 +- lib/assets/assets.go | 6 +- lib/cdp/client.go | 20 +- lib/cdp/client_test.go | 2 +- lib/cdp/error.go | 20 +- lib/cdp/utils.go | 6 +- lib/cdp/websocket.go | 21 +- lib/cdp/websocket_test.go | 4 +- lib/defaults/defaults.go | 6 +- lib/devices/device.go | 10 +- lib/devices/list.go | 72 +- lib/devices/utils.go | 2 +- lib/docker/main.go | 7 +- lib/examples/compare-chromedp/keys/main.go | 4 +- lib/examples/compare-chromedp/proxy/main.go | 6 +- lib/examples/compare-chromedp/subtree/main.go | 2 +- lib/examples/compare-chromedp/upload/main.go | 4 +- lib/examples/compare-chromedp/visible/main.go | 2 +- lib/examples/connect-browser/main.go | 2 +- lib/examples/disable-window-alert/main.go | 4 +- lib/examples/stripe/main.go | 2 +- lib/input/keyboard.go | 18 +- lib/input/keymap.go | 16 +- lib/input/mac_comands.go | 4 +- lib/input/mouse.go | 4 +- lib/js/generate/main.go | 2 +- lib/js/js.go | 2 +- lib/launcher/browser.go | 27 +- lib/launcher/flags/flags.go | 30 +- lib/launcher/launcher.go | 40 +- lib/launcher/manager.go | 16 +- lib/launcher/os_unix.go | 1 + lib/launcher/private_test.go | 4 +- lib/launcher/revision.go | 4 +- lib/launcher/revision/main.go | 4 +- lib/launcher/rod-manager/main.go | 2 +- lib/launcher/url_parser.go | 14 +- lib/proto/a_interface.go | 12 +- lib/proto/a_patch.go | 32 +- lib/proto/a_utils.go | 2 +- lib/proto/accessibility.go | 188 +-- lib/proto/animation.go | 70 +- lib/proto/audits.go | 312 ++--- lib/proto/background_service.go | 34 +- lib/proto/browser.go | 188 +-- lib/proto/cache_storage.go | 40 +- lib/proto/cast.go | 28 +- lib/proto/console.go | 50 +- lib/proto/css.go | 158 +-- lib/proto/database.go | 18 +- lib/proto/debugger.go | 270 ++--- lib/proto/definitions.go | 6 +- lib/proto/definitions_test.go | 4 +- lib/proto/device_access.go | 18 +- lib/proto/device_orientation.go | 8 +- lib/proto/dom.go | 392 +++---- lib/proto/dom_debugger.go | 54 +- lib/proto/dom_snapshot.go | 16 +- lib/proto/dom_storage.go | 32 +- lib/proto/emulation.go | 168 +-- lib/proto/event_breakpoints.go | 8 +- lib/proto/fed_cm.go | 28 +- lib/proto/fetch.go | 62 +- lib/proto/generate/main.go | 9 +- lib/proto/generate/schema.go | 1 - lib/proto/generate/utils.go | 8 +- lib/proto/headless_experimental.go | 20 +- lib/proto/heap_profiler.go | 60 +- lib/proto/indexed_db.go | 62 +- lib/proto/input.go | 164 +-- lib/proto/inspector.go | 18 +- lib/proto/io.go | 22 +- lib/proto/layer_tree.go | 56 +- lib/proto/log.go | 84 +- lib/proto/media.go | 40 +- lib/proto/memory.go | 56 +- lib/proto/network.go | 710 ++++++------ lib/proto/overlay.go | 180 +-- lib/proto/page.go | 1012 ++++++++--------- lib/proto/performance.go | 30 +- lib/proto/performance_timeline.go | 16 +- lib/proto/preload.go | 174 +-- lib/proto/profiler.go | 48 +- lib/proto/runtime.go | 382 +++---- lib/proto/schema.go | 4 +- lib/proto/security.go | 62 +- lib/proto/service_worker.go | 78 +- lib/proto/storage.go | 220 ++-- lib/proto/system_info.go | 28 +- lib/proto/target.go | 100 +- lib/proto/tethering.go | 16 +- lib/proto/tracing.go | 64 +- lib/proto/web_audio.go | 86 +- lib/proto/web_authn.go | 70 +- lib/utils/imageutil.go | 9 +- lib/utils/imageutil_test.go | 18 +- lib/utils/shell/shell.go | 4 +- lib/utils/sleeper.go | 27 +- lib/utils/sleeper_test.go | 4 +- lib/utils/utils.go | 64 +- must.go | 5 +- page.go | 68 +- page_eval.go | 17 +- page_eval_test.go | 12 +- page_test.go | 30 +- query.go | 114 +- query_test.go | 20 +- setup_test.go | 17 +- states.go | 12 +- utils.go | 24 +- 122 files changed, 3949 insertions(+), 3818 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index ead4236c..475e5722 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,19 +2,70 @@ run: skip-dirs-use-default: false linters: - enable: - - gofumpt - - revive - - gocyclo - - bodyclose + enable-all: true + disable: + - gochecknoinits + - paralleltest + - wrapcheck + - gosec + - gochecknoglobals + - musttag + - varnamelen + - wsl + - nonamedreturns + - tagliatelle + - nlreturn + - nakedret + - gomnd + - goerr113 + - exhaustruct + - godox + - depguard + - testpackage + - exhaustive + - containedctx + - prealloc + - perfsprint + - ireturn + - contextcheck -gocyclo: - min-complexity: 15 + # Deprecated ones: + - structcheck + - interfacer + - deadcode + - varcheck + - ifshort + - exhaustivestruct + - golint + - maligned + - nosnakecase + - scopelint + +linters-settings: + cyclop: + max-complexity: 15 + gocyclo: + min-complexity: 15 + nestif: + min-complexity: 6 + funlen: + lines: 120 issues: exclude-use-default: false exclude-rules: + - path: _test.go$ + linters: + - lll + - funlen + - dupword + - goconst + - contextcheck + - errorlint + - testableexamples + - forcetypeassert + # To support old golang version - path: lib/launcher/os_unix.go source: "// \\+build !windows" @@ -30,3 +81,44 @@ issues: - source: 'io/ioutil' linters: - staticcheck + + # Generated code + - path: lib/proto/ + linters: + - lll + - gocritic + - dupword + - forcetypeassert + - path: lib/devices/list.go + linters: + - lll + - path: lib/js/helper.go + linters: + - lll + + - path: /fixtures/ + linters: + - forbidigo + + - path: lib/examples/ + linters: + - forbidigo + - noctx + - gocritic + + - path: examples?_test.go$ + linters: + - forbidigo + - noctx + - gocritic + + - path: main.go$ + linters: + - forbidigo + - noctx + - forcetypeassert + - lll + + - path: lib/assets/ + linters: + - lll diff --git a/browser.go b/browser.go index 9af92c15..bd2045f5 100644 --- a/browser.go +++ b/browser.go @@ -23,7 +23,7 @@ import ( "github.com/ysmood/goob" ) -// Browser implements these interfaces +// Browser implements these interfaces. var ( _ proto.Client = &Browser{} _ proto.Contextable = &Browser{} @@ -81,7 +81,7 @@ func New() *Browser { }).WithPanic(utils.Panic) } -// Incognito creates a new incognito browser +// Incognito creates a new incognito browser. func (b *Browser) Incognito() (*Browser, error) { res, err := proto.TargetCreateBrowserContext{}.Call(b) if err != nil { @@ -100,31 +100,31 @@ func (b *Browser) ControlURL(url string) *Browser { return b } -// SlowMotion set the delay for each control action, such as the simulation of the human inputs +// SlowMotion set the delay for each control action, such as the simulation of the human inputs. func (b *Browser) SlowMotion(delay time.Duration) *Browser { b.slowMotion = delay return b } -// Trace enables/disables the visual tracing of the input actions on the page +// Trace enables/disables the visual tracing of the input actions on the page. func (b *Browser) Trace(enable bool) *Browser { b.trace = enable return b } -// Monitor address to listen if not empty. Shortcut for [Browser.ServeMonitor] +// Monitor address to listen if not empty. Shortcut for [Browser.ServeMonitor]. func (b *Browser) Monitor(url string) *Browser { b.monitor = url return b } -// Logger overrides the default log functions for tracing +// Logger overrides the default log functions for tracing. func (b *Browser) Logger(l utils.Logger) *Browser { b.logger = l return b } -// Client set the cdp client +// Client set the cdp client. func (b *Browser) Client(c CDPClient) *Browser { b.client = c return b @@ -138,7 +138,7 @@ func (b *Browser) DefaultDevice(d devices.Device) *Browser { return b } -// NoDefaultDevice is the same as [Browser.DefaultDevice](devices.Clear) +// NoDefaultDevice is the same as [Browser.DefaultDevice](devices.Clear). func (b *Browser) NoDefaultDevice() *Browser { return b.DefaultDevice(devices.Clear) } @@ -174,7 +174,7 @@ func (b *Browser) Connect() error { return proto.TargetSetDiscoverTargets{Discover: true}.Call(b) } -// Close the browser +// Close the browser. func (b *Browser) Close() error { if b.BrowserContextID == "" { return proto.BrowserClose{}.Call(b) @@ -213,7 +213,7 @@ func (b *Browser) Page(opts proto.TargetCreateTarget) (p *Page, err error) { return } -// Pages retrieves all visible pages +// Pages retrieves all visible pages. func (b *Browser) Pages() (Pages, error) { list, err := proto.TargetGetTargets{}.Call(b) if err != nil { @@ -247,7 +247,7 @@ func (b *Browser) Call(ctx context.Context, sessionID, methodName string, params return } -// PageFromSession is used for low-level debugging +// PageFromSession is used for low-level debugging. func (b *Browser) PageFromSession(sessionID proto.TargetSessionID) *Page { sessionCtx, cancel := context.WithCancel(b.ctx) return &Page{ @@ -358,7 +358,7 @@ func (b *Browser) eachEvent(sessionID proto.TargetSessionID, callbacks ...interf for _, cb := range callbacks { cbVal := reflect.ValueOf(cb) eType := cbVal.Type().In(0) - name := reflect.New(eType.Elem()).Interface().(proto.Event).ProtoEvent() + name := reflect.New(eType.Elem()).Interface().(proto.Event).ProtoEvent() //nolint: forcetypeassert cbMap[name] = cbVal // Only enabled domains will emit events to cdp client. @@ -366,7 +366,7 @@ func (b *Browser) eachEvent(sessionID proto.TargetSessionID, callbacks ...interf // We restore the domains to their previous states after the wait ends. domain, _ := proto.ParseMethodName(name) if req := proto.GetType(domain + ".enable"); req != nil { - enable := reflect.New(req).Interface().(proto.Request) + enable := reflect.New(req).Interface().(proto.Request) //nolint: forcetypeassert restores = append(restores, b.EnableDomain(sessionID, enable)) } } @@ -394,7 +394,7 @@ func (b *Browser) eachEvent(sessionID proto.TargetSessionID, callbacks ...interf if cbVal, has := cbMap[msg.Method]; has { e := reflect.New(proto.GetType(msg.Method)) - msg.Load(e.Interface().(proto.Event)) + msg.Load(e.Interface().(proto.Event)) //nolint: forcetypeassert args := []reflect.Value{e} if cbVal.Type().NumIn() == 2 { args = append(args, reflect.ValueOf(msg.SessionID)) @@ -410,7 +410,7 @@ func (b *Browser) eachEvent(sessionID proto.TargetSessionID, callbacks ...interf } } -// Event of the browser +// Event of the browser. func (b *Browser) Event() <-chan *Message { src := b.event.Subscribe(b.ctx) dst := make(chan *Message) @@ -427,7 +427,7 @@ func (b *Browser) Event() <-chan *Message { select { case <-b.ctx.Done(): return - case dst <- e.(*Message): + case dst <- e.(*Message): //nolint: forcetypeassert } } } @@ -476,7 +476,7 @@ func (b *Browser) IgnoreCertErrors(enable bool) error { return proto.SecuritySetIgnoreCertificateErrors{Ignore: enable}.Call(b) } -// GetCookies from the browser +// GetCookies from the browser. func (b *Browser) GetCookies() ([]*proto.NetworkCookie, error) { res, err := proto.StorageGetCookies{BrowserContextID: b.BrowserContextID}.Call(b) if err != nil { @@ -537,7 +537,7 @@ func (b *Browser) WaitDownload(dir string) func() (info *proto.PageDownloadWillB } } -// Version info of the browser +// Version info of the browser. func (b *Browser) Version() (*proto.BrowserGetVersionResult, error) { return proto.BrowserGetVersion{}.Call(b) } diff --git a/browser_test.go b/browser_test.go index 6c20f5d7..38aecfd4 100644 --- a/browser_test.go +++ b/browser_test.go @@ -50,7 +50,7 @@ func TestDefaultDevice(t *testing.T) { ua := "" s := g.Serve() - s.Mux.HandleFunc("/t", func(rw http.ResponseWriter, r *http.Request) { + s.Mux.HandleFunc("/t", func(_ http.ResponseWriter, r *http.Request) { ua = r.Header.Get("User-Agent") }) @@ -153,7 +153,7 @@ func TestBrowserWaitEvent(t *testing.T) { g.page.MustNavigate(g.blank()) wait() - wait = g.browser.EachEvent(func(e *proto.PageFrameNavigated, id proto.TargetSessionID) bool { + wait = g.browser.EachEvent(func(_ *proto.PageFrameNavigated, _ proto.TargetSessionID) bool { return true }) g.page.MustNavigate(g.blank()) @@ -201,7 +201,7 @@ func TestBlockingNavigation(t *testing.T) { s := g.Serve() pause := g.Context() - s.Mux.HandleFunc("/a", func(w http.ResponseWriter, r *http.Request) { + s.Mux.HandleFunc("/a", func(_ http.ResponseWriter, _ *http.Request) { <-pause.Done() }) s.Route("/b", ".html", `ok`) @@ -226,7 +226,7 @@ func TestResolveBlocking(t *testing.T) { pause := g.Context() - s.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + s.Mux.HandleFunc("/", func(_ http.ResponseWriter, _ *http.Request) { <-pause.Done() }) @@ -248,14 +248,14 @@ func TestTestTry(t *testing.T) { g.Nil(rod.Try(func() {})) err := rod.Try(func() { panic(1) }) - var errVal *rod.ErrTry + var errVal *rod.TryError g.True(errors.As(err, &errVal)) - g.Is(err, &rod.ErrTry{}) + g.Is(err, &rod.TryError{}) g.Eq(errVal.Unwrap().Error(), "1") g.Eq(1, errVal.Value) g.Has(errVal.Error(), "error value: 1\ngoroutine") - errVal = rod.Try(func() { panic(errors.New("t")) }).(*rod.ErrTry) + errVal = rod.Try(func() { panic(errors.New("t")) }).(*rod.TryError) g.Eq(errVal.Unwrap().Error(), "t") } @@ -405,7 +405,7 @@ func TestStreamReader(t *testing.T) { r := rod.NewStreamReader(g.page, "") - g.mc.stub(1, proto.IORead{}, func(send StubSend) (gson.JSON, error) { + g.mc.stub(1, proto.IORead{}, func(_ StubSend) (gson.JSON, error) { return gson.New(proto.IOReadResult{ Data: "test", }), nil @@ -418,7 +418,7 @@ func TestStreamReader(t *testing.T) { _, err := r.Read(nil) g.Err(err) - g.mc.stub(1, proto.IORead{}, func(send StubSend) (gson.JSON, error) { + g.mc.stub(1, proto.IORead{}, func(_ StubSend) (gson.JSON, error) { return gson.New(proto.IOReadResult{ Base64Encoded: true, Data: "@", diff --git a/context.go b/context.go index 39dadbe6..b7706954 100644 --- a/context.go +++ b/context.go @@ -15,45 +15,45 @@ type ( } ) -// Context returns a clone with the specified ctx for chained sub-operations +// Context returns a clone with the specified ctx for chained sub-operations. func (b *Browser) Context(ctx context.Context) *Browser { newObj := *b newObj.ctx = ctx return &newObj } -// GetContext of current instance +// GetContext of current instance. func (b *Browser) GetContext() context.Context { return b.ctx } -// Timeout returns a clone with the specified total timeout of all chained sub-operations +// Timeout returns a clone with the specified total timeout of all chained sub-operations. func (b *Browser) Timeout(d time.Duration) *Browser { ctx, cancel := context.WithTimeout(b.ctx, d) return b.Context(context.WithValue(ctx, timeoutContextKey{}, &timeoutContextVal{b.ctx, cancel})) } -// CancelTimeout cancels the current timeout context and returns a clone with the parent context +// CancelTimeout cancels the current timeout context and returns a clone with the parent context. func (b *Browser) CancelTimeout() *Browser { - val := b.ctx.Value(timeoutContextKey{}).(*timeoutContextVal) + val := b.ctx.Value(timeoutContextKey{}).(*timeoutContextVal) //nolint:forcetypeassert val.cancel() return b.Context(val.parent) } -// WithCancel returns a clone with a context cancel function +// WithCancel returns a clone with a context cancel function. func (b *Browser) WithCancel() (*Browser, func()) { ctx, cancel := context.WithCancel(b.ctx) return b.Context(ctx), cancel } -// Sleeper returns a clone with the specified sleeper for chained sub-operations +// Sleeper returns a clone with the specified sleeper for chained sub-operations. func (b *Browser) Sleeper(sleeper func() utils.Sleeper) *Browser { newObj := *b newObj.sleeper = sleeper return &newObj } -// Context returns a clone with the specified ctx for chained sub-operations +// Context returns a clone with the specified ctx for chained sub-operations. func (p *Page) Context(ctx context.Context) *Page { p.helpersLock.Lock() newObj := *p @@ -62,69 +62,69 @@ func (p *Page) Context(ctx context.Context) *Page { return &newObj } -// GetContext of current instance +// GetContext of current instance. func (p *Page) GetContext() context.Context { return p.ctx } -// Timeout returns a clone with the specified total timeout of all chained sub-operations +// Timeout returns a clone with the specified total timeout of all chained sub-operations. func (p *Page) Timeout(d time.Duration) *Page { ctx, cancel := context.WithTimeout(p.ctx, d) return p.Context(context.WithValue(ctx, timeoutContextKey{}, &timeoutContextVal{p.ctx, cancel})) } -// CancelTimeout cancels the current timeout context and returns a clone with the parent context +// CancelTimeout cancels the current timeout context and returns a clone with the parent context. func (p *Page) CancelTimeout() *Page { - val := p.ctx.Value(timeoutContextKey{}).(*timeoutContextVal) + val := p.ctx.Value(timeoutContextKey{}).(*timeoutContextVal) //nolint: forcetypeassert val.cancel() return p.Context(val.parent) } -// WithCancel returns a clone with a context cancel function +// WithCancel returns a clone with a context cancel function. func (p *Page) WithCancel() (*Page, func()) { ctx, cancel := context.WithCancel(p.ctx) return p.Context(ctx), cancel } -// Sleeper returns a clone with the specified sleeper for chained sub-operations +// Sleeper returns a clone with the specified sleeper for chained sub-operations. func (p *Page) Sleeper(sleeper func() utils.Sleeper) *Page { newObj := *p newObj.sleeper = sleeper return &newObj } -// Context returns a clone with the specified ctx for chained sub-operations +// Context returns a clone with the specified ctx for chained sub-operations. func (el *Element) Context(ctx context.Context) *Element { newObj := *el newObj.ctx = ctx return &newObj } -// GetContext of current instance +// GetContext of current instance. func (el *Element) GetContext() context.Context { return el.ctx } -// Timeout returns a clone with the specified total timeout of all chained sub-operations +// Timeout returns a clone with the specified total timeout of all chained sub-operations. func (el *Element) Timeout(d time.Duration) *Element { ctx, cancel := context.WithTimeout(el.ctx, d) return el.Context(context.WithValue(ctx, timeoutContextKey{}, &timeoutContextVal{el.ctx, cancel})) } -// CancelTimeout cancels the current timeout context and returns a clone with the parent context +// CancelTimeout cancels the current timeout context and returns a clone with the parent context. func (el *Element) CancelTimeout() *Element { - val := el.ctx.Value(timeoutContextKey{}).(*timeoutContextVal) + val := el.ctx.Value(timeoutContextKey{}).(*timeoutContextVal) //nolint: forcetypeassert val.cancel() return el.Context(val.parent) } -// WithCancel returns a clone with a context cancel function +// WithCancel returns a clone with a context cancel function. func (el *Element) WithCancel() (*Element, func()) { ctx, cancel := context.WithCancel(el.ctx) return el.Context(ctx), cancel } -// Sleeper returns a clone with the specified sleeper for chained sub-operations +// Sleeper returns a clone with the specified sleeper for chained sub-operations. func (el *Element) Sleeper(sleeper func() utils.Sleeper) *Element { newObj := *el newObj.sleeper = sleeper diff --git a/cspell.json b/cspell.json index ba806af8..210251b5 100644 --- a/cspell.json +++ b/cspell.json @@ -1,129 +1,138 @@ // cSpell Settings { - // Version of the setting file. Always 0.2 - "version": "0.2", - // language - current active spelling language - "language": "en", - "ignorePaths": [ - "**/*.{out,sketch,svg}", - "fixtures/fonts.html", - "**/tmp/**", - "lib/devices/list.go", - "lib/js/helper.go", - "lib/proto/!(a_*)", - "**/go.{mod,sum}" - ], - // words - list of words to be always considered correct - "words": [ - "APPDATA", - "Arraybuffer", - "backgrounding", - "backoff", - "Backquote", - "beforeunload", - "bodyclose", - "breakpad", - "Chromedp", - "codesearch", - "commandline", - "COMSPEC", - "containerenv", - "contenteditable", - "Contentful", - "Contextable", - "coverprofile", - "Dataview", - "datetime", - "dockerenv", - "dropzone", - "duckduckgo", - "enctype", - "errcheck", - "evenodd", - "excludesfile", - "fetchup", - "fontconfig", - "Fullscreen", - "Geolocation", - "getent", - "gobwas", - "gocyclo", - "GODEBUG", - "gofmt", - "gofumpt", - "goimports", - "golangci", - "goob", - "gopls", - "goproxy", - "gotrace", - "gson", - "headful", - "iframe", - "iframes", - "Interactable", - "ioutil", - "keychain", - "KHTML", - "ldflags", - "leakless", - "libasound", - "libcairo", - "libgbm", - "libgobject", - "libgtk", - "libnss", - "libxss", - "libxtst", - "Lmsgprefix", - "loglevel", - "MDPI", - "MITM", - "mitmproxy", - "mvdan", - "Noto", - "Numpad", - "onbeforeunload", - "onclick", - "onmouseenter", - "onmouseout", - "opencontainers", - "osversion", - "progresser", - "proto", - "proxyauth", - "Rects", - "repost", - "sattributes", - "schildren", - "Sessionable", - "Smood", - "Socketable", - "spki", - "spkis", - "srgb", - "staticcheck", - "stdlib", - "termux", - "tlid", - "touchend", - "touchstart", - "tracebackancestors", - "trimpath", - "Typedarray", - "tzdata", - "Unserializable", - "Wasmvalue", - "Weakmap", - "Weakset", - "Webassemblymemory", - "wsutil", - "xlink", - "XVFB", - "ysmood" - ], - // flagWords - list of words to be always considered incorrect - // This is useful for offensive words and common spelling errors. - // For example "hte" should be "the" - "flagWords": [] + // Version of the setting file. Always 0.2 + "version": "0.2", + // language - current active spelling language + "language": "en", + "ignorePaths": [ + "**/*.{out,sketch,svg}", + "fixtures/fonts.html", + "**/tmp/**", + "lib/devices/list.go", + "lib/js/helper.go", + "lib/proto/!(a_*)", + "**/go.{mod,sum}", + ".golangci.yml" + ], + // words - list of words to be always considered correct + "words": [ + "APPDATA", + "Arraybuffer", + "backgrounding", + "backoff", + "Backquote", + "beforeunload", + "bodyclose", + "breakpad", + "Chromedp", + "codesearch", + "commandline", + "COMSPEC", + "containerenv", + "contenteditable", + "Contentful", + "Contextable", + "contextcheck", + "coverprofile", + "Dataview", + "datetime", + "dockerenv", + "dropzone", + "duckduckgo", + "enctype", + "errcheck", + "evenodd", + "excludesfile", + "fetchup", + "fontconfig", + "forbidigo", + "forcetypeassert", + "Fullscreen", + "Geolocation", + "getent", + "gobwas", + "gocognit", + "gocyclo", + "GODEBUG", + "gofmt", + "gofumpt", + "goimports", + "golangci", + "goob", + "gopls", + "goproxy", + "gotrace", + "gson", + "headful", + "iframe", + "iframes", + "Interactable", + "ioutil", + "keychain", + "KHTML", + "ldflags", + "leakless", + "libasound", + "libcairo", + "libgbm", + "libgobject", + "libgtk", + "libnss", + "libxss", + "libxtst", + "Lmsgprefix", + "loglevel", + "MDPI", + "MITM", + "mitmproxy", + "mvdan", + "nilnil", + "noctx", + "nolint", + "Noto", + "Numpad", + "onbeforeunload", + "onclick", + "onmouseenter", + "onmouseout", + "opencontainers", + "osversion", + "progresser", + "proto", + "proxyauth", + "Rects", + "repost", + "sattributes", + "schildren", + "Sessionable", + "Smood", + "Socketable", + "spki", + "spkis", + "srgb", + "staticcheck", + "stdlib", + "termux", + "tlid", + "touchend", + "touchstart", + "tparallel", + "tracebackancestors", + "trimpath", + "Typedarray", + "tzdata", + "Unserializable", + "Wasmvalue", + "Weakmap", + "Weakset", + "Webassemblymemory", + "wsutil", + "xlink", + "XVFB", + "ysmood" + ], + // flagWords - list of words to be always considered incorrect + // This is useful for offensive words and common spelling errors. + // For example "hte" should be "the" + "flagWords": [] } diff --git a/dev_helpers.go b/dev_helpers.go index c0942627..c4527563 100644 --- a/dev_helpers.go +++ b/dev_helpers.go @@ -19,28 +19,28 @@ import ( "github.com/go-rod/rod/lib/utils" ) -// TraceType for logger +// TraceType for logger. type TraceType string -// String interface +// String interface. func (t TraceType) String() string { return fmt.Sprintf("[%s]", string(t)) } const ( - // TraceTypeWaitRequestsIdle type + // TraceTypeWaitRequestsIdle type. TraceTypeWaitRequestsIdle TraceType = "wait requests idle" - // TraceTypeWaitRequests type + // TraceTypeWaitRequests type. TraceTypeWaitRequests TraceType = "wait requests" - // TraceTypeQuery type + // TraceTypeQuery type. TraceTypeQuery TraceType = "query" - // TraceTypeWait type + // TraceTypeWait type. TraceTypeWait TraceType = "wait" - // TraceTypeInput type + // TraceTypeInput type. TraceTypeInput TraceType = "input" ) @@ -53,11 +53,11 @@ func (b *Browser) ServeMonitor(host string) string { utils.E(closeSvr()) }() - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { httHTML(w, assets.Monitor) }) - mux.HandleFunc("/api/pages", func(w http.ResponseWriter, r *http.Request) { - res, err := proto.TargetGetTargets{}.Call(b) + mux.HandleFunc("/api/pages", func(w http.ResponseWriter, _ *http.Request) { + res, err := proto.TargetGetTargets{}.Call(b) //nolint: contextcheck utils.E(err) list := []*proto.TargetTargetInfo{} @@ -70,12 +70,12 @@ func (b *Browser) ServeMonitor(host string) string { w.WriteHeader(http.StatusOK) utils.E(w.Write(utils.MustToJSONBytes(list))) }) - mux.HandleFunc("/page/", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/page/", func(w http.ResponseWriter, _ *http.Request) { httHTML(w, assets.MonitorPage) }) mux.HandleFunc("/api/page/", func(w http.ResponseWriter, r *http.Request) { id := r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:] - info, err := b.pageInfo(proto.TargetTargetID(id)) + info, err := b.pageInfo(proto.TargetTargetID(id)) //nolint: contextcheck utils.E(err) w.WriteHeader(http.StatusOK) utils.E(w.Write(utils.MustToJSONBytes(info))) @@ -86,13 +86,13 @@ func (b *Browser) ServeMonitor(host string) string { p := b.MustPageFromTargetID(target) w.Header().Add("Content-Type", "image/png;") - utils.E(w.Write(p.MustScreenshot())) + utils.E(w.Write(p.MustScreenshot())) //nolint: contextcheck }) return u } -// check method and sleep if needed +// check method and sleep if needed. func (b *Browser) trySlowMotion() { if b.slowMotion == 0 { return @@ -110,7 +110,7 @@ func (p *Page) ExposeHelpers(list ...*js.Function) { })) } -// Overlay a rectangle on the main frame with specified message +// Overlay a rectangle on the main frame with specified message. func (p *Page) Overlay(left, top, width, height float64, msg string) (remove func()) { id := utils.RandString(8) @@ -194,7 +194,7 @@ func (p *Page) tryTraceReq(includes, excludes []string) func(map[proto.NetworkRe return update } -// Overlay msg on the element +// Overlay msg on the element. func (el *Element) Overlay(msg string) (removeOverlay func()) { id := utils.RandString(8) diff --git a/element.go b/element.go index c78de541..97fceed0 100644 --- a/element.go +++ b/element.go @@ -8,23 +8,22 @@ import ( "strings" "time" - "github.com/ysmood/gson" - "github.com/go-rod/rod/lib/cdp" "github.com/go-rod/rod/lib/input" "github.com/go-rod/rod/lib/js" "github.com/go-rod/rod/lib/proto" "github.com/go-rod/rod/lib/utils" + "github.com/ysmood/gson" ) -// Element implements these interfaces +// Element implements these interfaces. var ( _ proto.Client = &Element{} _ proto.Contextable = &Element{} _ proto.Sessionable = &Element{} ) -// Element represents the DOM element +// Element represents the DOM element. type Element struct { Object *proto.RuntimeRemoteObject @@ -37,17 +36,17 @@ type Element struct { page *Page } -// GetSessionID interface +// GetSessionID interface. func (el *Element) GetSessionID() proto.TargetSessionID { return el.page.SessionID } -// String interface +// String interface. func (el *Element) String() string { return fmt.Sprintf("<%s>", el.Object.Description) } -// Page of the element +// Page of the element. func (el *Element) Page() *Page { return el.page } @@ -89,7 +88,7 @@ func (el *Element) Hover() error { return el.page.Context(el.ctx).Mouse.MoveTo(*pt) } -// MoveMouseOut of the current element +// MoveMouseOut of the current element. func (el *Element) MoveMouseOut() error { shape, err := el.Shape() if err != nil { @@ -143,7 +142,7 @@ func (el *Element) Tap() error { // Interactable checks if the element is interactable with cursor. // The cursor can be mouse, finger, stylus, etc. -// If not interactable err will be ErrNotInteractable, such as when covered by a modal, +// If not interactable err will be ErrNotInteractable, such as when covered by a modal,. func (el *Element) Interactable() (pt *proto.Point, err error) { noPointerEvents, err := el.Eval(`() => getComputedStyle(this).pointerEvents === 'none'`) if err != nil { @@ -151,7 +150,7 @@ func (el *Element) Interactable() (pt *proto.Point, err error) { } if noPointerEvents.Value.Bool() { - return nil, &ErrNoPointerEvents{el} + return nil, &NoPointerEventsError{el} } shape, err := el.Shape() @@ -161,7 +160,7 @@ func (el *Element) Interactable() (pt *proto.Point, err error) { pt = shape.OnePointInside() if pt == nil { - err = &ErrInvisibleShape{el} + err = &InvisibleShapeError{el} return } @@ -176,7 +175,7 @@ func (el *Element) Interactable() (pt *proto.Point, err error) { ) if err != nil { if errors.Is(err, cdp.ErrNodeNotFoundAtPos) { - err = &ErrInvisibleShape{el} + err = &InvisibleShapeError{el} } return } @@ -187,7 +186,7 @@ func (el *Element) Interactable() (pt *proto.Point, err error) { } if !isParent { - err = &ErrCovered{elAtPoint} + err = &CoveredError{elAtPoint} } return } @@ -352,12 +351,12 @@ func (el *Element) Select(selectors []string, selected bool, t SelectorType) err return err } if !res.Value.Bool() { - return &ErrElementNotFound{} + return &ElementNotFoundError{} } return nil } -// Matches checks if the element can be selected by the css selector +// Matches checks if the element can be selected by the css selector. func (el *Element) Matches(selector string) (bool, error) { res, err := el.Eval(`s => this.matches(s)`, selector) if err != nil { @@ -367,7 +366,8 @@ func (el *Element) Matches(selector string) (bool, error) { } // Attribute of the DOM object. -// Attribute vs Property: https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html +// Attribute vs Property: +// https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html func (el *Element) Attribute(name string) (*string, error) { attr, err := el.Eval("(n) => this.getAttribute(n)", name) if err != nil { @@ -375,7 +375,7 @@ func (el *Element) Attribute(name string) (*string, error) { } if attr.Value.Nil() { - return nil, nil + return nil, nil //nolint: nilnil } s := attr.Value.Str() @@ -383,7 +383,8 @@ func (el *Element) Attribute(name string) (*string, error) { } // Property of the DOM object. -// Property vs Attribute: https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html +// Property vs Attribute: +// https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html func (el *Element) Property(name string) (gson.JSON, error) { prop, err := el.Eval("(n) => this[n]", name) if err != nil { @@ -402,7 +403,7 @@ func (el *Element) Disabled() (bool, error) { return prop.Bool(), nil } -// SetFiles of the current file input element +// SetFiles of the current file input element. func (el *Element) SetFiles(paths []string) error { absPaths := utils.AbsolutePaths(paths) @@ -420,7 +421,8 @@ func (el *Element) SetFiles(paths []string) error { // Describe the current element. The depth is the maximum depth at which children should be retrieved, defaults to 1, // use -1 for the entire subtree or provide an integer larger than 0. // The pierce decides whether or not iframes and shadow roots should be traversed when returning the subtree. -// The returned [proto.DOMNode.NodeID] will always be empty, because NodeID is not stable (when [proto.DOMDocumentUpdated] +// The returned [proto.DOMNode.NodeID] will always be empty, +// because NodeID is not stable (when [proto.DOMDocumentUpdated] // is fired all NodeID on the page will be reassigned to another value) // we don't recommend using the NodeID, instead, use the [proto.DOMBackendNodeID] to identify the element. func (el *Element) Describe(depth int, pierce bool) (*proto.DOMNode, error) { @@ -431,7 +433,7 @@ func (el *Element) Describe(depth int, pierce bool) (*proto.DOMNode, error) { return val.Node, nil } -// ShadowRoot returns the shadow root of this element +// ShadowRoot returns the shadow root of this element. func (el *Element) ShadowRoot() (*Element, error) { node, err := el.Describe(1, false) if err != nil { @@ -440,7 +442,7 @@ func (el *Element) ShadowRoot() (*Element, error) { // though now it's an array, w3c changed the spec of it to be a single. if len(node.ShadowRoots) == 0 { - return nil, &ErrNoShadowRoot{el} + return nil, &NoShadowRootError{el} } id := node.ShadowRoots[0].BackendNodeID @@ -452,7 +454,7 @@ func (el *Element) ShadowRoot() (*Element, error) { return el.page.Context(el.ctx).ElementFromObject(shadowNode.Object) } -// Frame creates a page instance that represents the iframe +// Frame creates a page instance that represents the iframe. func (el *Element) Frame() (*Page, error) { node, err := el.Describe(1, false) if err != nil { @@ -477,7 +479,7 @@ func (el *Element) ContainsElement(target *Element) (bool, error) { return res.Value.Bool(), nil } -// Text that the element displays +// Text that the element displays. func (el *Element) Text() (string, error) { str, err := el.Evaluate(evalHelper(js.Text)) if err != nil { @@ -486,7 +488,7 @@ func (el *Element) Text() (string, error) { return str.Value.String(), nil } -// HTML of the element +// HTML of the element. func (el *Element) HTML() (string, error) { res, err := proto.DOMGetOuterHTML{ObjectID: el.Object.ObjectID}.Call(el) if err != nil { @@ -495,7 +497,7 @@ func (el *Element) HTML() (string, error) { return res.OuterHTML, nil } -// Visible returns true if the element is visible on the page +// Visible returns true if the element is visible on the page. func (el *Element) Visible() (bool, error) { res, err := el.Evaluate(evalHelper(js.Visible)) if err != nil { @@ -504,7 +506,7 @@ func (el *Element) Visible() (bool, error) { return res.Value.Bool(), nil } -// WaitLoad for element like +// WaitLoad for element like . func (el *Element) WaitLoad() error { defer el.tryTrace(TraceTypeWait, "load")() _, err := el.Evaluate(evalHelper(js.WaitLoad).ByPromise()) @@ -594,7 +596,7 @@ func (el *Element) WaitInteractable() (pt *proto.Point, err error) { } pt, err = el.Interactable() - if errors.Is(err, &ErrCovered{}) { + if errors.Is(err, &CoveredError{}) { return false, nil } return true, err @@ -602,12 +604,12 @@ func (el *Element) WaitInteractable() (pt *proto.Point, err error) { return } -// Wait until the js returns true +// Wait until the js returns true. func (el *Element) Wait(opts *EvalOptions) error { return el.page.Context(el.ctx).Sleeper(el.sleeper).Wait(opts.This(el.Object)) } -// WaitVisible until the element is visible +// WaitVisible until the element is visible. func (el *Element) WaitVisible() error { defer el.tryTrace(TraceTypeWait, "visible")() return el.Wait(evalHelper(js.Visible)) @@ -627,7 +629,7 @@ func (el *Element) WaitWritable() error { return el.Wait(Eval(`() => !this.readonly`)) } -// WaitInvisible until the element invisible +// WaitInvisible until the element invisible. func (el *Element) WaitInvisible() error { defer el.tryTrace(TraceTypeWait, "invisible")() return el.Wait(evalHelper(js.Invisible)) @@ -647,7 +649,7 @@ func (el *Element) CanvasToImage(format string, quality float64) ([]byte, error) return bin, nil } -// Resource returns the "src" content of current element. Such as the jpg of +// Resource returns the "src" content of current element. Such as the jpg of . func (el *Element) Resource() ([]byte, error) { src, err := el.Evaluate(evalHelper(js.Resource).ByPromise()) if err != nil { @@ -657,7 +659,7 @@ func (el *Element) Resource() ([]byte, error) { return el.page.Context(el.ctx).GetResource(src.Value.String()) } -// BackgroundImage returns the css background-image of the element +// BackgroundImage returns the css background-image of the element. func (el *Element) BackgroundImage() ([]byte, error) { res, err := el.Eval(`() => window.getComputedStyle(this).backgroundImage.replace(/^url\("/, '').replace(/"\)$/, '')`) if err != nil { @@ -669,7 +671,7 @@ func (el *Element) BackgroundImage() ([]byte, error) { return el.page.Context(el.ctx).GetResource(u) } -// Screenshot of the area of the element +// Screenshot of the area of the element. func (el *Element) Screenshot(format proto.PageCaptureScreenshotFormat, quality int) ([]byte, error) { err := el.ScrollIntoView() if err != nil { @@ -708,7 +710,7 @@ func (el *Element) Release() error { return el.page.Context(el.ctx).Release(el.Object) } -// Remove the element from the page +// Remove the element from the page. func (el *Element) Remove() error { _, err := el.Eval(`() => this.remove()`) if err != nil { @@ -717,7 +719,7 @@ func (el *Element) Remove() error { return el.Release() } -// Call implements the [proto.Client] +// Call implements the [proto.Client]. func (el *Element) Call(ctx context.Context, sessionID, methodName string, params interface{}) (res []byte, err error) { return el.page.Call(ctx, sessionID, methodName, params) } @@ -742,7 +744,7 @@ func (el *Element) id() proto.RuntimeRemoteObjectID { return el.Object.ObjectID } -// GetXPath returns the xpath of the element +// GetXPath returns the xpath of the element. func (el *Element) GetXPath(optimized bool) (string, error) { str, err := el.Evaluate(evalHelper(js.GetXPath, optimized)) if err != nil { diff --git a/element_test.go b/element_test.go index 23ce9fa5..506bbd95 100644 --- a/element_test.go +++ b/element_test.go @@ -12,14 +12,13 @@ import ( "testing" "time" - "github.com/ysmood/gson" - "github.com/go-rod/rod" "github.com/go-rod/rod/lib/cdp" "github.com/go-rod/rod/lib/devices" "github.com/go-rod/rod/lib/input" "github.com/go-rod/rod/lib/proto" "github.com/go-rod/rod/lib/utils" + "github.com/ysmood/gson" ) func TestGetElementPage(t *testing.T) { @@ -118,10 +117,10 @@ func TestNotInteractable(t *testing.T) { }`) _, err := el.Interactable() g.Has(err.Error(), "element covered by:
") - g.Is(err, &rod.ErrNotInteractable{}) - g.Is(err, &rod.ErrCovered{}) + g.Is(err, &rod.NotInteractableError{}) + g.Is(err, &rod.CoveredError{}) g.False(el.MustInteractable()) - var ee *rod.ErrNotInteractable + var ee *rod.NotInteractableError g.True(errors.As(err, &ee)) g.Eq(ee.Error(), "element is not cursor interactable") @@ -148,17 +147,17 @@ func TestInteractableWithNoShape(t *testing.T) { el := p.MustElement("#no-shape") _, err := el.Interactable() - g.Is(err, &rod.ErrInvisibleShape{}) - g.Is(err, &rod.ErrNotInteractable{}) + g.Is(err, &rod.InvisibleShapeError{}) + g.Is(err, &rod.NotInteractableError{}) g.Eq(err.Error(), "element has no visible shape or outside the viewport: ") el = p.MustElement("#outside") _, err = el.Interactable() - g.Is(err, &rod.ErrInvisibleShape{}) + g.Is(err, &rod.InvisibleShapeError{}) el = p.MustElement("#invisible") _, err = el.Interactable() - g.Is(err, &rod.ErrInvisibleShape{}) + g.Is(err, &rod.InvisibleShapeError{}) } func TestNotInteractableWithNoPointerEvents(t *testing.T) { @@ -166,8 +165,8 @@ func TestNotInteractableWithNoPointerEvents(t *testing.T) { p := g.page.MustNavigate(g.srcFile("fixtures/interactable.html")) _, err := p.MustElementR("#no-pointer-events", "click me").Interactable() - g.Is(err, &rod.ErrNoPointerEvents{}) - g.Is(err, &rod.ErrNotInteractable{}) + g.Is(err, &rod.NoPointerEventsError{}) + g.Is(err, &rod.NotInteractableError{}) g.Eq(err.Error(), "element's pointer-events is none: ") } @@ -299,7 +298,7 @@ func TestShadowDOM(t *testing.T) { elNoShadow := p.MustElement("script") _, err := elNoShadow.ShadowRoot() - g.True((&rod.ErrNoShadowRoot{}).Is(err)) + g.True((&rod.NoShadowRootError{}).Is(err)) g.Has(err.Error(), "element has no shadow root:") } @@ -478,7 +477,7 @@ func TestSelectOptions(t *testing.T) { g.Eq("", el.MustText()) // option not found error - g.Is(el.Select([]string{"not-exists"}, true, rod.SelectorTypeCSSSector), &rod.ErrElementNotFound{}) + g.Is(el.Select([]string{"not-exists"}, true, rod.SelectorTypeCSSSector), &rod.ElementNotFoundError{}) { g.mc.stubErr(5, proto.RuntimeCallFunctionOn{}) @@ -700,7 +699,7 @@ func TestResource(t *testing.T) { el := p.MustElement("img") g.Eq(len(el.MustResource()), 22661) - g.mc.stub(1, proto.PageGetResourceContent{}, func(send StubSend) (gson.JSON, error) { + g.mc.stub(1, proto.PageGetResourceContent{}, func(_ StubSend) (gson.JSON, error) { return gson.New(proto.PageGetResourceContentResult{ Content: "ok", Base64Encoded: false, @@ -806,14 +805,14 @@ func TestFnErr(t *testing.T) { _, err := el.Eval("foo()") g.Err(err) g.Has(err.Error(), "ReferenceError: foo is not defined") - var e *rod.ErrEval + var e *rod.EvalError g.True(errors.As(err, &e)) g.Eq(proto.RuntimeRemoteObjectSubtypeError, e.Exception.Subtype) _, err = el.ElementByJS(rod.Eval("() => foo()")) g.Err(err) g.Has(err.Error(), "ReferenceError: foo is not defined") - g.True(errors.Is(err, &rod.ErrEval{})) + g.True(errors.Is(err, &rod.EvalError{})) } func TestElementEWithDepth(t *testing.T) { diff --git a/error.go b/error.go index 87decdb8..c6a43c06 100644 --- a/error.go +++ b/error.go @@ -8,186 +8,186 @@ import ( "github.com/go-rod/rod/lib/utils" ) -// ErrTry error -type ErrTry struct { +// TryError error. +type TryError struct { Value interface{} Stack string } -func (e *ErrTry) Error() string { +func (e *TryError) Error() string { return fmt.Sprintf("error value: %#v\n%s", e.Value, e.Stack) } -// Is interface -func (e *ErrTry) Is(err error) bool { _, ok := err.(*ErrTry); return ok } +// Is interface. +func (e *TryError) Is(err error) bool { _, ok := err.(*TryError); return ok } -// Unwrap stdlib interface -func (e *ErrTry) Unwrap() error { +// Unwrap stdlib interface. +func (e *TryError) Unwrap() error { if err, ok := e.Value.(error); ok { return err } return fmt.Errorf("%v", e.Value) } -// ErrExpectElement error -type ErrExpectElement struct { +// ExpectElementError error. +type ExpectElementError struct { *proto.RuntimeRemoteObject } -func (e *ErrExpectElement) Error() string { +func (e *ExpectElementError) Error() string { return fmt.Sprintf("expect js to return an element, but got: %s", utils.MustToJSON(e)) } -// Is interface -func (e *ErrExpectElement) Is(err error) bool { _, ok := err.(*ErrExpectElement); return ok } +// Is interface. +func (e *ExpectElementError) Is(err error) bool { _, ok := err.(*ExpectElementError); return ok } -// ErrExpectElements error -type ErrExpectElements struct { +// ExpectElementsError error. +type ExpectElementsError struct { *proto.RuntimeRemoteObject } -func (e *ErrExpectElements) Error() string { +func (e *ExpectElementsError) Error() string { return fmt.Sprintf("expect js to return an array of elements, but got: %s", utils.MustToJSON(e)) } -// Is interface -func (e *ErrExpectElements) Is(err error) bool { _, ok := err.(*ErrExpectElements); return ok } +// Is interface. +func (e *ExpectElementsError) Is(err error) bool { _, ok := err.(*ExpectElementsError); return ok } -// ErrElementNotFound error -type ErrElementNotFound struct{} +// ElementNotFoundError error. +type ElementNotFoundError struct{} -func (e *ErrElementNotFound) Error() string { +func (e *ElementNotFoundError) Error() string { return "cannot find element" } -// NotFoundSleeper returns ErrElementNotFound on the first call +// NotFoundSleeper returns ErrElementNotFound on the first call. func NotFoundSleeper() utils.Sleeper { return func(context.Context) error { - return &ErrElementNotFound{} + return &ElementNotFoundError{} } } -// ErrObjectNotFound error -type ErrObjectNotFound struct { +// ObjectNotFoundError error. +type ObjectNotFoundError struct { *proto.RuntimeRemoteObject } -func (e *ErrObjectNotFound) Error() string { +func (e *ObjectNotFoundError) Error() string { return fmt.Sprintf("cannot find object: %s", utils.MustToJSON(e)) } -// Is interface -func (e *ErrObjectNotFound) Is(err error) bool { _, ok := err.(*ErrObjectNotFound); return ok } +// Is interface. +func (e *ObjectNotFoundError) Is(err error) bool { _, ok := err.(*ObjectNotFoundError); return ok } -// ErrEval error -type ErrEval struct { +// EvalError error. +type EvalError struct { *proto.RuntimeExceptionDetails } -func (e *ErrEval) Error() string { +func (e *EvalError) Error() string { exp := e.Exception return fmt.Sprintf("eval js error: %s %s", exp.Description, exp.Value) } -// Is interface -func (e *ErrEval) Is(err error) bool { _, ok := err.(*ErrEval); return ok } +// Is interface. +func (e *EvalError) Is(err error) bool { _, ok := err.(*EvalError); return ok } -// ErrNavigation error -type ErrNavigation struct { +// NavigationError error. +type NavigationError struct { Reason string } -func (e *ErrNavigation) Error() string { +func (e *NavigationError) Error() string { return "navigation failed: " + e.Reason } -// Is interface -func (e *ErrNavigation) Is(err error) bool { _, ok := err.(*ErrNavigation); return ok } +// Is interface. +func (e *NavigationError) Is(err error) bool { _, ok := err.(*NavigationError); return ok } -// ErrPageCloseCanceled error -type ErrPageCloseCanceled struct{} +// PageCloseCanceledError error. +type PageCloseCanceledError struct{} -func (e *ErrPageCloseCanceled) Error() string { +func (e *PageCloseCanceledError) Error() string { return "page close canceled" } -// ErrNotInteractable error. Check the doc of Element.Interactable for details. -type ErrNotInteractable struct{} +// NotInteractableError error. Check the doc of Element.Interactable for details. +type NotInteractableError struct{} -func (e *ErrNotInteractable) Error() string { +func (e *NotInteractableError) Error() string { return "element is not cursor interactable" } -// ErrInvisibleShape error. -type ErrInvisibleShape struct { +// InvisibleShapeError error. +type InvisibleShapeError struct { *Element } // Error ... -func (e *ErrInvisibleShape) Error() string { +func (e *InvisibleShapeError) Error() string { return fmt.Sprintf("element has no visible shape or outside the viewport: %s", e.String()) } -// Is interface -func (e *ErrInvisibleShape) Is(err error) bool { _, ok := err.(*ErrInvisibleShape); return ok } +// Is interface. +func (e *InvisibleShapeError) Is(err error) bool { _, ok := err.(*InvisibleShapeError); return ok } // Unwrap ... -func (e *ErrInvisibleShape) Unwrap() error { - return &ErrNotInteractable{} +func (e *InvisibleShapeError) Unwrap() error { + return &NotInteractableError{} } -// ErrCovered error. -type ErrCovered struct { +// CoveredError error. +type CoveredError struct { *Element } // Error ... -func (e *ErrCovered) Error() string { +func (e *CoveredError) Error() string { return fmt.Sprintf("element covered by: %s", e.String()) } // Unwrap ... -func (e *ErrCovered) Unwrap() error { - return &ErrNotInteractable{} +func (e *CoveredError) Unwrap() error { + return &NotInteractableError{} } -// Is interface -func (e *ErrCovered) Is(err error) bool { _, ok := err.(*ErrCovered); return ok } +// Is interface. +func (e *CoveredError) Is(err error) bool { _, ok := err.(*CoveredError); return ok } -// ErrNoPointerEvents error. -type ErrNoPointerEvents struct { +// NoPointerEventsError error. +type NoPointerEventsError struct { *Element } // Error ... -func (e *ErrNoPointerEvents) Error() string { +func (e *NoPointerEventsError) Error() string { return fmt.Sprintf("element's pointer-events is none: %s", e.String()) } // Unwrap ... -func (e *ErrNoPointerEvents) Unwrap() error { - return &ErrNotInteractable{} +func (e *NoPointerEventsError) Unwrap() error { + return &NotInteractableError{} } -// Is interface -func (e *ErrNoPointerEvents) Is(err error) bool { _, ok := err.(*ErrNoPointerEvents); return ok } +// Is interface. +func (e *NoPointerEventsError) Is(err error) bool { _, ok := err.(*NoPointerEventsError); return ok } -// ErrPageNotFound error -type ErrPageNotFound struct{} +// PageNotFoundError error. +type PageNotFoundError struct{} -func (e *ErrPageNotFound) Error() string { +func (e *PageNotFoundError) Error() string { return "cannot find page" } -// ErrNoShadowRoot error -type ErrNoShadowRoot struct { +// NoShadowRootError error. +type NoShadowRootError struct { *Element } // Error ... -func (e *ErrNoShadowRoot) Error() string { +func (e *NoShadowRootError) Error() string { return fmt.Sprintf("element has no shadow root: %s", e.String()) } -// Is interface -func (e *ErrNoShadowRoot) Is(err error) bool { _, ok := err.(*ErrNoShadowRoot); return ok } +// Is interface. +func (e *NoShadowRootError) Is(err error) bool { _, ok := err.(*NoShadowRootError); return ok } diff --git a/examples_test.go b/examples_test.go index 1fe553e3..85956fa1 100644 --- a/examples_test.go +++ b/examples_test.go @@ -158,7 +158,7 @@ func Example_context_and_EachEvent() { }() // It's a blocking method, it will wait until the context is cancelled - page.EachEvent(func(e *proto.PageLifecycleEvent) {})() + page.EachEvent(func(_ *proto.PageLifecycleEvent) {})() if page.GetContext().Err() == context.Canceled { fmt.Println("cancelled") @@ -173,7 +173,7 @@ func Example_error_handling() { // We use Go's standard way to check error types, no magic. check := func(err error) { - var evalErr *rod.ErrEval + var evalErr *rod.EvalError if errors.Is(err, context.DeadlineExceeded) { // timeout error fmt.Println("timeout err") } else if errors.As(err, &evalErr) { // eval error @@ -370,7 +370,7 @@ func Example_customize_retry_strategy() { // If sleeper is nil page.ElementE will query without retrying. // If nothing found it will return an error. el, err := page.Sleeper(rod.NotFoundSleeper).Element("input") - if errors.Is(err, &rod.ErrElementNotFound{}) { + if errors.Is(err, &rod.ElementNotFoundError{}) { fmt.Println("element not found") } else if err != nil { panic(err) @@ -454,7 +454,7 @@ func Example_handle_events() { if false { // Subscribe events before they happen, run the "wait()" to start consuming // the events. We can return an optional stop signal to unsubscribe events. - wait := page.EachEvent(func(e *proto.PageLoadEventFired) (stop bool) { + wait := page.EachEvent(func(_ *proto.PageLoadEventFired) (stop bool) { return true }) page.MustNavigate("https://mdn.dev") @@ -532,7 +532,7 @@ func Example_hijack_requests() { // Output: done } -// Shows how to share a remote object reference between two Eval +// Shows how to share a remote object reference between two Eval. func Example_eval_reuse_remote_object() { page := rod.New().MustConnect().MustPage() diff --git a/hijack.go b/hijack.go index 829dc64b..bfb68c9c 100644 --- a/hijack.go +++ b/hijack.go @@ -31,7 +31,7 @@ func (p *Page) HijackRequests() *HijackRouter { return newHijackRouter(p.browser, p).initEvents() } -// HijackRouter context +// HijackRouter context. type HijackRouter struct { run func() stop func() @@ -50,7 +50,7 @@ func newHijackRouter(browser *Browser, client proto.Client) *HijackRouter { } } -func (r *HijackRouter) initEvents() *HijackRouter { +func (r *HijackRouter) initEvents() *HijackRouter { //nolint: gocognit ctx := r.browser.ctx if cta, ok := r.client.(proto.Contextable); ok { ctx = cta.GetContext() @@ -128,7 +128,7 @@ func (r *HijackRouter) Add(pattern string, resourceType proto.NetworkResourceTyp return r.enable.Call(r.client) } -// Remove handler via the pattern +// Remove handler via the pattern. func (r *HijackRouter) Remove(pattern string) error { patterns := []*proto.FetchRequestPattern{} handlers := []*hijackHandler{} @@ -144,7 +144,7 @@ func (r *HijackRouter) Remove(pattern string) error { return r.enable.Call(r.client) } -// new context +// new context. func (r *HijackRouter) new(ctx context.Context, e *proto.FetchRequestPaused) *Hijack { headers := http.Header{} for k, v := range e.Request.Headers { @@ -174,7 +174,7 @@ func (r *HijackRouter) new(ctx context.Context, e *proto.FetchRequestPaused) *Hi RequestID: e.RequestID, }, }, - OnError: func(err error) {}, + OnError: func(_ error) {}, browser: r.browser, } @@ -185,20 +185,20 @@ func (r *HijackRouter) Run() { r.run() } -// Stop the router +// Stop the router. func (r *HijackRouter) Stop() error { r.stop() return proto.FetchDisable{}.Call(r.client) } -// hijackHandler to handle each request that match the regexp +// hijackHandler to handle each request that match the regexp. type hijackHandler struct { pattern string regexp *regexp.Regexp handler func(*Hijack) } -// Hijack context +// Hijack context. type Hijack struct { Request *HijackRequest Response *HijackResponse @@ -249,34 +249,34 @@ func (h *Hijack) LoadResponse(client *http.Client, loadBody bool) error { return nil } -// HijackRequest context +// HijackRequest context. type HijackRequest struct { event *proto.FetchRequestPaused req *http.Request } -// Type of the resource +// Type of the resource. func (ctx *HijackRequest) Type() proto.NetworkResourceType { return ctx.event.ResourceType } -// Method of the request +// Method of the request. func (ctx *HijackRequest) Method() string { return ctx.event.Request.Method } -// URL of the request +// URL of the request. func (ctx *HijackRequest) URL() *url.URL { u, _ := url.Parse(ctx.event.Request.URL) return u } -// Header via a key +// Header via a key. func (ctx *HijackRequest) Header(key string) string { return ctx.event.Request.Headers[key].String() } -// Headers of request +// Headers of request. func (ctx *HijackRequest) Headers() proto.NetworkHeaders { return ctx.event.Request.Headers } @@ -286,7 +286,7 @@ func (ctx *HijackRequest) Body() string { return ctx.event.Request.PostData } -// JSONBody of the request +// JSONBody of the request. func (ctx *HijackRequest) JSONBody() gson.JSON { return gson.NewFrom(ctx.Body()) } @@ -296,7 +296,7 @@ func (ctx *HijackRequest) Req() *http.Request { return ctx.req } -// SetContext of the underlying http.Request instance +// SetContext of the underlying http.Request instance. func (ctx *HijackRequest) SetContext(c context.Context) *HijackRequest { ctx.req = ctx.req.WithContext(c) return ctx @@ -320,12 +320,12 @@ func (ctx *HijackRequest) SetBody(obj interface{}) *HijackRequest { return ctx } -// IsNavigation determines whether the request is a navigation request +// IsNavigation determines whether the request is a navigation request. func (ctx *HijackRequest) IsNavigation() bool { return ctx.Type() == proto.NetworkResourceTypeDocument } -// HijackResponse context +// HijackResponse context. type HijackResponse struct { payload *proto.FetchFulfillRequest RawResponse *http.Response @@ -337,7 +337,7 @@ func (ctx *HijackResponse) Payload() *proto.FetchFulfillRequest { return ctx.payload } -// Body of the payload +// Body of the payload. func (ctx *HijackResponse) Body() string { return string(ctx.payload.Body) } @@ -354,7 +354,7 @@ func (ctx *HijackResponse) Headers() http.Header { return header } -// SetHeader of the payload via key-value pairs +// SetHeader of the payload via key-value pairs. func (ctx *HijackResponse) SetHeader(pairs ...string) *HijackResponse { for i := 0; i < len(pairs); i += 2 { ctx.payload.ResponseHeaders = append(ctx.payload.ResponseHeaders, &proto.FetchHeaderEntry{ @@ -378,7 +378,7 @@ func (ctx *HijackResponse) SetBody(obj interface{}) *HijackResponse { return ctx } -// Fail request +// Fail request. func (ctx *HijackResponse) Fail(reason proto.NetworkErrorReason) *HijackResponse { ctx.fail.ErrorReason = reason return ctx diff --git a/hijack_test.go b/hijack_test.go index f9f6ae2c..7b207d24 100644 --- a/hijack_test.go +++ b/hijack_test.go @@ -87,7 +87,7 @@ func TestHijack(t *testing.T) { g.Eq("{\"text\":\"test\"}", ctx.Response.Body()) }) - router.MustAdd(s.URL("/b"), func(ctx *rod.Hijack) { + router.MustAdd(s.URL("/b"), func(_ *rod.Hijack) { panic("should not come to here") }) router.MustRemove(s.URL("/b")) @@ -157,7 +157,7 @@ func TestHijackMockWholeResponseNoBody(t *testing.T) { defer router.MustStop() // intercept and reply without setting a body - router.MustAdd("*", func(ctx *rod.Hijack) { + router.MustAdd("*", func(_ *rod.Hijack) { // we don't set any body here }) @@ -234,7 +234,7 @@ func TestHijackOnErrorLog(t *testing.T) { go router.Run() - g.mc.stub(1, proto.FetchContinueRequest{}, func(send StubSend) (gson.JSON, error) { + g.mc.stub(1, proto.FetchContinueRequest{}, func(_ StubSend) (gson.JSON, error) { return gson.New(nil), errors.New("err") }) @@ -296,7 +296,7 @@ func TestHijackLoadResponseErr(t *testing.T) { g.Err(ctx.LoadResponse(&http.Client{ Transport: &MockRoundTripper{res: &http.Response{ - StatusCode: 200, + StatusCode: http.StatusOK, Body: ioutil.NopCloser(&MockReader{err: errors.New("err")}), }}, }, true)) @@ -355,7 +355,7 @@ func TestHandleAuth(t *testing.T) { u, p, ok := r.BasicAuth() if !ok { w.Header().Add("WWW-Authenticate", `Basic realm="web"`) - w.WriteHeader(401) + w.WriteHeader(http.StatusUnauthorized) return } diff --git a/input.go b/input.go index e2871bff..c7d3f9fb 100644 --- a/input.go +++ b/input.go @@ -10,7 +10,7 @@ import ( "github.com/ysmood/gson" ) -// Keyboard represents the keyboard on a page, it's always related the main frame +// Keyboard represents the keyboard on a page, it's always related the main frame. type Keyboard struct { sync.Mutex @@ -54,7 +54,7 @@ func (k *Keyboard) Press(key input.Key) error { return key.Encode(proto.InputDispatchKeyEventTypeKeyDown, k.modifiers()).Call(k.page) } -// Release the key +// Release the key. func (k *Keyboard) Release(key input.Key) error { defer k.page.tryTrace(TraceTypeInput, "release key: "+key.Info().Code)() @@ -70,7 +70,7 @@ func (k *Keyboard) Release(key input.Key) error { return key.Encode(proto.InputDispatchKeyEventTypeKeyUp, k.modifiers()).Call(k.page) } -// Type releases the key after the press +// Type releases the key after the press. func (k *Keyboard) Type(keys ...input.Key) (err error) { for _, key := range keys { err = k.Press(key) @@ -85,23 +85,23 @@ func (k *Keyboard) Type(keys ...input.Key) (err error) { return } -// KeyActionType enum +// KeyActionType enum. type KeyActionType int -// KeyActionTypes +// KeyActionTypes. const ( KeyActionPress KeyActionType = iota KeyActionRelease KeyActionTypeKey ) -// KeyAction to perform +// KeyAction to perform. type KeyAction struct { Type KeyActionType Key input.Key } -// KeyActions to simulate +// KeyActions to simulate. type KeyActions struct { keyboard *Keyboard @@ -114,7 +114,7 @@ func (p *Page) KeyActions() *KeyActions { return &KeyActions{keyboard: p.Keyboard} } -// Press keys is guaranteed to have a release at the end of actions +// Press keys is guaranteed to have a release at the end of actions. func (ka *KeyActions) Press(keys ...input.Key) *KeyActions { for _, key := range keys { ka.Actions = append(ka.Actions, KeyAction{KeyActionPress, key}) @@ -122,7 +122,7 @@ func (ka *KeyActions) Press(keys ...input.Key) *KeyActions { return ka } -// Release keys +// Release keys. func (ka *KeyActions) Release(keys ...input.Key) *KeyActions { for _, key := range keys { ka.Actions = append(ka.Actions, KeyAction{KeyActionRelease, key}) @@ -130,7 +130,7 @@ func (ka *KeyActions) Release(keys ...input.Key) *KeyActions { return ka } -// Type will release the key immediately after the pressing +// Type will release the key immediately after the pressing. func (ka *KeyActions) Type(keys ...input.Key) *KeyActions { for _, key := range keys { ka.Actions = append(ka.Actions, KeyAction{KeyActionTypeKey, key}) @@ -138,7 +138,7 @@ func (ka *KeyActions) Type(keys ...input.Key) *KeyActions { return ka } -// Do the actions +// Do the actions. func (ka *KeyActions) Do() (err error) { for _, a := range ka.balance() { switch a.Type { @@ -181,7 +181,7 @@ func (ka *KeyActions) balance() []KeyAction { return actions } -// InsertText is like pasting text into the page +// InsertText is like pasting text into the page. func (p *Page) InsertText(text string) error { defer p.tryTrace(TraceTypeInput, "insert text "+text)() p.browser.trySlowMotion() @@ -190,7 +190,7 @@ func (p *Page) InsertText(text string) error { return err } -// Mouse represents the mouse on a page, it's always related the main frame +// Mouse represents the mouse on a page, it's always related the main frame. type Mouse struct { sync.Mutex @@ -209,14 +209,14 @@ func (p *Page) newMouse() *Page { return p } -// Position of current cursor +// Position of current cursor. func (m *Mouse) Position() proto.Point { m.Lock() defer m.Unlock() return m.pos } -// MoveTo the absolute position +// MoveTo the absolute position. func (m *Mouse) MoveTo(p proto.Point) error { m.Lock() defer m.Unlock() @@ -285,7 +285,7 @@ func (m *Mouse) MoveLinear(to proto.Point, steps int) error { }) } -// Scroll the relative offset with specified steps +// Scroll the relative offset with specified steps. func (m *Mouse) Scroll(offsetX, offsetY float64, steps int) error { m.Lock() defer m.Unlock() @@ -321,12 +321,12 @@ func (m *Mouse) Scroll(offsetX, offsetY float64, steps int) error { return nil } -// Down holds the button down +// Down holds the button down. func (m *Mouse) Down(button proto.InputMouseButton, clickCount int) error { m.Lock() defer m.Unlock() - toButtons := append(m.buttons, button) + toButtons := append(append([]proto.InputMouseButton{}, m.buttons...), button) _, buttons := input.EncodeMouseButton(toButtons) @@ -346,7 +346,7 @@ func (m *Mouse) Down(button proto.InputMouseButton, clickCount int) error { return nil } -// Up releases the button +// Up releases the button. func (m *Mouse) Up(button proto.InputMouseButton, clickCount int) error { m.Lock() defer m.Unlock() @@ -377,7 +377,7 @@ func (m *Mouse) Up(button proto.InputMouseButton, clickCount int) error { return nil } -// Click the button. It's the combination of [Mouse.Down] and [Mouse.Up] +// Click the button. It's the combination of [Mouse.Down] and [Mouse.Up]. func (m *Mouse) Click(button proto.InputMouseButton, clickCount int) error { m.page.browser.trySlowMotion() @@ -400,7 +400,7 @@ func (p *Page) newTouch() *Page { return p } -// Start a touch action +// Start a touch action. func (t *Touch) Start(points ...*proto.InputTouchPoint) error { // TODO: https://crbug.com/613219 _ = t.page.WaitRepaint() @@ -423,7 +423,7 @@ func (t *Touch) Move(points ...*proto.InputTouchPoint) error { }.Call(t.page) } -// End touch action +// End touch action. func (t *Touch) End() error { return proto.InputDispatchTouchEvent{ Type: proto.InputDispatchTouchEventTypeTouchEnd, @@ -432,7 +432,7 @@ func (t *Touch) End() error { }.Call(t.page) } -// Cancel touch action +// Cancel touch action. func (t *Touch) Cancel() error { return proto.InputDispatchTouchEvent{ Type: proto.InputDispatchTouchEventTypeTouchCancel, diff --git a/lib/assets/assets.go b/lib/assets/assets.go index 1f8623f2..4dbb107f 100644 --- a/lib/assets/assets.go +++ b/lib/assets/assets.go @@ -1,7 +1,7 @@ // Package assets is generated by "lib/assets/generate" package assets -// MousePointer for rod +// MousePointer for rod. const MousePointer = ` @@ -26,7 +26,7 @@ const MousePointer = ` ` -// Monitor for rod +// Monitor for rod. const Monitor = ` Rod Monitor - Pages @@ -82,7 +82,7 @@ const Monitor = ` ` -// MonitorPage for rod +// MonitorPage for rod. const MonitorPage = `