From 75359f121ed3fbad80d7dbf8037d3bcb6d4ff702 Mon Sep 17 00:00:00 2001 From: wq19971213 Date: Fri, 18 Jun 2021 11:38:55 +0800 Subject: [PATCH 1/4] Support execute cdp command --- internal/seleniumtest/seleniumtest.go | 22 +++++++++++++++ remote.go | 40 +++++++++++++++++++++++++++ selenium.go | 4 +++ 3 files changed, 66 insertions(+) diff --git a/internal/seleniumtest/seleniumtest.go b/internal/seleniumtest/seleniumtest.go index e225928..a53f64c 100644 --- a/internal/seleniumtest/seleniumtest.go +++ b/internal/seleniumtest/seleniumtest.go @@ -1700,7 +1700,29 @@ func testChromeExtension(t *testing.T, c Config) { } } +func testChromeCdp(t *testing.T, c Config) { + caps := newTestCapabilities(t, c) + + wd, err := NewRemote(t, caps, c.Addr) + if err != nil { + t.Fatalf("newRemote(_, _) returned error: %v", err) + } + defer wd.Quit() + + res, err := wd.ExecuteCdpCommand("Browser.getVersion", nil) + if err != nil { + t.Fatalf("cdp execute error: %s", err.Error()) + } + + if data, ok := res.(map[string]interface{}); !ok { + t.Fatalf("cdp execute failed with result: %v", res) + } else { + t.Log(data["product"]) + } +} + func RunChromeTests(t *testing.T, c Config) { // Chrome-specific tests. t.Run("Extension", runTest(testChromeExtension, c)) + t.Run("CDP", runTest(testChromeCdp, c)) } diff --git a/remote.go b/remote.go index 466d361..5099954 100644 --- a/remote.go +++ b/remote.go @@ -1148,6 +1148,46 @@ func (wd *remoteWD) execScript(script string, args []interface{}, suffix string) return reply.Value, nil } +func (wd *remoteWD) execCdpCommandRaw(data []byte) ([]byte, error) { + return wd.execute("POST", wd.requestURL("/session/%s/goog/cdp/execute", wd.id), data) +} + +// execCdpCommand execute cdp command +// this interface didn't define in official wiki(https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol) +// so I just refered to selenium in python (selenium.webdriver.chrome.remote_connection.ChromeRemoteConnection) +func (wd *remoteWD) execCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) { + if params == nil { + params = make(map[string]interface{}) + } + + data, err := json.Marshal(map[string]interface{}{ + "cmd": cmd, + "params": params, + }) + if err != nil { + return nil, err + } + + response, err := wd.execCdpCommandRaw(data) + if err != nil { + return nil, err + } + + reply := new(struct{ Value interface{} }) + if err = json.Unmarshal(response, reply); err != nil { + return nil, err + } + + return reply.Value, nil +} + +func (wd *remoteWD) ExecuteCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) { + if wd.browser != "chrome" { + return nil, fmt.Errorf("cdp command must execute in chrome not %s", wd.browser) + } + return wd.execCdpCommand(cmd, params) +} + func (wd *remoteWD) ExecuteScript(script string, args []interface{}) (interface{}, error) { if !wd.w3cCompatible { return wd.execScript(script, args, "") diff --git a/selenium.go b/selenium.go index ac9dcd6..e30e98a 100644 --- a/selenium.go +++ b/selenium.go @@ -370,6 +370,10 @@ type WebDriver interface { // perform JSON decoding. ExecuteScriptAsyncRaw(script string, args []interface{}) ([]byte, error) + // ExecuteCdpCommand execute Chrome Devtools Protocol command and get returned result + // refer to link https://chromedevtools.github.io/devtools-protocol/ + ExecuteCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) + // WaitWithTimeoutAndInterval waits for the condition to evaluate to true. WaitWithTimeoutAndInterval(condition Condition, timeout, interval time.Duration) error From c5c91e7578187d2d08f9dbedf6965ed1e7c6cfba Mon Sep 17 00:00:00 2001 From: wq19971213 Date: Fri, 18 Jun 2021 19:06:41 +0800 Subject: [PATCH 2/4] Support execute cdp command with cdproto --- go.mod | 2 + go.sum | 3 ++ internal/seleniumtest/seleniumtest.go | 26 ++++++++++++- remote.go | 55 +++++++++++++++++++++++++++ selenium.go | 4 ++ 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 80e4ad9..91dedbe 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,12 @@ require ( github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 github.com/blang/semver v3.5.1+incompatible + github.com/chromedp/cdproto v0.0.0-20200209033844-7e00b02ea7d2 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/protobuf v1.3.4 github.com/google/go-cmp v0.3.0 github.com/google/go-github/v27 v27.0.4 + github.com/mailru/easyjson v0.7.0 github.com/mediabuyerbot/go-crx3 v1.3.1 google.golang.org/api v0.7.0 ) diff --git a/go.sum b/go.sum index 28a9333..b760a43 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chromedp/cdproto v0.0.0-20200209033844-7e00b02ea7d2 h1:osPk40NN+GLEj2Tay/N+H/K4itKyHZ6gdrC/pXjjgQ8= github.com/chromedp/cdproto v0.0.0-20200209033844-7e00b02ea7d2/go.mod h1:PfAWWKJqjlGFYJEidUM6aVIWPr0EpobeyVWEEmplX7g= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -80,6 +81,7 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08 h1:V0an7KRw92wmJysvFvtqtKMAPmvS5O0jtB0nYo6t+gs= github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08/go.mod h1:dFWs1zEqDjFtnBXsd1vPOZaLsESovai349994nHx3e0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -87,6 +89,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mediabuyerbot/go-crx3 v1.3.1 h1:JG3Hlaf7FsMhTJHBt+iEO5bK1GTh/Ms/cBT2aR2kBUE= diff --git a/internal/seleniumtest/seleniumtest.go b/internal/seleniumtest/seleniumtest.go index a53f64c..4ede131 100644 --- a/internal/seleniumtest/seleniumtest.go +++ b/internal/seleniumtest/seleniumtest.go @@ -23,6 +23,7 @@ import ( socks5 "github.com/armon/go-socks5" "github.com/blang/semver" + "github.com/chromedp/cdproto/browser" "github.com/google/go-cmp/cmp" "github.com/tebeka/selenium" "github.com/tebeka/selenium/chrome" @@ -1721,8 +1722,29 @@ func testChromeCdp(t *testing.T, c Config) { } } +func testChromeCdpWithCdproto(t *testing.T, c Config) { + caps := newTestCapabilities(t, c) + + wd, err := NewRemote(t, caps, c.Addr) + if err != nil { + t.Fatalf("newRemote(_, _) returned error: %v", err) + } + defer wd.Quit() + + version := browser.GetVersion() + + _, product, _, _, _, err := version.Do(wd.GenerateCdprotoContext(context.Background())) + + if err != nil { + t.Fatalf("cdproto execute error : %s", err.Error()) + } + + t.Log(product) +} + func RunChromeTests(t *testing.T, c Config) { // Chrome-specific tests. - t.Run("Extension", runTest(testChromeExtension, c)) - t.Run("CDP", runTest(testChromeCdp, c)) + // t.Run("Extension", runTest(testChromeExtension, c)) + // t.Run("CDP", runTest(testChromeCdp, c)) + t.Run("Cdproto", runTest(testChromeCdpWithCdproto, c)) } diff --git a/remote.go b/remote.go index 5099954..e9819d8 100644 --- a/remote.go +++ b/remote.go @@ -5,6 +5,7 @@ package selenium import ( "bytes" + "context" "encoding/base64" "encoding/json" "errors" @@ -18,6 +19,8 @@ import ( "time" "github.com/blang/semver" + "github.com/chromedp/cdproto/cdp" + "github.com/mailru/easyjson" "github.com/tebeka/selenium/firefox" "github.com/tebeka/selenium/log" ) @@ -1156,6 +1159,7 @@ func (wd *remoteWD) execCdpCommandRaw(data []byte) ([]byte, error) { // this interface didn't define in official wiki(https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol) // so I just refered to selenium in python (selenium.webdriver.chrome.remote_connection.ChromeRemoteConnection) func (wd *remoteWD) execCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) { + // params can't be nil if params == nil { params = make(map[string]interface{}) } @@ -1181,6 +1185,57 @@ func (wd *remoteWD) execCdpCommand(cmd string, params map[string]interface{}) (i return reply.Value, nil } +// CdpExecutor execute cdp command with cdproto +type CdpExecutor struct { + *remoteWD +} + +// Execute refer to https://github.com/chromedp/cdproto/blob/master/cdp/types.go +func (wd CdpExecutor) Execute(ctx context.Context, cmd string, params easyjson.Marshaler, res easyjson.Unmarshaler) (err error) { + body := map[string]interface{}{"cmd": cmd} + + if params == nil { + // params can't be nil + body["params"] = make(map[string]string) + } else { + body["params"] = params + } + + data, err := json.Marshal(body) + + if err != nil { + return + } + + response, err := wd.execCdpCommandRaw(data) + if err != nil { + return + } + + reply := new(struct{ Value easyjson.Unmarshaler }) + reply.Value = res + + if err = json.Unmarshal(response, reply); err != nil { + debugLog("cdproto value :%+v", res) + return + } + + debugLog("cdproto return value is :%+v", res) + + return +} + +func (wd *remoteWD) generateCdprotoExecutor() cdp.Executor { + return CdpExecutor{wd} +} + +func (wd *remoteWD) GenerateCdprotoContext(ctx context.Context) context.Context { + if ctx == nil { + ctx = context.Background() + } + return cdp.WithExecutor(ctx, wd.generateCdprotoExecutor()) +} + func (wd *remoteWD) ExecuteCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) { if wd.browser != "chrome" { return nil, fmt.Errorf("cdp command must execute in chrome not %s", wd.browser) diff --git a/selenium.go b/selenium.go index e30e98a..27ec941 100644 --- a/selenium.go +++ b/selenium.go @@ -1,6 +1,7 @@ package selenium import ( + "context" "time" "github.com/tebeka/selenium/chrome" @@ -373,6 +374,9 @@ type WebDriver interface { // ExecuteCdpCommand execute Chrome Devtools Protocol command and get returned result // refer to link https://chromedevtools.github.io/devtools-protocol/ ExecuteCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) + // GenerateCdprotoContext execute cdp command with cdproto + // refer to https://github.com/chromedp/cdproto + GenerateCdprotoContext(ctx context.Context) context.Context // WaitWithTimeoutAndInterval waits for the condition to evaluate to true. WaitWithTimeoutAndInterval(condition Condition, timeout, interval time.Duration) error From 1b4d8a8758e57015a58fa92580201d4407bd681a Mon Sep 17 00:00:00 2001 From: wq19971213 Date: Fri, 2 Jul 2021 16:57:43 +0800 Subject: [PATCH 3/4] Correct some coding standards issues --- internal/seleniumtest/seleniumtest.go | 32 ++++++++++------ remote.go | 55 +++++++++++++++++---------- selenium.go | 13 ++++--- 3 files changed, 62 insertions(+), 38 deletions(-) diff --git a/internal/seleniumtest/seleniumtest.go b/internal/seleniumtest/seleniumtest.go index 4ede131..1cae544 100644 --- a/internal/seleniumtest/seleniumtest.go +++ b/internal/seleniumtest/seleniumtest.go @@ -1701,7 +1701,7 @@ func testChromeExtension(t *testing.T, c Config) { } } -func testChromeCdp(t *testing.T, c Config) { +func testExecuteChromeDPCommand(t *testing.T, c Config) { caps := newTestCapabilities(t, c) wd, err := NewRemote(t, caps, c.Addr) @@ -1710,19 +1710,25 @@ func testChromeCdp(t *testing.T, c Config) { } defer wd.Quit() - res, err := wd.ExecuteCdpCommand("Browser.getVersion", nil) + res, err := wd.ExecuteChromeDPCommand("Browser.getVersion", nil) if err != nil { t.Fatalf("cdp execute error: %s", err.Error()) } - if data, ok := res.(map[string]interface{}); !ok { + version, ok := res.(map[string]interface{}) + if !ok || version == nil { t.Fatalf("cdp execute failed with result: %v", res) - } else { - t.Log(data["product"]) } + + product, ok := version["product"] + if !ok { + t.Fatalf("cdp execute [Browser.getVersion] failed with result: %v", res) + } + + t.Log(product) } -func testChromeCdpWithCdproto(t *testing.T, c Config) { +func testGenerateCDProtoContext(t *testing.T, c Config) { caps := newTestCapabilities(t, c) wd, err := NewRemote(t, caps, c.Addr) @@ -1733,18 +1739,22 @@ func testChromeCdpWithCdproto(t *testing.T, c Config) { version := browser.GetVersion() - _, product, _, _, _, err := version.Do(wd.GenerateCdprotoContext(context.Background())) + _, product, _, _, _, err := version.Do(wd.GenerateCDProtoContext(context.Background())) if err != nil { t.Fatalf("cdproto execute error : %s", err.Error()) } - t.Log(product) + if strings.Index(product, "Chrome") > 0 { + t.Log(product) + } else { + t.Fatalf("invalid chrome version %s", product) + } } func RunChromeTests(t *testing.T, c Config) { // Chrome-specific tests. - // t.Run("Extension", runTest(testChromeExtension, c)) - // t.Run("CDP", runTest(testChromeCdp, c)) - t.Run("Cdproto", runTest(testChromeCdpWithCdproto, c)) + t.Run("Extension", runTest(testChromeExtension, c)) + t.Run("ExecuteChromeDPCommand", runTest(testExecuteChromeDPCommand, c)) + t.Run("GenerateCDProtoContext", runTest(testGenerateCDProtoContext, c)) } diff --git a/remote.go b/remote.go index e9819d8..05cc5ab 100644 --- a/remote.go +++ b/remote.go @@ -1151,14 +1151,14 @@ func (wd *remoteWD) execScript(script string, args []interface{}, suffix string) return reply.Value, nil } -func (wd *remoteWD) execCdpCommandRaw(data []byte) ([]byte, error) { +func (wd *remoteWD) execChromeDPCommandRaw(data []byte) ([]byte, error) { return wd.execute("POST", wd.requestURL("/session/%s/goog/cdp/execute", wd.id), data) } -// execCdpCommand execute cdp command -// this interface didn't define in official wiki(https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol) -// so I just refered to selenium in python (selenium.webdriver.chrome.remote_connection.ChromeRemoteConnection) -func (wd *remoteWD) execCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) { +// This command is not defined in the Selenium or WebDriver documentation. +// The functionality was ported from the Python Selenium driver +// (selenium.webdriver.chrome.remote_connection.ChromeRemoteConnection). +func (wd *remoteWD) execChromeDPCommand(cmd string, params map[string]interface{}) (interface{}, error) { // params can't be nil if params == nil { params = make(map[string]interface{}) @@ -1172,7 +1172,7 @@ func (wd *remoteWD) execCdpCommand(cmd string, params map[string]interface{}) (i return nil, err } - response, err := wd.execCdpCommandRaw(data) + response, err := wd.execChromeDPCommandRaw(data) if err != nil { return nil, err } @@ -1185,13 +1185,27 @@ func (wd *remoteWD) execCdpCommand(cmd string, params map[string]interface{}) (i return reply.Value, nil } -// CdpExecutor execute cdp command with cdproto -type CdpExecutor struct { +// CDProtoExecutor execute Chrome DevTools Protocol command through cdproto +type CDProtoExecutor struct { *remoteWD } -// Execute refer to https://github.com/chromedp/cdproto/blob/master/cdp/types.go -func (wd CdpExecutor) Execute(ctx context.Context, cmd string, params easyjson.Marshaler, res easyjson.Unmarshaler) (err error) { +var _ cdp.Executor = (*CDProtoExecutor)(nil) + +// Execute executes a Chrome DevTools Protocol command. +// So that CDProtoExecutor can be executor for cdproto, +// refer to https://github.com/chromedp/cdproto/blob/master/cdp/types.go +func (e CDProtoExecutor) Execute(ctx context.Context, cmd string, params easyjson.Marshaler, res easyjson.Unmarshaler) (err error) { + if e.browser != "chrome" { + return fmt.Errorf("executing a Chrome DevTools command through cdproto is only supported in Chrome, not %s", e.browser) + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + body := map[string]interface{}{"cmd": cmd} if params == nil { @@ -1202,12 +1216,11 @@ func (wd CdpExecutor) Execute(ctx context.Context, cmd string, params easyjson.M } data, err := json.Marshal(body) - if err != nil { return } - response, err := wd.execCdpCommandRaw(data) + response, err := e.execChromeDPCommandRaw(data) if err != nil { return } @@ -1216,31 +1229,31 @@ func (wd CdpExecutor) Execute(ctx context.Context, cmd string, params easyjson.M reply.Value = res if err = json.Unmarshal(response, reply); err != nil { - debugLog("cdproto value :%+v", res) + debugLog("cdproto value parse error :%+v", res) return } - debugLog("cdproto return value is :%+v", res) + debugLog("cdproto value return :%+v", res) return } -func (wd *remoteWD) generateCdprotoExecutor() cdp.Executor { - return CdpExecutor{wd} +func (wd *remoteWD) generateCDProtoExecutor() cdp.Executor { + return CDProtoExecutor{wd} } -func (wd *remoteWD) GenerateCdprotoContext(ctx context.Context) context.Context { +func (wd *remoteWD) GenerateCDProtoContext(ctx context.Context) context.Context { if ctx == nil { ctx = context.Background() } - return cdp.WithExecutor(ctx, wd.generateCdprotoExecutor()) + return cdp.WithExecutor(ctx, wd.generateCDProtoExecutor()) } -func (wd *remoteWD) ExecuteCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) { +func (wd *remoteWD) ExecuteChromeDPCommand(cmd string, params map[string]interface{}) (interface{}, error) { if wd.browser != "chrome" { - return nil, fmt.Errorf("cdp command must execute in chrome not %s", wd.browser) + return nil, fmt.Errorf("executing a Chrome DevTools command is only supported in Chrome, not %s", wd.browser) } - return wd.execCdpCommand(cmd, params) + return wd.execChromeDPCommand(cmd, params) } func (wd *remoteWD) ExecuteScript(script string, args []interface{}) (interface{}, error) { diff --git a/selenium.go b/selenium.go index 27ec941..1f29153 100644 --- a/selenium.go +++ b/selenium.go @@ -371,12 +371,13 @@ type WebDriver interface { // perform JSON decoding. ExecuteScriptAsyncRaw(script string, args []interface{}) ([]byte, error) - // ExecuteCdpCommand execute Chrome Devtools Protocol command and get returned result - // refer to link https://chromedevtools.github.io/devtools-protocol/ - ExecuteCdpCommand(cmd string, params map[string]interface{}) (interface{}, error) - // GenerateCdprotoContext execute cdp command with cdproto - // refer to https://github.com/chromedp/cdproto - GenerateCdprotoContext(ctx context.Context) context.Context + // ExecuteChromeDPCommand executes a Chrome DevTools Protocol command. + // See https://chromedevtools.github.io/devtools-protocol/ for available commands. + ExecuteChromeDPCommand(cmd string, params map[string]interface{}) (interface{}, error) + // GenerateCDProtoContext generates context with a executor + // which can execute a Chrome DevTools Protocol command through cdproto. + // See https://github.com/chromedp/cdproto for usage information. + GenerateCDProtoContext(ctx context.Context) context.Context // WaitWithTimeoutAndInterval waits for the condition to evaluate to true. WaitWithTimeoutAndInterval(condition Condition, timeout, interval time.Duration) error From 841bf7216c726edf5bdf8cd1d08d123a8b685d75 Mon Sep 17 00:00:00 2001 From: wq19971213 Date: Thu, 26 Aug 2021 15:58:30 +0800 Subject: [PATCH 4/4] modify go mod --- go.mod | 5 ++++- go.sum | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 91dedbe..43a6ca1 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/tebeka/selenium +module github.com/wanmail/selenium go 1.12 @@ -14,5 +14,8 @@ require ( github.com/google/go-github/v27 v27.0.4 github.com/mailru/easyjson v0.7.0 github.com/mediabuyerbot/go-crx3 v1.3.1 + github.com/tebeka/selenium v0.9.9 google.golang.org/api v0.7.0 ) + +replace github.com/tebeka/selenium => github.com/wanmail/selenium diff --git a/go.sum b/go.sum index b760a43..836f9fc 100644 --- a/go.sum +++ b/go.sum @@ -126,6 +126,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tebeka/selenium v0.9.9 h1:cNziB+etNgyH/7KlNI7RMC1ua5aH1+5wUlFQyzeMh+w= +github.com/tebeka/selenium v0.9.9/go.mod h1:5Fr8+pUvU6B1OiPfkdCKdXZyr5znvVkxuPd0NOdZCQc= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=