diff --git a/README.md b/README.md index 7c8de86..41326b5 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,9 @@ one. implement this support](https://github.com/mozilla/geckodriver/issues/159). Then, [Selenium 3 doesn't implement this support for Firefox](https://github.com/SeleniumHQ/selenium/issues/2285). +5. [The Proxy object is + misinterpreted](https://github.com/mozilla/geckodriver/issues/490) by + Geckodriver when passed through by Selenium 3. The Geckodriver team recommends using the newest available Firefox version, as the integration is actively being developed. diff --git a/remote_test.go b/remote_test.go index 7e97362..9ff5c35 100644 --- a/remote_test.go +++ b/remote_test.go @@ -7,10 +7,12 @@ import ( "net" "net/http" "net/http/httptest" + "net/url" "os" "os/exec" "path/filepath" "reflect" + "strconv" "strings" "testing" "time" @@ -485,6 +487,7 @@ func runTests(t *testing.T, c config) { t.Run("ResizeWindow", runTest(testResizeWindow, c)) t.Run("KeyDownUp", runTest(testKeyDownUp, c)) t.Run("CSSProperty", runTest(testCSSProperty, c)) + t.Run("Proxy", runTest(testProxy, c)) } func testStatus(t *testing.T, c config) { @@ -750,7 +753,7 @@ func testFindElement(t *testing.T, c config) { we, ok := elem.(*remoteWE) if !ok { - t.Errorf("wd.FindElement(%q, %q) = %T, want a *remoteWE", tc.by, tc.query) + t.Errorf("wd.FindElement(%q, %q) = %T, want a *remoteWE", tc.by, tc.query, elem) continue } @@ -1363,6 +1366,87 @@ func testCSSProperty(t *testing.T, c config) { t.Fatalf(`e.CSSProperty("color") = %q, want one of %q`, color, wantColors) } +func testProxy(t *testing.T, c config) { + const pageContents = "You are viewing a proxied page" + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + fmt.Fprintf(w, pageContents) + })) + defer s.Close() + + u, err := url.Parse(s.URL) + if err != nil { + t.Fatalf("url.Parse(%q) returned error: %v", s.URL, err) + } + + caps := newTestCapabilities(t, c) + proxy := Proxy{Type: Manual} + switch c.browser { + case "firefox": + switch c.seleniumVersion.Major { + case 0: // Geckodriver. + host, port, err := net.SplitHostPort(u.Host) + if err != nil { + t.Fatalf("net.SplitHostPort(%q) returned error: %v", u.Host, err) + } + p, err := strconv.Atoi(port) + if err != nil { + t.Fatalf("strconv.Atoi(%q) returned error: %v", port, err) + } + proxy.HTTP = host + proxy.HTTPPort = p + case 2: + proxy.HTTP = u.Host + case 3: + // When the Proxy object is passed through Selenium 3 to GeckoDriver, it + // adds a whole bunch of "null" values for empty entities. GeckoDriver + // does not interpret this well. + // https://github.com/mozilla/geckodriver/issues/490 + t.Skip("Skipping test due to https://github.com/mozilla/geckodriver/issues/490") + } + // By default, Firefox explicitly does not use a proxy for connection to + // localhost and 127.0.0.1. Clear this preference to reach our test proxy. + ff, ok := caps[firefox.CapabilitiesKey].(firefox.Capabilities) + if ok { // Selenium 3.0.1 does not support Firefox capabilities. + if ff.Prefs == nil { + ff.Prefs = make(map[string]interface{}) + } + ff.Prefs["network.proxy.no_proxies_on"] = "" + caps[firefox.CapabilitiesKey] = ff + } + case "chrome": + proxy.HTTP = u.Host + } + caps.AddProxy(proxy) + + wd := &remoteWD{ + capabilities: caps, + urlPrefix: c.addr, + } + defer func() { + if err := wd.Quit(); err != nil { + t.Fatalf("wd.Quit() returned error: %v", err) + } + }() + if _, err := wd.NewSession(); err != nil { + t.Fatalf("wd.NewSession() returned error: %v", err) + } + + if err := wd.Get(serverURL); err != nil { + t.Fatalf("wd.Get(%q) returned error: %v", serverURL, err) + } + source, err := wd.PageSource() + if err != nil { + t.Fatalf("wd.PageSource() returned error: %v", err) + } + + if !strings.Contains(source, pageContents) { + if strings.Contains(source, "Go Selenium Test Suite") { + t.Fatal("Got non-proxied page.") + } + t.Fatalf("Got page: %s\n\nExpected: %q", source, pageContents) + } +} + var homePage = ` diff --git a/selenium.go b/selenium.go index b2a5ae4..847925b 100644 --- a/selenium.go +++ b/selenium.go @@ -104,9 +104,15 @@ func (c Capabilities) AddFirefox(f firefox.Capabilities) { c[firefox.CapabilitiesKey] = f } +// AddProxy adds proxy configuration to the capabilities. +func (c Capabilities) AddProxy(p Proxy) { + c["proxy"] = p +} + // Proxy specifies configuration for proxies in the browser. Set the key // "proxy" in Capabilities to an instance of this type. type Proxy struct { + // Type is the type of proxy to use. This is required to be populated. Type ProxyType `json:"proxyType"` // AutoconfigURL is the URL to be used for proxy auto configuration. This is @@ -114,6 +120,9 @@ type Proxy struct { AutoconfigURL string `json:"proxyAutoconfigUrl,omitempty"` // The following are used when Type is set to Manual. + // + // Note that in Firefox, connections to localhost are not proxied by default, + // even if a proxy is set. This can be overrided via a preference setting. FTP string `json:"ftpProxy,omitempty"` HTTP string `json:"httpProxy,omitempty"` SSL string `json:"sslProxy,omitempty"` @@ -122,8 +131,13 @@ type Proxy struct { SOCKSPassword string `json:"socksPassword,omitempty"` NoProxy string `json:"noProxy,omitempty"` - // TODO(minusnine): The W3C draft spec includes port fields as well. Should - // they be added here? + // The W3C draft spec includes port fields as well. According to the + // specification, ports can also be included in the above addresses. However, + // in the Geckodriver implementation, the ports must be specified by these + // additional fields. + HTTPPort int `json:"httpProxyPort,omitempty"` + SSLPort int `json:"sslProxyPort,omitempty"` + SocksPort int `json:"socksProxyPort,omitempty"` } // ProxyType is an enumeration of the types of proxies available. diff --git a/vendor/init.go b/vendor/init.go index fe59e2d..ab2262d 100644 --- a/vendor/init.go +++ b/vendor/init.go @@ -64,9 +64,9 @@ var files = []file{ }, { // This is a recent nightly. Update this path periodically. - url: "https://archive.mozilla.org/pub/firefox/nightly/2017/02/2017-02-14-11-02-12-mozilla-central/firefox-54.0a1.en-US.linux-x86_64.tar.bz2", + url: "https://archive.mozilla.org/pub/firefox/nightly/2017/02/2017-02-15-11-01-51-mozilla-central/firefox-54.0a1.en-US.linux-x86_64.tar.bz2", name: "firefox-54.0a1.en-US.linux-x86_64.tar.bz2", - hash: "df3dcecbb630ca662851160b4d619a11c3ab52a8ceb238eb00e522248a3890ee", + hash: "1d2a066308b9c31adc8fe6f9ce92e6cb503e004141b4ca8b7a50f74632ae7aed", browser: true, rename: []string{"firefox", "firefox-nightly"}, },