Repository: bunsenapp/go-selenium Branch: master Commit: c3562b854632 Files: 78 Total size: 182.6 KB Directory structure: gitextract_o2cobv8o/ ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── api_service.go ├── capabilities.go ├── doc.go ├── errors.go ├── errors_test.go ├── examples/ │ ├── error-handling/ │ │ └── main.go │ ├── getting-started/ │ │ └── main.go │ └── hackernews/ │ └── main.go ├── remote_driver.go ├── remote_driver_alert.go ├── remote_driver_alert_test.go ├── remote_driver_command.go ├── remote_driver_command_test.go ├── remote_driver_cookie.go ├── remote_driver_cookie_test.go ├── remote_driver_document.go ├── remote_driver_document_test.go ├── remote_driver_element.go ├── remote_driver_element_test.go ├── remote_driver_helpers.go ├── remote_driver_navigation.go ├── remote_driver_navigation_test.go ├── remote_driver_screenshot.go ├── remote_driver_screenshot_test.go ├── remote_driver_session.go ├── remote_driver_session_test.go ├── remote_driver_test.go ├── remote_element.go ├── remote_element_test.go ├── test/ │ └── integration_tests/ │ ├── alert_acceptalert_test.go │ ├── alert_alerttext_test.go │ ├── alert_dismissalert_test.go │ ├── alert_sendalerttext_test.go │ ├── command_closewindow_test.go │ ├── command_maximizewindow_test.go │ ├── command_setwindowsize_test.go │ ├── command_switchtoframe_test.go │ ├── command_switchtoparentframe_test.go │ ├── command_windowhandle_test.go │ ├── command_windowhandles_test.go │ ├── command_windowsize_test.go │ ├── cookie_addcookie_test.go │ ├── cookie_allcookies_test.go │ ├── cookie_cookie_test.go │ ├── cookie_deletecookie_test.go │ ├── document_executescript_test.go │ ├── document_pagesource_test.go │ ├── element_attribute_test.go │ ├── element_clear_test.go │ ├── element_click_test.go │ ├── element_cssclass_test.go │ ├── element_enabled_test.go │ ├── element_findelement_test.go │ ├── element_findelements_test.go │ ├── element_rectangle_test.go │ ├── element_selected_test.go │ ├── element_sendkeys_test.go │ ├── element_tagname_test.go │ ├── element_text_test.go │ ├── helpers_elementpresent_test.go │ ├── helpers_untilurlis_test.go │ ├── navigate_back_test.go │ ├── navigate_forward_test.go │ ├── navigate_go_test.go │ ├── navigate_refresh_test.go │ ├── navigate_title_test.go │ ├── screenshot_screenshot_test.go │ ├── session_create_test.go │ ├── session_delete_test.go │ ├── session_general_test.go │ ├── session_settimeout_test.go │ ├── session_status_test.go │ └── test.go └── web_driver.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof *.swp ================================================ FILE: .travis.yml ================================================ language: go go: - 1.x script: go test ./*.go -v ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) Bunsen 2016 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # go-selenium [![Build Status](https://travis-ci.org/bunsenapp/go-selenium.svg?branch=master)](https://travis-ci.org/bunsenapp/go-selenium) [![GoDoc](https://godoc.org/github.com/bunsenapp/go-selenium?status.svg)](https://godoc.org/github.com/bunsenapp/go-selenium) [![Go Report Card](https://goreportcard.com/badge/github.com/bunsenapp/go-selenium)](https://goreportcard.com/report/github.com/bunsenapp/go-selenium) ## Maintainer Required This package is no longer maintained. The author no longer writes automated tests with Selenium, and will only fix this package should there be a major security issue. If you or someone you know is interested in maintaining this package, please raise an issue and tag me (@elsyms) in it. ## Introduction Yes, yet another Selenium Web Driver library has been brought to the table. This one, however, is slightly different. * Easy to understand. * Full test coverage by unit tests and integration tests. * Excellent support; we use this in our main project so if you find an issue - it'll likely impact us! * Idiomatic, structured code with no gimmicks. * Simple errors that describe what has happened and why. ## Installation As with all Go libraries, go-selenium is easy to install. Simply run the below command: `go get github.com/bunsenapp/go-selenium` and then import the library in your project: `import "github.com/bunsenapp/go-selenium"` ## Getting started Prior to using this library you need to ensure that you have a Selenium instance running (standalone or grid is fine). If you don't know how to do this, there is a small section called 'Getting Selenium running' below. Please see the [examples/getting-started/main.go](https://github.com/bunsenapp/go-selenium/blob/master/examples/getting-started/main.go) file. ## Examples Further examples, including tests of HackerNews (c), are available within the `examples` directory. ## Documentation All documentation is available on the godoc.org website: [https://godoc.org/github.com/bunsenapp/go-selenium](https://godoc.org/github.com/bunsenapp/go-selenium). ## Getting Selenium running ### With Docker 1. Choose an image from the following URL: https://github.com/SeleniumHQ/docker-selenium 2. Execute the following Docker command replacing the image with your chosen one: `docker run -d -p 4444:4444 --name selenium selenium/standalone-firefox`. ### Without Docker 1. Download the Selenium standalone server from the following URL: http://www.seleniumhq.org/download/ 2. Download the appropriate web driver executable and include it in your path. For Firefox, that will be the Gecko driver. 3. Run the Selenium server with the following command: `java -jar selenium-server-standalone-3.0.1.jar`. ================================================ FILE: api_service.go ================================================ package goselenium import ( "bytes" "encoding/json" "fmt" "io" "net/http" "errors" ) type apiServicer interface { performRequest(string, string, io.Reader) ([]byte, error) } type requestError struct { State string `json:"state"` Value requestErrorValue `json:"value"` } func (r requestError) Error() string { return fmt.Sprintf("Invalid status code returned, message: %v, information: %v", r.State, r.Value.Message) } type requestErrorValue struct { Message string `json:"localizedMessage"` } type seleniumAPIService struct{} func (a seleniumAPIService) performRequest(url string, method string, body io.Reader) ([]byte, error) { request, err := http.NewRequest(method, url, body) if err != nil { return nil, err } client := http.Client{} resp, err := client.Do(request) if err != nil { return nil, fmt.Errorf("%s: an unexpected communication failure occurred, error: %s", method, err.Error()) } defer resp.Body.Close() var buf bytes.Buffer buf.ReadFrom(resp.Body) r := buf.Bytes() if resp.StatusCode != 200 { var reqErr requestError var errStr string err := json.Unmarshal(r, &reqErr) if err == nil { return nil, &reqErr } errStr = fmt.Sprintf("Status code %v returned with no body", resp.StatusCode) return nil, errors.New(errStr) } return r, nil } ================================================ FILE: capabilities.go ================================================ package goselenium import "encoding/json" // Browser defines a supported selenium enabled browser. type Browser interface { BrowserName() string } // Browser represents a browser to run within Selenium. type browser struct { browserName string } // BrowserName returns the browser name assigned to the current browser object. func (b browser) BrowserName() string { return b.browserName } // FirefoxBrowser returns a Firefox browser object. func FirefoxBrowser() Browser { return browser{"firefox"} } // ChromeBrowser returns a Chrome browser object. func ChromeBrowser() Browser { return browser{"chrome"} } // AndroidBrowser returns an Android browser object. func AndroidBrowser() Browser { return browser{"android"} } // HTMLUnitBrowser returns a HTMLUnit browser object. func HTMLUnitBrowser() Browser { return browser{"htmlunit"} } // InternetExplorerBrowser returns an IE browser object. func InternetExplorerBrowser() Browser { return browser{"internetexplorer"} } // IPhoneBrowser returns an IPhone browser object. func IPhoneBrowser() Browser { return browser{"iphone"} } // IPadBrowser returns an IPad browser object. func IPadBrowser() Browser { return browser{"ipad"} } // OperaBrowser returns an Opera browser object. func OperaBrowser() Browser { return browser{"opera"} } // SafariBrowser returns a Safari browser object. func SafariBrowser() Browser { return browser{"safari"} } // Capabilities represents the capabilities defined in the W3C specification. // The main capability is the browser, which can be set by calling one of the // \wBrowser\(\) methods. type Capabilities struct { browser Browser } // Browser yields the browser capability assigned to the current Capabilities // object.. func (c *Capabilities) Browser() Browser { if c.browser != nil { return c.browser } return browser{} } // SetBrowser sets the browser capability to be one of the allowed browsers. func (c *Capabilities) SetBrowser(b Browser) { c.browser = b } func (c *Capabilities) toJSON() (string, error) { capabilities := map[string]map[string]interface{}{ "desiredCapabilities": { "browserName": c.browser.BrowserName(), }, } capabilitiesJSON, err := json.Marshal(capabilities) if err != nil { return "", err } return string(capabilitiesJSON), nil } ================================================ FILE: doc.go ================================================ // Package goselenium is a Selenium web driver library written in Go. package goselenium ================================================ FILE: errors.go ================================================ package goselenium import "fmt" // ErrorResponse is what is returned from the Selenium API when an error // occurs. type ErrorResponse struct { Message string State string } // CommunicationError is the result of a communication failure between // this library and the WebDriver API. type CommunicationError struct { url string Response *ErrorResponse method string } // Error returns a formatted communication error string. func (c CommunicationError) Error() string { return fmt.Sprintf("%s: api error, url: %s, err: %+v", c.method, c.url, c.Response) } // IsCommunicationError checks whether an error is a selenium communication // error. func IsCommunicationError(err error) bool { _, ok := err.(CommunicationError) return ok } func newCommunicationError(err error, method string, url string, resp []byte) CommunicationError { var convertedResponse ErrorResponse reqErr, ok := err.(*requestError) if ok { convertedResponse = ErrorResponse{ Message: reqErr.Value.Message, State: reqErr.State, } } return CommunicationError{ url: url, Response: &convertedResponse, method: method, } } // UnmarshallingError is the result of an unmarshalling failure of a JSON // string. type UnmarshallingError struct { err error json string method string } // Error returns a formatted unmarshalling error string. func (u UnmarshallingError) Error() string { return fmt.Sprintf("%s: unmarshalling error, json: %s, err: %s", u.method, u.json, u.err) } // IsUnmarshallingError checks whether an error is a selenium unmarshalling // error. func IsUnmarshallingError(err error) bool { _, ok := err.(UnmarshallingError) return ok } func newUnmarshallingError(err error, method string, json string) UnmarshallingError { return UnmarshallingError{ err: err, json: json, method: method, } } // MarshallingError is an error that is returned when a json.Marshal error occurs. type MarshallingError struct { err error object interface{} method string } // Error returns a formatted marshalling error string. func (m MarshallingError) Error() string { return fmt.Sprintf("%s: marshalling error for object %+v, err: %s", m.method, m.object, m.err.Error()) } // IsMarshallingError checks whether an error is a marshalling error. func IsMarshallingError(err error) bool { _, ok := err.(MarshallingError) return ok } func newMarshallingError(err error, method string, obj interface{}) MarshallingError { return MarshallingError{ err: err, object: obj, method: method, } } // SessionIDError is an error that is returned when the session id is // invalid. This value will contain the method that the session error occurred // in. type SessionIDError string // Error returns a formatted session error string. func (s SessionIDError) Error() string { return fmt.Sprintf("%s: session id is invalid (have you created a session yet?)", string(s)) } // IsSessionIDError checks whether an error is due to a session ID not being // set. func IsSessionIDError(err error) bool { _, ok := err.(SessionIDError) return ok } func newSessionIDError(method string) SessionIDError { return SessionIDError(method) } // InvalidURLError is an error that is returned whenever a URL is not correctly // formatted. type InvalidURLError string // Error returns the formatted invalid error string. func (i InvalidURLError) Error() string { return fmt.Sprintf("invalid url: %s", string(i)) } // IsInvalidURLError checks whether an error is due to the URL being incorrectly // formatted. func IsInvalidURLError(err error) bool { _, ok := err.(InvalidURLError) return ok } // InvalidURLError func newInvalidURLError(url string) InvalidURLError { return InvalidURLError(url) } ================================================ FILE: errors_test.go ================================================ package goselenium import ( "errors" "testing" ) func communicationError() error { return newCommunicationError(errors.New(":<"), "Test", "", nil) } func sessionError() error { return newSessionIDError("Test") } func unmarshallingError() error { return newUnmarshallingError(errors.New(":<"), "Test", "") } func marshallingError() error { return newMarshallingError(errors.New(":<"), "Test", "test") } func Test_Errors_CommunicationErrorCanBeCastSuccessfully(t *testing.T) { e := communicationError() back, ok := e.(CommunicationError) if !ok || back.method != "Test" { t.Errorf("Could not assert error") } } func Test_Errors_SessionErrorCanBeCastSuccessfully(t *testing.T) { e := sessionError() _, ok := e.(SessionIDError) if !ok { t.Errorf("Could not assert error") } } func Test_Errors_UnmarshallingErrorCanBeCastSuccessfully(t *testing.T) { e := unmarshallingError() body, ok := e.(UnmarshallingError) if !ok || body.method != "Test" { t.Errorf("Could not assert error") } } func Test_Errors_MarshallingErrorCanBeCastSuccessfully(t *testing.T) { e := marshallingError() body, ok := e.(MarshallingError) if !ok || body.method != "Test" { t.Errorf("Could not assert error") } } ================================================ FILE: examples/error-handling/main.go ================================================ package main import ( "fmt" goselenium "github.com/bunsenapp/go-selenium" ) func main() { // Create the capabilities. capabilities := goselenium.Capabilities{} capabilities.SetBrowser(goselenium.FirefoxBrowser()) // Create the driver. driver, err := goselenium.NewSeleniumWebDriver("http://localhost:4444/wd/hub/", capabilities) if err != nil { fmt.Println("Error creating web driver.") return } // Create the session. _, err = driver.CreateSession() if err != nil { fmt.Println("Error creating session.") return } // Navigate to Google. _, err = driver.Go("https://www.google.com") if err != nil { fmt.Println("An error occurred whilst visiting URL.") return } // Find a non existent element for it to error. _, err = driver.FindElement(goselenium.ByCSSSelector("mynonexistentelement")) if err != nil { // Switch the different types of errors. You do not need to do this in // every call and can simply abstract it behind a function. If you // don't want to handle the custom errors, they all implement the // Error interface meaning it'll work anywhere your normal errors do. switch err.(type) { case goselenium.CommunicationError: e := err.(goselenium.CommunicationError) // Switch the different states that we want to handle. switch e.Response.State { case goselenium.UnknownError: fmt.Println("An unknown error occurred.") case goselenium.SessionNotCreated: fmt.Println("The session was not created.") case goselenium.NoSuchElement: fmt.Println("Failed to find element. Example passed!") } case goselenium.UnmarshallingError: fmt.Println("An unmarshalling error occurred :<") } } // Delete the session. driver.DeleteSession() } ================================================ FILE: examples/getting-started/main.go ================================================ package main import ( "fmt" "github.com/bunsenapp/go-selenium" ) func main() { // Create a capabilities object. capabilities := goselenium.Capabilities{} // Populate it with the browser you wish to use. capabilities.SetBrowser(goselenium.FirefoxBrowser()) // Initialise a new web driver. driver, err := goselenium.NewSeleniumWebDriver("http://localhost:4444/wd/hub", capabilities) if err != nil { fmt.Println(err) return } // Create a session. _, err = driver.CreateSession() if err != nil { fmt.Println(err) return } // Defer the deletion of the session. defer driver.DeleteSession() // Navigate to Google. _, err = driver.Go("https://www.google.com") if err != nil { fmt.Println(err) } // Hooray, we navigated to Google! fmt.Println("Successfully navigated to Google!") } ================================================ FILE: examples/hackernews/main.go ================================================ package main import ( "fmt" "time" goselenium "github.com/bunsenapp/go-selenium" ) func main() { // Create capabilities, driver etc. capabilities := goselenium.Capabilities{} capabilities.SetBrowser(goselenium.FirefoxBrowser()) driver, err := goselenium.NewSeleniumWebDriver("http://localhost:4444/wd/hub", capabilities) if err != nil { fmt.Println(err) return } _, err = driver.CreateSession() if err != nil { fmt.Println(err) return } // Delete the session once this function is completed. defer driver.DeleteSession() // Navigate to the HackerNews website. _, err = driver.Go("https://news.ycombinator.com") if err != nil { fmt.Println(err) return } // Click the 'new' link at the top el, err := driver.FindElement(goselenium.ByCSSSelector("a[href='newest']")) if err != nil { fmt.Println(err) return } // Click the link. _, err = el.Click() if err != nil { fmt.Println(err) return } // Wait until the URL has changed with a timeout of 1 second and a check // interval of 10ms.. newLink := "https://news.ycombinator.com/newest" ok := driver.Wait(goselenium.UntilURLIs(newLink), 1*time.Second, 10*time.Millisecond) if !ok { fmt.Println("Wait timed out :<") return } // Woohoo! We have successfully navigated to a page. fmt.Println("Successfully navigated to URL " + newLink) } ================================================ FILE: remote_driver.go ================================================ package goselenium import ( "bytes" "encoding/json" "io" "strings" "errors" ) // NewSeleniumWebDriver creates a new instance of a Selenium web driver with a // service URL (usually http://domain:port/wd/hub) and a Capabilities object. // This method will return validation errors if the Selenium URL is invalid or // the required capabilities (BrowserName) are not set. func NewSeleniumWebDriver(serviceURL string, capabilities Capabilities) (WebDriver, error) { if serviceURL == "" { return nil, errors.New("Provided Selenium URL is invalid") } urlValid := strings.HasPrefix(serviceURL, "http://") || strings.HasPrefix(serviceURL, "https://") if !urlValid { return nil, errors.New("Provided Selenium URL is invalid.") } browser := capabilities.Browser() hasBrowserCapability := browser.BrowserName() != "" if !hasBrowserCapability { return nil, errors.New("An invalid capabilities object was provided.") } if strings.HasSuffix(serviceURL, "/") { serviceURL = strings.TrimSuffix(serviceURL, "/") } driver := &seleniumWebDriver{ seleniumURL: serviceURL, capabilities: &capabilities, apiService: &seleniumAPIService{}, } return driver, nil } // SessionScriptTimeout creates an appropriate Timeout implementation for the // script timeout. func SessionScriptTimeout(to int) Timeout { return timeout{ timeoutType: "script", timeout: to, } } // SessionPageLoadTimeout creates an appropriate Timeout implementation for the // page load timeout. func SessionPageLoadTimeout(to int) Timeout { return timeout{ timeoutType: "page load", timeout: to, } } // SessionImplicitWaitTimeout creates an appropriate timeout implementation for the // session implicit wait timeout. func SessionImplicitWaitTimeout(to int) Timeout { return timeout{ timeoutType: "implicit", timeout: to, } } // ByIndex accepts an integer that represents what the index of an element is // and returns the appropriate By implementation. func ByIndex(index uint) By { return by{ t: "index", value: index, } } // ByCSSSelector accepts a CSS selector (i.e. ul#id > a) for use in the // FindElement(s) functions. func ByCSSSelector(selector string) By { return by{ t: "css selector", value: selector, } } // ByLinkText is used to find an anchor element by its innerText. func ByLinkText(text string) By { return by{ t: "link text", value: text, } } // ByPartialLinkText works the same way as ByLinkText but performs a search // where the link text contains the string passed in instead of a full match. func ByPartialLinkText(text string) By { return by{ t: "partial link text", value: text, } } // ByXPath utilises the xpath to find elements (see http://www.guru99.com/xpath-selenium.html). func ByXPath(path string) By { return by{ t: "xpath", value: path, } } type seleniumWebDriver struct { seleniumURL string sessionID string capabilities *Capabilities apiService apiServicer } func (s *seleniumWebDriver) DriverURL() string { return s.seleniumURL } func (s *seleniumWebDriver) stateRequest(req *request) (*stateResponse, error) { var response stateResponse var err error resp, err := s.apiService.performRequest(req.url, req.method, req.body) if err != nil { return nil, newCommunicationError(err, req.callingMethod, req.url, resp) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, req.callingMethod, string(resp)) } return &response, nil } func (s *seleniumWebDriver) valueRequest(req *request) (*valueResponse, error) { var response valueResponse var err error resp, err := s.apiService.performRequest(req.url, req.method, req.body) if err != nil { return nil, newCommunicationError(err, req.callingMethod, req.url, resp) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, req.callingMethod, string(resp)) } return &response, nil } func (s *seleniumWebDriver) elementRequest(req *elRequest) ([]byte, error) { b := map[string]interface{}{ "using": req.by.Type(), "value": req.by.Value(), } bJSON, err := json.Marshal(b) if err != nil { return nil, newMarshallingError(err, req.callingMethod, bJSON) } body := bytes.NewReader(bJSON) resp, err := s.apiService.performRequest(req.url, req.method, body) if err != nil { return nil, newCommunicationError(err, req.callingMethod, req.url, resp) } return resp, nil } func (s *seleniumWebDriver) scriptRequest(script string, url string, method string) (*ExecuteScriptResponse, error) { r := map[string]interface{}{ "script": script, "args": []string{""}, } b, err := json.Marshal(r) if err != nil { return nil, newMarshallingError(err, method, r) } body := bytes.NewReader(b) resp, err := s.valueRequest(&request{ url: url, method: "POST", body: body, callingMethod: method, }) if err != nil { return nil, err } return &ExecuteScriptResponse{State: resp.State, Response: resp.Value}, nil } type timeout struct { timeoutType string timeout int } func (t timeout) Type() string { return t.timeoutType } func (t timeout) Timeout() int { return t.timeout } type request struct { url string method string body io.Reader callingMethod string } type elRequest struct { url string by By method string callingMethod string } type stateResponse struct { State string `json:"state"` } type valueResponse struct { State string `json:"state"` Value string `json:"value"` } type by struct { t string value interface{} } func (b by) Type() string { return b.t } func (b by) Value() interface{} { return b.value } ================================================ FILE: remote_driver_alert.go ================================================ package goselenium import ( "bytes" "encoding/json" "fmt" ) // DismissAlertResponse is the response returned from calling the DismissAlert // method. type DismissAlertResponse struct { State string } // AcceptAlertResponse is the response returned from calling the AcceptAlert // method. type AcceptAlertResponse struct { State string } // AlertTextResponse is the response returned from calling the AlertText // method. type AlertTextResponse struct { State string Text string } // SendAlertTextResponse is the response returned from calling the // SendAlertText method. type SendAlertTextResponse struct { State string } func (s *seleniumWebDriver) DismissAlert() (*DismissAlertResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("DismissAlert") } var err error url := fmt.Sprintf("%s/session/%s/alert/dismiss", s.seleniumURL, s.sessionID) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "DismissAlert", }) if err != nil { return nil, err } return &DismissAlertResponse{State: resp.State}, nil } func (s *seleniumWebDriver) AcceptAlert() (*AcceptAlertResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("AcceptAlert") } var err error url := fmt.Sprintf("%s/session/%s/alert/accept", s.seleniumURL, s.sessionID) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "AcceptAlert", }) if err != nil { return nil, err } return &AcceptAlertResponse{State: resp.State}, nil } func (s *seleniumWebDriver) AlertText() (*AlertTextResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("AlertTextResponse") } var err error url := fmt.Sprintf("%s/session/%s/alert/text", s.seleniumURL, s.sessionID) resp, err := s.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "AlertText", }) if err != nil { return nil, err } return &AlertTextResponse{State: resp.State, Text: resp.Value}, nil } func (s *seleniumWebDriver) SendAlertText(text string) (*SendAlertTextResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("SendAlertText") } var err error url := fmt.Sprintf("%s/session/%s/alert/text", s.seleniumURL, s.sessionID) b := map[string]string{ "text": text, } json, err := json.Marshal(b) if err != nil { return nil, newMarshallingError(err, "SendAlertText", b) } body := bytes.NewReader(json) resp, err := s.valueRequest(&request{ url: url, method: "POST", body: body, callingMethod: "SendAlertText", }) if err != nil { return nil, err } return &SendAlertTextResponse{State: resp.State}, nil } ================================================ FILE: remote_driver_alert_test.go ================================================ package goselenium import ( "errors" "testing" ) /* DismissAlert() Tests */ func Test_AlertDismissAlert_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.DismissAlert() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_AlertDismissAlert_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.DismissAlert() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_AlertDismissAlert_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.DismissAlert() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_AlertDismissAlert_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "8" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.DismissAlert() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* AcceptAlert() Tests */ func Test_AlertAcceptAlert_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.AcceptAlert() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_AlertAcceptAlert_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AcceptAlert() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_AlertAcceptAlert_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AcceptAlert() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_AlertAcceptAlert_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "8" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.AcceptAlert() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* AlertText() Tests */ func Test_AlertAlertText_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.AlertText() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_AlertAlertText_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AlertText() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_AlertAlertText_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AlertText() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_AlertAlertText_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "this is text" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.AlertText() if err != nil || resp.State != "success" || resp.Text != "this is text" { t.Errorf(correctResponseErrorText) } } /* SendAlertText() Tests */ func Test_AlertSendAlertText_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.SendAlertText("test") if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_AlertSendAlertText_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.SendAlertText("test") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_AlertSendAlertText_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.SendAlertText("test") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_AlertSendAlertText_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.SendAlertText("test") if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } ================================================ FILE: remote_driver_command.go ================================================ package goselenium import ( "bytes" "encoding/json" "errors" "fmt" ) // WindowHandleResponse is the response returned from the WindowHandle() method. // The handle is the current active window. Should you switch windows, // any value returned prior to that call will be invalid. type WindowHandleResponse struct { State string Handle string } // CloseWindowResponse is the response returned from the CloseWindow() method. // As per the W3C specification, it yields all of the available window handles // minus the active one that closes as a result of the CloseWindow() call. type CloseWindowResponse struct { State string `json:"state"` Handles []string `json:"value"` } // SwitchToWindowResponse is the response returned from the SwitchToWindow() // method. You can verify that this result is correct by calling the // WindowHandle() method. The two should match. type SwitchToWindowResponse struct { } // WindowHandlesResponse is the response returned from the WindowHandles() // method. This is essentially an array of available window handlers that // aren't necessarily active. type WindowHandlesResponse struct { State string `json:"state"` Handles []string `json:"value"` } // SwitchToFrameResponse is the response returned from the SwitchToFrame() // method. For now, according to the specification, it only returns a state. type SwitchToFrameResponse struct { State string } // SwitchToParentFrameResponse represents the response from attempting to // switch the top level browsing context to the parent of the current top level // browsing context. type SwitchToParentFrameResponse struct { State string } // WindowSizeResponse is the response returned from calling the WindowSize // method. The definitions are in CSS pixels. type WindowSizeResponse struct { State string `json:"state"` Dimensions Dimensions `json:"value"` } // Dimensions is a type that is both returned and accept by functions. It is // usually only used for the window size components. type Dimensions struct { Width uint `json:"width"` Height uint `json:"height"` } // SetWindowSizeResponse is the response that is returned from setting the // window size of the current top level browsing context. type SetWindowSizeResponse struct { State string } // MaximizeWindowResponse is the response that is returned from increasing the // browser to match the viewport. type MaximizeWindowResponse struct { State string } func (s *seleniumWebDriver) WindowHandle() (*WindowHandleResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("WindowHandle") } var response WindowHandleResponse var err error url := fmt.Sprintf("%s/session/%s/window", s.seleniumURL, s.sessionID) resp, err := s.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "WindowHandle", }) if err != nil { return nil, err } response = WindowHandleResponse{ State: resp.State, Handle: resp.Value, } return &response, nil } func (s *seleniumWebDriver) CloseWindow() (*CloseWindowResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("CloseWindow") } var response CloseWindowResponse var err error url := fmt.Sprintf("%s/session/%s/window", s.seleniumURL, s.sessionID) resp, err := s.apiService.performRequest(url, "DELETE", nil) if err != nil { return nil, newCommunicationError(err, "CloseWindow", url, resp) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "CloseWindow", string(resp)) } return &response, nil } func (s *seleniumWebDriver) SwitchToWindow(handle string) (*SwitchToWindowResponse, error) { return nil, nil } func (s *seleniumWebDriver) WindowHandles() (*WindowHandlesResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("WindowHandles") } var response WindowHandlesResponse var err error url := fmt.Sprintf("%s/session/%s/window/handles", s.seleniumURL, s.sessionID) resp, err := s.apiService.performRequest(url, "GET", nil) if err != nil { return nil, newCommunicationError(err, "WindowHandles", url, resp) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "WindowHandles", string(resp)) } return &response, nil } func (s *seleniumWebDriver) SwitchToFrame(by By) (*SwitchToFrameResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("SwitchToFrame") } if by == nil || (by.Type() != "index") { return nil, errors.New("switchtoframe: invalid by argument") } var err error url := fmt.Sprintf("%s/session/%s/frame", s.seleniumURL, s.sessionID) params := map[string]interface{}{ "id": by.Value(), } requestJSON, err := json.Marshal(params) if err != nil { return nil, newMarshallingError(err, "SwitchToFrame", params) } body := bytes.NewReader(requestJSON) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: body, callingMethod: "SwitchToFrame", }) if err != nil { return nil, err } return &SwitchToFrameResponse{State: resp.State}, nil } func (s *seleniumWebDriver) SwitchToParentFrame() (*SwitchToParentFrameResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("SwitchToParentFrame") } var err error url := fmt.Sprintf("%s/session/%s/frame/parent", s.seleniumURL, s.sessionID) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "SwitchToParentFrame", }) if err != nil { return nil, err } return &SwitchToParentFrameResponse{State: resp.State}, nil } func (s *seleniumWebDriver) WindowSize() (*WindowSizeResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("WindowSize") } var response WindowSizeResponse var err error url := fmt.Sprintf("%s/session/%s/window/size", s.seleniumURL, s.sessionID) resp, err := s.apiService.performRequest(url, "GET", nil) if err != nil { return nil, newCommunicationError(err, "WindowSize", url, nil) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "WindowSize", string(resp)) } return &response, nil } func (s *seleniumWebDriver) SetWindowSize(dimension *Dimensions) (*SetWindowSizeResponse, error) { if dimension == nil { return nil, errors.New("setwindowsize: invalid dimension argument") } else if len(s.sessionID) == 0 { return nil, newSessionIDError("SetWindowSize") } var err error url := fmt.Sprintf("%s/session/%s/window/size", s.seleniumURL, s.sessionID) body := map[string]uint{ "width": dimension.Width, "height": dimension.Height, } json, err := json.Marshal(body) if err != nil { return nil, newMarshallingError(err, "SetWindowSize", body) } jsonBytes := bytes.NewReader(json) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: jsonBytes, callingMethod: "SetWindowSize", }) if err != nil { return nil, err } return &SetWindowSizeResponse{State: resp.State}, nil } func (s *seleniumWebDriver) MaximizeWindow() (*MaximizeWindowResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("MaximizeWindow") } var err error url := fmt.Sprintf("%s/session/%s/window/maximize", s.seleniumURL, s.sessionID) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "MaximizeWindow", }) if err != nil { return nil, err } return &MaximizeWindowResponse{State: resp.State}, nil } ================================================ FILE: remote_driver_command_test.go ================================================ package goselenium import ( "errors" "testing" ) /* WindowHandle() Tests */ func Test_CommandWindowHandle_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.WindowHandle() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandWindowHandle_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.WindowHandle() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandWindowHandle_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.WindowHandle() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandWindowHandle_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "8" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.WindowHandle() if err != nil || resp.State != "success" || resp.Handle != "8" { t.Errorf(correctResponseErrorText) } } /* CloseWindow() Tests */ func Test_CommandCloseWindow_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.CloseWindow() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandCloseWindow_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.CloseWindow() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandCloseWindow_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.CloseWindow() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } /* SwitchToWindow() Tests */ /* WindowHandles() Tests */ func Test_CommandWindowHandles_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.WindowHandles() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandWindowHandles_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.WindowHandles() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandWindowHandles_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.WindowHandles() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandWindowHandles_SingleResultCanBeReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": [ "8" ] }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.WindowHandles() if err != nil || resp.State != "success" || resp.Handles[0] != "8" { t.Errorf(correctResponseErrorText) } } func Test_CommandWindowHandles_MultipleResultsCanBeReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": [ "8", "9" ] }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.WindowHandles() if err != nil || resp.State != "success" || resp.Handles[0] != "8" || resp.Handles[1] != "9" { t.Errorf(correctResponseErrorText) } } /* SwitchToFrame Tests */ func Test_CommandSwitchToFrame_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.SwitchToFrame(nil) if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandSwitchToFrame_InvalidByResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" invalidBys := []By{ nil, ByCSSSelector("test"), } for _, i := range invalidBys { _, err := d.SwitchToFrame(i) if err == nil { t.Errorf(argumentErrorText) } } } func Test_CommandSwitchToFrame_APICommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.SwitchToFrame(ByIndex(1)) if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandSwitchToFrame_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.SwitchToFrame(ByIndex(32)) if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* SwitchToParentFrame tests */ func Test_CommandSwitchToParentFrame_InvalidSessionIDResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.SwitchToFrame(nil) if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandSwitchToParentFrame_ApiCommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.SwitchToParentFrame() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandSwitchToParentFrame_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.SwitchToParentFrame() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandSwitchToParentFrame_CorrectResponseCanBeReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.SwitchToParentFrame() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* WindowSize tests */ func Test_CommandWindowSize_InvalidSessionIDResultsInAnError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.WindowSize() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandWindowSize_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.WindowSize() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandWindowSize_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.WindowSize() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandWindowSize_CorrectResultIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": { "width": 800, "height": 600 } }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.WindowSize() if err != nil || resp.State != "success" || resp.Dimensions.Width == 0 || resp.Dimensions.Height == 0 { t.Errorf(correctResponseErrorText) } } /* SetWindowSize tests */ func Test_CommandSetWindowSize_NullDimensionResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.SetWindowSize(nil) if err == nil { t.Errorf(argumentErrorText) } } func Test_CommandSetWindowSize_InvalidSessionIDResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) dimensions := &Dimensions{ Width: 830, Height: 255, } _, err := d.SetWindowSize(dimensions) if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandSetWindowSize_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" dimensions := &Dimensions{ Width: 830, Height: 255, } _, err := d.SetWindowSize(dimensions) if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandSetWindowSize_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" dimensions := &Dimensions{ Width: 830, Height: 255, } _, err := d.SetWindowSize(dimensions) if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandSetWindowSize_ResultIsReturnedSuccessfully(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" dimensions := &Dimensions{ Width: 830, Height: 255, } resp, err := d.SetWindowSize(dimensions) if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* MaximizeWindow tests */ func Test_CommandMaximizeWindow_InvalidSessionIDResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.MaximizeWindow() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandMaximizeWindow_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.MaximizeWindow() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandMaximizeWindow_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.MaximizeWindow() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandMaximizeWindow_ResultIsReturnedSuccessfully(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.MaximizeWindow() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } ================================================ FILE: remote_driver_cookie.go ================================================ package goselenium import ( "bytes" "encoding/json" "fmt" ) // AllCookiesResponse is the response returned from the AllCookies method. type AllCookiesResponse struct { State string `json:"state"` Cookies []Cookie `json:"value"` } // CookieResponse is the response returned from the Cookie method. type CookieResponse struct { State string `json:"state"` Cookie Cookie `json:"value"` } // Cookie represents a browser cookie. type Cookie struct { Name string `json:"name"` Value string `json:"value"` Path string `json:"path"` Domain string `json:"domain"` SecureOnly bool `json:"secure"` HTTPOnly bool `json:"httpOnly"` } // AddCookieResponse is the result returned from calling the AddCookie method. type AddCookieResponse struct { State string } // DeleteCookieResponse is the result returned from calling the DeleteCookie // method. type DeleteCookieResponse struct { State string } func (s *seleniumWebDriver) AllCookies() (*AllCookiesResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("AllCookies") } var response AllCookiesResponse var err error url := fmt.Sprintf("%s/session/%s/cookie", s.seleniumURL, s.sessionID) resp, err := s.apiService.performRequest(url, "GET", nil) if err != nil { return nil, newCommunicationError(err, "AllCookies", url, nil) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "AllCookies", string(resp)) } return &response, nil } func (s *seleniumWebDriver) Cookie(name string) (*CookieResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("Cookie") } var response CookieResponse var err error url := fmt.Sprintf("%s/session/%s/cookie/%s", s.seleniumURL, s.sessionID, name) resp, err := s.apiService.performRequest(url, "GET", nil) if err != nil { return nil, newCommunicationError(err, "Cookie", url, nil) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "Cookie", string(resp)) } return &response, nil } func (s *seleniumWebDriver) AddCookie(c *Cookie) (*AddCookieResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("AddCookie") } var err error url := fmt.Sprintf("%s/session/%s/cookie", s.seleniumURL, s.sessionID) j := map[string]Cookie{ "cookie": *c, } b, err := json.Marshal(j) if err != nil { return nil, newMarshallingError(err, "AddCookie", c) } body := bytes.NewReader(b) resp, err := s.stateRequest(&request{ url: url, body: body, method: "POST", callingMethod: "AddCookie", }) if err != nil { return nil, err } return &AddCookieResponse{State: resp.State}, nil } func (s *seleniumWebDriver) DeleteCookie(name string) (*DeleteCookieResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("DeleteCookie") } var err error url := fmt.Sprintf("%s/session/%s/cookie/%s", s.seleniumURL, s.sessionID, name) resp, err := s.stateRequest(&request{ url: url, body: nil, method: "DELETE", callingMethod: "DeleteCookie", }) if err != nil { return nil, err } return &DeleteCookieResponse{State: resp.State}, nil } ================================================ FILE: remote_driver_cookie_test.go ================================================ package goselenium import ( "errors" "testing" ) /* AllCookies tests */ func Test_CookieAllCookies_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.AllCookies() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CookieAllCookies_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AllCookies() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CookieAllCookies_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AllCookies() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CookieAllCookies_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": [ { "name": "Test Cookie", "value": "Test Value", "path": "/", "domain": "www.google.com", "secure": true, "httpOnly": true, "expiry": "2016-12-25T00:00:00Z" } ] }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.AllCookies() if err != nil || resp.State != "success" || resp.Cookies[0].Name != "Test Cookie" || resp.Cookies[0].Value != "Test Value" || resp.Cookies[0].Path != "/" || resp.Cookies[0].Domain != "www.google.com" || !resp.Cookies[0].SecureOnly || !resp.Cookies[0].HTTPOnly { t.Errorf(correctResponseErrorText) } } /* Cookie tests */ func Test_CookieCookie_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.Cookie("test") if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CookieCookie_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Cookie("test") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CookieCookie_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Cookie("test") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CookieCookie_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": { "name": "Test Cookie", "value": "Test Value", "path": "/", "domain": "www.google.com", "secure": true, "httpOnly": true, "expiry": "2016-12-25T00:00:00Z" } }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Cookie("test") if err != nil || resp.State != "success" || resp.Cookie.Name != "Test Cookie" || resp.Cookie.Value != "Test Value" || resp.Cookie.Path != "/" || resp.Cookie.Domain != "www.google.com" || !resp.Cookie.SecureOnly || !resp.Cookie.HTTPOnly { t.Errorf(correctResponseErrorText) } } /* AddCookie tests */ func Test_CookieAddCookie_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.AddCookie(nil) if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CookieAddCookie_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AddCookie(&Cookie{Name: "cookie", Path: "/"}) if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CookieAddCookie_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.AddCookie(&Cookie{Name: "cookie", Path: "/"}) if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CookieAddCookie_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.AddCookie(&Cookie{Name: "cookie", Path: "/"}) if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* DeleteCookie tests */ func Test_CookieDeleteCookie_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.DeleteCookie("") if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CookieDeleteCookie_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.DeleteCookie("") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CookieDeleteCookie_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.DeleteCookie("") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CookieDeleteCookie_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.DeleteCookie("") if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } ================================================ FILE: remote_driver_document.go ================================================ package goselenium import "fmt" // PageSourceResponse is the response returned from calling the PageSource // method. type PageSourceResponse struct { State string Source string } // ExecuteScriptResponse is the response returned from calling the ExecuteScript // method. type ExecuteScriptResponse struct { State string Response string } func (s *seleniumWebDriver) PageSource() (*PageSourceResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("PageSource") } var err error url := fmt.Sprintf("%s/session/%s/source", s.seleniumURL, s.sessionID) resp, err := s.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "PageSource", }) if err != nil { return nil, err } return &PageSourceResponse{State: resp.State, Source: resp.Value}, nil } func (s *seleniumWebDriver) ExecuteScript(script string) (*ExecuteScriptResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("ExecuteScript") } url := fmt.Sprintf("%s/session/%s/execute", s.seleniumURL, s.sessionID) return s.scriptRequest(script, url, "ExecuteScript") } func (s *seleniumWebDriver) ExecuteScriptAsync(script string) (*ExecuteScriptResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("ExecuteScriptAsync") } url := fmt.Sprintf("%s/session/%s/execute_async", s.seleniumURL, s.sessionID) return s.scriptRequest(script, url, "ExecuteScriptAsync") } ================================================ FILE: remote_driver_document_test.go ================================================ package goselenium import ( "errors" "testing" ) /* PageSource tests */ func Test_DocumentPageSource_InvalidSessionIDResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.PageSource() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_DocumentPageSource_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.PageSource() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_DocumentPageSource_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.PageSource() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_DocumentPageSource_ResultIsReturnedSuccessfully(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "this would be HTML" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.PageSource() if err != nil || resp.State != "success" || resp.Source != "this would be HTML" { t.Errorf(correctResponseErrorText) } } /* ExecuteScript tests */ func Test_CommandExecuteScript_InvalidSessionIDResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.ExecuteScript("alert('test');") if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandExecuteScript_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.ExecuteScript("alert('test');") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandExecuteScript_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.ExecuteScript("alert('test');") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandExecuteScript_ResultIsReturnedSuccessfully(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "test" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.ExecuteScript("alert('test');") if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* ExecuteScriptAsync tests */ func Test_CommandExecuteScriptAsync_InvalidSessionIDResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.ExecuteScriptAsync("alert('test');") if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_CommandExecuteScriptAsync_CommunicationErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.ExecuteScriptAsync("alert('test');") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_CommandExecuteScriptAsync_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.ExecuteScriptAsync("alert('test');") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_CommandExecuteScriptAsync_ResultIsReturnedSuccessfully(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "test" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.ExecuteScriptAsync("alert('test');") if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } ================================================ FILE: remote_driver_element.go ================================================ package goselenium import ( "encoding/json" "errors" "fmt" ) type findElementResponse struct { E element `json:"value"` } type findElementsResponse struct { E []element `json:"value"` } type element struct { ID string `json:"element"` } func (s *seleniumWebDriver) FindElement(by By) (Element, error) { if by.Type() == "index" { return nil, errors.New("findelement: invalid by argument") } if len(s.sessionID) == 0 { return nil, newSessionIDError("FindElement") } var response findElementResponse var err error url := fmt.Sprintf("%s/session/%s/element", s.seleniumURL, s.sessionID) resp, err := s.elementRequest(&elRequest{ url: url, by: by, method: "POST", callingMethod: "FindElement", }) if err != nil { return nil, err } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "FindElement", string(resp)) } el := newSeleniumElement(response.E.ID, s) return el, nil } func (s *seleniumWebDriver) FindElements(by By) ([]Element, error) { if by.Type() == "index" { return nil, errors.New("findelements: invalid by argument") } if len(s.sessionID) == 0 { return nil, newSessionIDError("FindElements") } var response findElementsResponse var err error url := fmt.Sprintf("%s/session/%s/elements", s.seleniumURL, s.sessionID) resp, err := s.elementRequest(&elRequest{ url: url, by: by, method: "POST", callingMethod: "FindElements", }) if err != nil { return nil, err } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "FindElements", string(resp)) } elements := make([]Element, len(response.E)) for i := range response.E { elements[i] = newSeleniumElement(response.E[i].ID, s) } return elements, nil } ================================================ FILE: remote_driver_element_test.go ================================================ package goselenium import ( "errors" "testing" ) /* FIND ELEMENT TESTS */ func Test_ElementFindElement_ByIndexResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.FindElement(ByIndex(32)) if err == nil { t.Errorf(sessionIDErrorText) } } func Test_ElementFindElement_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.FindElement(ByCSSSelector("test")) if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_ElementFindElement_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.FindElement(ByCSSSelector("iframe > ul")) if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementFindElement_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.FindElement(ByCSSSelector("iframe > ul")) if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementFindElement_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": { "ELEMENT": "0" } }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.FindElement(ByCSSSelector("iframe > ul")) if err != nil || resp.ID() != "0" { t.Errorf(correctResponseErrorText) } } /* FIND ELEMENTS TESTS */ func Test_ElementFindElements_ByIndexResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.FindElements(ByIndex(32)) if err == nil { t.Errorf(sessionIDErrorText) } } func Test_ElementFindElements_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.FindElements(ByCSSSelector("test")) if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_ElementFindElements_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.FindElements(ByCSSSelector("iframe > ul")) if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementFindElements_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.FindElements(ByCSSSelector("iframe > ul")) if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementFindElements_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": [ {"ELEMENT": "0"}, {"ELEMENT": "1"} ] }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.FindElements(ByCSSSelector("iframe > ul")) if err != nil || len(resp) <= 1 || resp[1].ID() != "1" { t.Errorf(correctResponseErrorText) } } ================================================ FILE: remote_driver_helpers.go ================================================ package goselenium import "time" // Until represents a function that will be continuously repeated until it // succeeds or a timeout is reached. type Until func(w WebDriver) bool // UntilElementPresent attempts to locate an element on the page. It is // determined as existing if the state is 'Success' and the error is nil. func UntilElementPresent(by By) Until { return func(w WebDriver) bool { _, err := w.FindElement(by) return err == nil } } // UntilURLIs checks whether or not the page's URL has changed. func UntilURLIs(url string) Until { return func(w WebDriver) bool { resp, err := w.CurrentURL() return err == nil && resp.URL == url } } func (s *seleniumWebDriver) Wait(u Until, timeout time.Duration, sleep time.Duration) bool { response := make(chan bool, 1) quit := make(chan bool, 1) go func() { outer: for { select { case <-quit: break outer default: e := u(s) if e { response <- true break outer } } time.Sleep(sleep) } }() select { case r := <-response: return r case <-time.After(timeout): close(quit) return false } } ================================================ FILE: remote_driver_navigation.go ================================================ package goselenium import ( "bytes" "encoding/json" "fmt" "strings" ) // GoResponse is the response returned from the selenium web driver when calling // the Go() call. Unfortunately, the W3C specification defines that the response // should only be whether the call succeeded or not. Should there be any redirects // they will not be catered for in this response. Should you expect any redirects // to happen, call the CurrentURL() method. type GoResponse struct { State string } // CurrentURLResponse is the response returned from the GET Url call. type CurrentURLResponse struct { State string URL string } // BackResponse is the response returned from the Back call. type BackResponse struct { State string } // ForwardResponse is the response returned from the Forward call. type ForwardResponse struct { State string } // RefreshResponse is the response returned from the Refresh call. type RefreshResponse struct { State string } // TitleResponse is the response returned from the Title call. type TitleResponse struct { State string Title string } func (s *seleniumWebDriver) Go(goURL string) (*GoResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("Go") } var err error url := fmt.Sprintf("%s/session/%s/url", s.seleniumURL, s.sessionID) invalidURL := goURL == "" validProtocol := strings.HasPrefix(goURL, "https://") || strings.HasPrefix(goURL, "http://") if invalidURL || !validProtocol { return nil, newInvalidURLError(goURL) } params := map[string]string{ "url": goURL, } marshalledJSON, err := json.Marshal(params) if err != nil { return nil, newMarshallingError(err, "Go", params) } bodyReader := bytes.NewReader([]byte(marshalledJSON)) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: bodyReader, callingMethod: "Go", }) if err != nil { return nil, err } return &GoResponse{State: resp.State}, nil } func (s *seleniumWebDriver) CurrentURL() (*CurrentURLResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("CurrentURL") } var response CurrentURLResponse var err error url := fmt.Sprintf("%s/session/%s/url", s.seleniumURL, s.sessionID) resp, err := s.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "CurrentURL", }) if err != nil { return nil, err } response = CurrentURLResponse{ State: resp.State, URL: resp.Value, } return &response, nil } func (s *seleniumWebDriver) Back() (*BackResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("Back") } var err error url := fmt.Sprintf("%s/session/%s/back", s.seleniumURL, s.sessionID) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "Back", }) if err != nil { return nil, err } return &BackResponse{State: resp.State}, nil } func (s *seleniumWebDriver) Forward() (*ForwardResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("Forward") } var err error url := fmt.Sprintf("%s/session/%s/forward", s.seleniumURL, s.sessionID) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "Forward", }) if err != nil { return nil, err } return &ForwardResponse{State: resp.State}, nil } func (s *seleniumWebDriver) Refresh() (*RefreshResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("Refresh") } var err error url := fmt.Sprintf("%s/session/%s/refresh", s.seleniumURL, s.sessionID) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "Refresh", }) if err != nil { return nil, err } return &RefreshResponse{State: resp.State}, nil } func (s *seleniumWebDriver) Title() (*TitleResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("Title") } var response TitleResponse var err error url := fmt.Sprintf("%s/session/%s/title", s.seleniumURL, s.sessionID) resp, err := s.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "Title", }) if err != nil { return nil, err } response = TitleResponse{ State: resp.State, Title: resp.Value, } return &response, nil } ================================================ FILE: remote_driver_navigation_test.go ================================================ package goselenium import ( "errors" "testing" ) /* Navigation Go Tests */ func Test_NavigateGo_NoSessionIdCausesError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.Go("http://google.com") if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_NavigateGo_InvalidURLFormatResultsInError(t *testing.T) { invalidURLs := []string{ "", "google.com", "htt://google.com", "://google.com", "/\\", } for _, i := range invalidURLs { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Go(i) if err == nil || !IsInvalidURLError(err) { t.Errorf("URL error was not returned") } } } func Test_NavigateGo_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error! :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Go("https://www.google.com") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_NavigateGo_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Go("https://www.google.com") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_NavigateGo_ResultIsUnmarshalledSuccessfully(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Go("https://www.google.com") if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* CurrentURL tests */ func Test_NavigateCurrentURL_InvalidSessionIdResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.CurrentURL() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_NavigateCurrentURL_CommunicationFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("AN error :< "), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.CurrentURL() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_NavigateCurrentURL_UnmarshallingFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.CurrentURL() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_NavigateCurrentURL_SuccessfulResultGetsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "http://google.com" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.CurrentURL() if err != nil || resp.URL != "http://google.com" || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* Back tests */ func Test_NavigateBack_InvalidSessionIdResultsInAnError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.Back() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_NavigateBack_CommunicationFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("AN error :< "), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Back() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_NavigateBack__UnmarshallingFailureResultsInAnError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Back() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_NavigateBack_SuccessfulResultGetsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Back() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* Forward tests */ func Test_NavigateForward_InvalidSessionIdResultsInAnError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.Forward() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_NavigateForward_CommunicationFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("AN error :< "), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Forward() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_NavigateForward__UnmarshallingFailureResultsInAnError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Forward() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_NavigateForward_SuccessfulResultGetsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Forward() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* Refresh tests */ func Test_NavigateRefresh_InvalidSessionIdResultsInAnError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.Refresh() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_NavigateRefresh_CommunicationFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("AN error :< "), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Refresh() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_NavigateRefresh_UnmarshallingFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Refresh() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_NavigateRefresh_SuccessfulResultGetsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Refresh() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* Title tests */ func Test_NavigateTitle_InvalidSessionIdResultsInAnError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.Title() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_NavigateTitle_CommunicationFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("AN error :< "), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Title() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_NavigateTitle_UnmarshallingFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Title() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_NavigateTitle_SuccessfulResultGetsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "Google" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Title() if err != nil || resp.State != "success" || resp.Title != "Google" { t.Errorf(correctResponseErrorText) } } ================================================ FILE: remote_driver_screenshot.go ================================================ package goselenium import ( "encoding/base64" "fmt" ) // ScreenshotResponse is the response returned from the Screenshot and // ScreenshotElement methods. type ScreenshotResponse struct { State string EncodedImage string } // ImageBytes is a helpful function for decoding the base64 encoded image URL. // The image returned is a PNG image and as such can be manipulated by the // image/png package. Trying to save this as any other image type will // result in it failing to open. func (s *ScreenshotResponse) ImageBytes() ([]byte, error) { return base64.StdEncoding.DecodeString(s.EncodedImage) } func (s *seleniumWebDriver) Screenshot() (*ScreenshotResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("Screenshot") } var err error url := fmt.Sprintf("%s/session/%s/screenshot", s.seleniumURL, s.sessionID) resp, err := s.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "Screenshot", }) if err != nil { return nil, err } return &ScreenshotResponse{State: resp.State, EncodedImage: resp.Value}, nil } ================================================ FILE: remote_driver_screenshot_test.go ================================================ package goselenium import ( "errors" "testing" ) func Test_ScreenshotScreenshot_NoSessionIdCausesError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.Screenshot() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_ScreenshotScreenshot_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error! :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Screenshot() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ScreenshotScreenshot_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.Screenshot() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ScreenshotScreen_CorrectResponseCanBeReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "dGVzdA==" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Screenshot() if err != nil || resp.State != "success" || resp.EncodedImage != "dGVzdA==" { t.Errorf(correctResponseErrorText) } } func Test_ScreenshotScreenshot_Base64StringCanBeDecoded(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "dGVzdA==" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.Screenshot() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } bytes, err := resp.ImageBytes() if err != nil || len(bytes) == 0 { t.Errorf(correctResponseErrorText) } } ================================================ FILE: remote_driver_session.go ================================================ package goselenium import ( "bytes" "encoding/json" "fmt" ) // CreateSessionResponse is the response returned from the API when the // CreateSession() method does not throw an error. type CreateSessionResponse struct { Capabilities CreateSessionCapabilities `json:"value"` SessionID string `json:"sessionId"` } // CreateSessionCapabilities is a summarisation of the capabilities returned // from the CreateSession method. type CreateSessionCapabilities struct { AcceptInsecureCerts bool `json:"acceptSslCerts"` BrowserName string `json:"browserName"` BrowserVersion string `json:"browserVersion"` PlatformName string `json:"platformVersion"` } // DeleteSessionResponse is the response returned from the API when the // DeleteSession() method does not thrown an error. type DeleteSessionResponse struct { State string `json:"state"` SessionID string `json:"sessionId"` } // SessionStatusResponse is the response returned from the API when the // SessionStatus() method is called. type SessionStatusResponse struct { State string } // SetSessionTimeoutResponse is the response returned from the API when the // SetSessionTimeoutResponse() method is called. type SetSessionTimeoutResponse struct { State string } func (s *seleniumWebDriver) CreateSession() (*CreateSessionResponse, error) { var response CreateSessionResponse var err error url := fmt.Sprintf("%s/session", s.seleniumURL) capabilitiesJSON, err := s.capabilities.toJSON() if err != nil { return nil, newMarshallingError(err, "CreateSession", s.capabilities) } body := bytes.NewReader([]byte(capabilitiesJSON)) resp, err := s.apiService.performRequest(url, "POST", body) if err != nil { return nil, newCommunicationError(err, "CreateSession", url, resp) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "CreateSession", string(resp)) } s.sessionID = response.SessionID return &response, nil } func (s *seleniumWebDriver) DeleteSession() (*DeleteSessionResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("DeleteSession") } var response DeleteSessionResponse var err error url := fmt.Sprintf("%s/session/%s", s.seleniumURL, s.sessionID) resp, err := s.apiService.performRequest(url, "DELETE", nil) if err != nil { return nil, newCommunicationError(err, "DeleteSession", url, resp) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "DeleteSession", string(resp)) } return &response, nil } func (s *seleniumWebDriver) SessionStatus() (*SessionStatusResponse, error) { var err error url := fmt.Sprintf("%s/status", s.seleniumURL) resp, err := s.stateRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "SessionStatus", }) if err != nil { return nil, err } return &SessionStatusResponse{State: resp.State}, nil } func (s *seleniumWebDriver) SetSessionTimeout(to Timeout) (*SetSessionTimeoutResponse, error) { if len(s.sessionID) == 0 { return nil, newSessionIDError("SetSessionTimeout") } var err error url := fmt.Sprintf("%s/session/%s/timeouts", s.seleniumURL, s.sessionID) params := map[string]interface{}{ "type": to.Type(), "ms": to.Timeout(), } marshalledJSON, err := json.Marshal(params) if err != nil { return nil, newMarshallingError(err, "SetSessionTimeout", params) } bodyReader := bytes.NewReader([]byte(marshalledJSON)) resp, err := s.stateRequest(&request{ url: url, method: "POST", body: bodyReader, callingMethod: "SetSessionTimeout", }) if err != nil { return nil, err } return &SetSessionTimeoutResponse{State: resp.State}, nil } ================================================ FILE: remote_driver_session_test.go ================================================ package goselenium import ( "errors" "testing" ) /* CREATE SESSION TESTS */ func Test_CreateSession_FailedAPIRequestResultsInAnErrorBeingReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.CreateSession() if !IsCommunicationError(err) { t.Errorf(sessionIDErrorText) } } func Test_CreateSession_ResultGetsUnmarshalledCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "sessionId": "a45a54d3-5413-425c-84ef-d1190cc0521c" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) resp, err := d.CreateSession() if err != nil || resp.SessionID == "" { t.Errorf(correctResponseErrorText) } } func Test_CreateSession_ResultIsAssignedToWebDriver(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "sessionId": "a45a54d3-5413-425c-84ef-d1190cc0521c" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.CreateSession() if err != nil || d.sessionID != "a45a54d3-5413-425c-84ef-d1190cc0521c" { t.Errorf(correctResponseErrorText) } } func Test_CreateSession_UnmarshallingErrorIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.CreateSession() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } /* DELETE SESSION TESTS */ func Test_DeleteSession_WhenSessionIDIsNotSetAnErrorIsThrown(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.DeleteSession() if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_DeleteSession_ApiFailureIsHandled(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("This is an error"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.DeleteSession() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_DeleteSession_ResponseIsUnmarshalledCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "sessionId": "3cebaef3-4fd0-464f-bd24-0a7170074ad4" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" resp, err := d.DeleteSession() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } func Test_DeleteSession_UnmarshallingFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" _, err := d.DeleteSession() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } /* Session Status Test */ func Test_SessionStatus_ApiFailureIsHandled(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("This is an error"), } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.SessionStatus() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_SessionStatusResponse_IsUnmarshalledCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) resp, err := d.SessionStatus() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } func Test_SessionStatusResponse_UnmarshallingFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.SessionStatus() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } /* Session Set Timeout Test */ func Test_SetSessionTimeout_ErrorIsThrownIfSessionIdNotSet(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) _, err := d.SetSessionTimeout(nil) if err == nil || !IsSessionIDError(err) { t.Errorf(sessionIDErrorText) } } func Test_SetSessionTimeout_ApiCommunicationErrorIsHandled(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error!"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "1" var timeouts = []Timeout{ SessionScriptTimeout(25000), SessionPageLoadTimeout(25000), SessionImplicitWaitTimeout(25000), } for _, i := range timeouts { _, err := d.SetSessionTimeout(i) if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } } func Test_SetSessionTimeout_ResponseIsUnmarshalledCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "1" var timeouts = []Timeout{ SessionScriptTimeout(25000), SessionPageLoadTimeout(25000), SessionImplicitWaitTimeout(25000), } for _, i := range timeouts { resp, err := d.SetSessionTimeout(i) if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } } func Test_SetSessionTimeout_UnmarshallingFailureResultsInError(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "1" var timeouts = []Timeout{ SessionScriptTimeout(25000), SessionPageLoadTimeout(25000), SessionImplicitWaitTimeout(25000), } for _, i := range timeouts { _, err := d.SetSessionTimeout(i) if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } } ================================================ FILE: remote_driver_test.go ================================================ package goselenium import ( "io" "strings" "testing" ) const ( apiCommunicationErrorText = "An error was not returned or was not of the API communication type" sessionIDErrorText = "An error was not returned or was not of the SessionIDError type" correctResponseErrorText = "An error was returned or the result was not what was expected" argumentErrorText = "An error was not returned or was not of the ArgumentError type" unmarshallingErrorText = "An error was not returned or was not of the UnmarshallingError type" ) func setUpDefaultCaps() *Capabilities { caps := Capabilities{} caps.SetBrowser(FirefoxBrowser()) return &caps } func setUpDriver(caps *Capabilities, api apiServicer) *seleniumWebDriver { return &seleniumWebDriver{ seleniumURL: "http://localhost:4444/wd/hub/", capabilities: caps, apiService: api, } } type testableAPIService struct { jsonToReturn string errorToReturn error bodyNilError error } func (t *testableAPIService) performRequest(url string, method string, body io.Reader) ([]byte, error) { json := []byte(t.jsonToReturn) return json, t.errorToReturn } func Test_NewSelenium_WebDriverCreatesErrorIfSeleniumURLIsInvalid(t *testing.T) { invalidSeleniumUrls := []string{ "", " ", "myRequirementWithoutProtocol", } for _, i := range invalidSeleniumUrls { caps := setUpDefaultCaps() _, err := NewSeleniumWebDriver(i, *caps) if err == nil { t.Errorf("Passing an invalid remote Selenium URL did not cause an error") } } } func Test_NewSelenium_WebDriverCreatesSuccessfullyIfSeleniumURLIsValid(t *testing.T) { validSeleniumUrls := []string{ "http://google.com", "https://google.com", } for _, i := range validSeleniumUrls { caps := setUpDefaultCaps() w, err := NewSeleniumWebDriver(i, *caps) if w == nil || err != nil { t.Errorf("Passing a valid remote Selenium URL caused an error or did not return a valid driver.") } } } func Test_NewSelenium_WebDriverCreatesErrorIfCapabilitiesAreEmpty(t *testing.T) { _, err := NewSeleniumWebDriver("http://google.com", Capabilities{}) if err == nil { t.Errorf("Passing an empty capabilities object did not cause an error.") } } func Test_NewSelenium_TrailingSlashIsRemovedIfTheUserDoesNotSpecifyOne(t *testing.T) { invalidUrls := []string{ "http://localhost/", "http://localhost:444/", } for _, i := range invalidUrls { caps := setUpDefaultCaps() d, err := NewSeleniumWebDriver(i, *caps) if err != nil || strings.HasSuffix(d.DriverURL(), "/") { t.Errorf("Trailing slash was not removed from URL or an error was returned.") } } } /* By tests */ func Test_ByByIndex_CorrectIndexReturnsAsExpected(t *testing.T) { correctIndexes := []uint{ 1, 58, 65535, } for _, i := range correctIndexes { r := ByIndex(i) if r.Type() != "index" || r.Value().(uint) != i { t.Errorf(correctResponseErrorText) } } } ================================================ FILE: remote_element.go ================================================ package goselenium import ( "bytes" "encoding/json" "fmt" ) func newSeleniumElement(i string, w *seleniumWebDriver) *seleniumElement { return &seleniumElement{ id: i, wd: w, } } // ElementSelectedResponse is the response returned from the Selected() call. // The result /should/ always be successfully returned unless there is a // server error. type ElementSelectedResponse struct { State string `json:"state"` Selected bool `json:"value"` } // ElementAttributeResponse is the response returned from the Attribute call. type ElementAttributeResponse struct { State string Value string } // ElementCSSValueResponse is the response returned when the CSSValue method // is called on an Element implementation. type ElementCSSValueResponse struct { State string Value string } // ElementTextResponse is the response returned from calling the Text method. type ElementTextResponse struct { State string Text string } // ElementTagNameResponse is the response returned from calling the TagName method. type ElementTagNameResponse struct { State string Tag string } // ElementRectangleResponse is the response returned from calling the Rectangle // method. type ElementRectangleResponse struct { State string Rectangle Rectangle `json:"value"` } // Rectangle repsents an elements size and position on the page. type Rectangle struct { Dimensions X int `json:"x"` Y int `json:"y"` } // ElementEnabledResponse is the response returned from calling the Enabled method. type ElementEnabledResponse struct { State string `json:"state"` Enabled bool `json:"value"` } // ElementClickResponse is the response returned from calling the Click method. type ElementClickResponse struct { State string } // ElementClearResponse is the response returned from calling the Clear method. type ElementClearResponse struct { State string } // ElementSendKeysResponse is the response returned from calling the SendKeys method. type ElementSendKeysResponse struct { State string } type seleniumElement struct { id string wd *seleniumWebDriver } func (s *seleniumElement) ID() string { return s.id } func (s *seleniumElement) Selected() (*ElementSelectedResponse, error) { var el ElementSelectedResponse var err error url := fmt.Sprintf("%s/session/%s/element/%s/selected", s.wd.seleniumURL, s.wd.sessionID, s.ID()) resp, err := s.wd.apiService.performRequest(url, "GET", nil) if err != nil { return nil, newCommunicationError(err, "Selected", url, nil) } err = json.Unmarshal(resp, &el) if err != nil { return nil, newUnmarshallingError(err, "Selected", string(resp)) } return &el, nil } func (s *seleniumElement) Attribute(att string) (*ElementAttributeResponse, error) { var err error url := fmt.Sprintf("%s/session/%s/element/%s/attribute/%s", s.wd.seleniumURL, s.wd.sessionID, s.ID(), att) resp, err := s.wd.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "Attribute", }) if err != nil { return nil, err } return &ElementAttributeResponse{State: resp.State, Value: resp.Value}, nil } func (s *seleniumElement) CSSValue(prop string) (*ElementCSSValueResponse, error) { var err error url := fmt.Sprintf("%s/session/%s/element/%s/css/%s", s.wd.seleniumURL, s.wd.sessionID, s.ID(), prop) resp, err := s.wd.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "CSSValue", }) if err != nil { return nil, err } return &ElementCSSValueResponse{State: resp.State, Value: resp.Value}, nil } func (s *seleniumElement) Text() (*ElementTextResponse, error) { var err error url := fmt.Sprintf("%s/session/%s/element/%s/text", s.wd.seleniumURL, s.wd.sessionID, s.ID()) resp, err := s.wd.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "Text", }) if err != nil { return nil, err } return &ElementTextResponse{State: resp.State, Text: resp.Value}, nil } func (s *seleniumElement) TagName() (*ElementTagNameResponse, error) { var err error url := fmt.Sprintf("%s/session/%s/element/%s/name", s.wd.seleniumURL, s.wd.sessionID, s.ID()) resp, err := s.wd.valueRequest(&request{ url: url, method: "GET", body: nil, callingMethod: "TagName", }) if err != nil { return nil, err } return &ElementTagNameResponse{State: resp.State, Tag: resp.Value}, nil } func (s *seleniumElement) Rectangle() (*ElementRectangleResponse, error) { var response ElementRectangleResponse var err error url := fmt.Sprintf("%s/session/%s/element/%s/rect", s.wd.seleniumURL, s.wd.sessionID, s.ID()) resp, err := s.wd.apiService.performRequest(url, "GET", nil) if err != nil { return nil, newCommunicationError(err, "Rectangle", url, nil) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "Rectangle", string(resp)) } return &response, nil } func (s *seleniumElement) Enabled() (*ElementEnabledResponse, error) { var response ElementEnabledResponse var err error url := fmt.Sprintf("%s/session/%s/element/%s/enabled", s.wd.seleniumURL, s.wd.sessionID, s.ID()) resp, err := s.wd.apiService.performRequest(url, "GET", nil) if err != nil { return nil, newCommunicationError(err, "Enabled", url, nil) } err = json.Unmarshal(resp, &response) if err != nil { return nil, newUnmarshallingError(err, "Enabled", string(resp)) } return &response, nil } func (s *seleniumElement) Click() (*ElementClickResponse, error) { var err error url := fmt.Sprintf("%s/session/%s/element/%s/click", s.wd.seleniumURL, s.wd.sessionID, s.ID()) resp, err := s.wd.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "Click", }) if err != nil { return nil, err } return &ElementClickResponse{State: resp.State}, nil } func (s *seleniumElement) Clear() (*ElementClearResponse, error) { var err error url := fmt.Sprintf("%s/session/%s/element/%s/clear", s.wd.seleniumURL, s.wd.sessionID, s.ID()) resp, err := s.wd.stateRequest(&request{ url: url, method: "POST", body: nil, callingMethod: "Clear", }) if err != nil { return nil, err } return &ElementClearResponse{State: resp.State}, nil } func (s *seleniumElement) SendKeys(keys string) (*ElementSendKeysResponse, error) { var err error url := fmt.Sprintf("%s/session/%s/element/%s/value", s.wd.seleniumURL, s.wd.sessionID, s.ID()) keyChars := make([]string, len(keys)) for i, k := range keys { keyChars[i] = string(k) } dict := map[string][]string{ "value": keyChars, } body, err := json.Marshal(dict) if err != nil { return nil, newMarshallingError(err, "SendKeys", dict) } reader := bytes.NewReader(body) resp, err := s.wd.stateRequest(&request{ url: url, method: "POST", body: reader, callingMethod: "SendKeys", }) if err != nil { return nil, err } return &ElementSendKeysResponse{State: resp.State}, nil } ================================================ FILE: remote_element_test.go ================================================ package goselenium import ( "errors" "testing" ) func Test_RemoteElement_IDCanBeRetrieved(t *testing.T) { el := newSeleniumElement("test", nil) if el.ID() != "test" { t.Errorf(correctResponseErrorText) } } /* SELECTED TESTS */ func Test_ElementSelected_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Selected() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementSelected_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Selected() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementSelected_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": true }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.Selected() if err != nil || resp.State != "success" || resp.Selected != true { t.Errorf(correctResponseErrorText) } } /* ATTRIBUTE TESTS */ func Test_ElementAttribute_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Attribute("test") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementAttribute_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Attribute("test") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementAttribute_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "test value" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.Attribute("test") if err != nil || resp.State != "success" || resp.Value != "test value" { t.Errorf(correctResponseErrorText) } } /* CSSVALUE TESTS */ func Test_ElementCSSValue_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.CSSValue("test") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementCSSValue_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.CSSValue("test") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementCSSValue_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "test value" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.CSSValue("test") if err != nil || resp.State != "success" || resp.Value != "test value" { t.Errorf(correctResponseErrorText) } } /* TEXT TESTS */ func Test_ElementText_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Text() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementText_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Text() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementText_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "test value" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.Text() if err != nil || resp.State != "success" || resp.Text != "test value" { t.Errorf(correctResponseErrorText) } } /* TAG NAME TESTS */ func Test_ElementTagName_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.TagName() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementTagName_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.TagName() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementTagName_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": "test value" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.TagName() if err != nil || resp.State != "success" || resp.Tag != "test value" { t.Errorf(correctResponseErrorText) } } /* RECTANGLE TESTS */ func Test_ElementRectangle_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Rectangle() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementRectangle_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Rectangle() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementRectangle_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": { "x": 100, "y": 200, "width": 50, "height": 50 } }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.Rectangle() if err != nil || resp.State != "success" || resp.Rectangle.X != 100 || resp.Rectangle.Height != 50 { t.Errorf(correctResponseErrorText) } } /* ENABLED TESTS */ func Test_ElementEnabled_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Enabled() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementEnabled_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Enabled() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementEnabled_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success", "value": true }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.Enabled() if err != nil || resp.State != "success" || !resp.Enabled { t.Errorf(correctResponseErrorText) } } /* CLICK TESTS */ func Test_ElementClick_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Click() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementClick_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Click() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementClick_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.Click() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* CLEAR TESTS */ func Test_ElementClear_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Clear() if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementClear_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.Clear() if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementClear_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.Clear() if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } /* SEND KEYS TESTS */ func Test_ElementSendKeys_CommunicationErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "", errorToReturn: errors.New("An error :<"), } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.SendKeys("test") if err == nil || !IsCommunicationError(err) { t.Errorf(apiCommunicationErrorText) } } func Test_ElementSendKeys_UnmarshallingErrorIsReturnedCorrectly(t *testing.T) { api := &testableAPIService{ jsonToReturn: "Invalid JSON!", errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) _, err := el.SendKeys("test") if err == nil || !IsUnmarshallingError(err) { t.Errorf(unmarshallingErrorText) } } func Test_ElementSendKeys_CorrectResponseIsReturned(t *testing.T) { api := &testableAPIService{ jsonToReturn: `{ "state": "success" }`, errorToReturn: nil, } d := setUpDriver(setUpDefaultCaps(), api) d.sessionID = "12345" el := newSeleniumElement("0", d) resp, err := el.SendKeys("test") if err != nil || resp.State != "success" { t.Errorf(correctResponseErrorText) } } ================================================ FILE: test/integration_tests/alert_acceptalert_test.go ================================================ package integrationtests import "testing" func Test_AlertAcceptAlert_CanAcceptAnAlertCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Create session error", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/alert.html") if err != nil { errorAndWrap(t, "Error navigating to URL", err) } resp, err := driver.AcceptAlert() if err != nil || resp.State != "success" { errorAndWrap(t, "Error accepting alert", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/alert_alerttext_test.go ================================================ package integrationtests import "testing" func Test_AlertAlertText_CanGetTheAlertText(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session.", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/alert.html") if err != nil { errorAndWrap(t, "Error visiting URL.", err) } resp, err := driver.AlertText() if err != nil || resp.State != "success" || resp.Text != "this is an alert" { errorAndWrap(t, "Error getting alert text.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/alert_dismissalert_test.go ================================================ package integrationtests import ( "testing" goselenium "github.com/bunsenapp/go-selenium" ) func Test_AlertDismissAlert_CanDismissAnAlertCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/alert.html") if err != nil { errorAndWrap(t, "Error visiting URL", err) } resp, err := driver.DismissAlert() if err != nil || resp.State != "success" { errorAndWrap(t, "Alert response was not correct", err) } printObjectResult(resp) } func Test_AlertDismissAlert_DismissingAnInvalidAlertResultsInAnError(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session", err) } _, err = driver.Go("https://google.com") if err != nil { errorAndWrap(t, "Error visiting URL", err) } resp, err := driver.DismissAlert() if err != nil { comErr := err.(goselenium.CommunicationError) if comErr.Response.State != goselenium.NoSuchAlert { errorAndWrap(t, "Incorrect result returned", err) } } else { errorAndWrap(t, "Incorrect result returned", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/alert_sendalerttext_test.go ================================================ package integrationtests import ( "testing" goselenium "github.com/bunsenapp/go-selenium" ) func Test_AlertSendAlertText_CanSendAlertTextCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/prompt.html") if err != nil { errorAndWrap(t, "Error visiting URL", err) } resp, err := driver.SendAlertText("test") if err != nil || resp.State != "success" { errorAndWrap(t, "Error sending alert text", err) } _, err = driver.AcceptAlert() if err != nil { errorAndWrap(t, "Error accepting alert", err) } _, err = driver.AlertText() if err != nil { comErr := err.(goselenium.CommunicationError) if comErr.Response.State != goselenium.NoSuchAlert { errorAndWrap(t, "Error returned was not correct", err) } } else { errorAndWrap(t, "Error returned was not correct", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_closewindow_test.go ================================================ package integrationtests import "testing" func Test_CommandCloseWindow_CanCloseTheWindow(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } resp, err := driver.CloseWindow() if err != nil || resp.State != "success" || len(resp.Handles) > 0 { errorAndWrap(t, "Error was returned or response was not correct", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_maximizewindow_test.go ================================================ package integrationtests import "testing" func Test_CommandMaximizeWindow_CorrectResultIsReturned(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } resp, err := driver.MaximizeWindow() if err != nil || resp.State != "success" { errorAndWrap(t, "Error was returned or response was not correct", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_setwindowsize_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_CommandSetWindowSize_CorrectResponseIsReturned(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } dimensions := &goselenium.Dimensions{ Width: 600, Height: 400, } resp, err := driver.SetWindowSize(dimensions) if err != nil || resp.State != "success" { errorAndWrap(t, "Error was returned or response was not correct", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_switchtoframe_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_CommandSwitchToFrame_CorrectResponseIsReturnedByIndex(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/iframe.html") if err != nil { errorAndWrap(t, "Error was thrown or result was not a success.", err) } resp, err := driver.SwitchToFrame(goselenium.ByIndex(0)) if err != nil || resp.State != "success" { errorAndWrap(t, "Error was thrown or result was not a success", err) } printObjectResult(resp) } func Test_CommandSwitchToFrame_InvalidByResultsInAnError(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/iframe.html") if err != nil { errorAndWrap(t, "Error was thrown or result was not a success.", err) } resp, err := driver.SwitchToFrame(goselenium.ByCSSSelector("iframe")) if err == nil { errorAndWrap(t, "Error was not thrown or was not the expected type.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_switchtoparentframe_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_CommandSwitchToParentFrame_CorrectResponseCanBeReturned(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/iframe.html") if err != nil { errorAndWrap(t, "Error was thrown whilst navigating.", err) } _, err = driver.SwitchToFrame(goselenium.ByIndex(0)) if err != nil { errorAndWrap(t, "Error was thrown whilst switching to frame 0.", err) } resp, err := driver.SwitchToParentFrame() if err != nil || resp.State != "success" { errorAndWrap(t, "Error was thrown or response was not a success.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_windowhandle_test.go ================================================ package integrationtests import "testing" func Test_CommandWindowHandle_CorrectResponseIsReturned(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } resp, err := driver.WindowHandle() if err != nil || resp.State != "success" || resp.Handle == "" { errorAndWrap(t, "Error was returned or response was not correct", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_windowhandles_test.go ================================================ package integrationtests import "testing" func Test_CommandWindowHandles_WindowHandlesAreReturned(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() resp, err := driver.WindowHandles() if err != nil || resp.State != "success" || resp.Handles[0] == "" { errorAndWrap(t, "Error thrown or result was not what was expected.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/command_windowsize_test.go ================================================ package integrationtests import "testing" func Test_CommandWindowSize_CorrectResultIsReturned(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } resp, err := driver.WindowSize() if err != nil || resp.State != "success" || resp.Dimensions.Width == 0 || resp.Dimensions.Height == 0 { errorAndWrap(t, "Error was returned or response was not correct", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/cookie_addcookie_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_CookieAddCookie_CanAddCookieWithCorrectFields(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst trying to create session.", err) } _, err = driver.Go("https://news.ycombinator.com") if err != nil { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } resp, err := driver.AddCookie(&goselenium.Cookie{ Name: "cookie", Value: "cookieValue", Path: "/", Domain: ".ycombinator.com", SecureOnly: false, HTTPOnly: true, }) if err != nil || resp.State != "success" { errorAndWrap(t, "Error was thrown whilst retrieving cookies", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/cookie_allcookies_test.go ================================================ package integrationtests import "testing" func Test_CookieAllCookies_CanRetrieveAllCookiesFromWebPage(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst trying to create session.", err) } _, err = driver.Go("https://news.ycombinator.com") if err != nil { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } resp, err := driver.AllCookies() if err != nil || resp.State != "success" || resp.Cookies[0].Name == "" { errorAndWrap(t, "Error was thrown whilst retrieving cookies", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/cookie_cookie_test.go ================================================ package integrationtests import "testing" func Test_CookieCookie_CanRetrieveCookieFromWebPage(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst trying to create session.", err) } _, err = driver.Go("https://news.ycombinator.com") if err != nil { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } resp, err := driver.Cookie("__cfduid") if err != nil || resp.State != "success" || resp.Cookie.Name == "" { errorAndWrap(t, "Error was thrown whilst retrieving cookie", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/cookie_deletecookie_test.go ================================================ package integrationtests import "testing" func Test_CookieDeleteCookie_CanDeleteSpecifiedCookie(t *testing.T) { setUp() defer tearDown() tests := []struct { url string cookieName string }{ { url: "https://news.ycombinator.com", cookieName: "__cfduid", }, { url: "https://www.google.com", cookieName: "CONSENT", }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { t.Errorf("Session creation failed") } _, err = driver.Go(te.url) if err != nil { t.Errorf("Navigation failed") } resp, err := driver.DeleteCookie(te.cookieName) if err != nil || resp.State != "success" { t.Errorf("Error whilst deleting cookie or was not a success.") } cookie, err := driver.Cookie(te.cookieName) if err != nil || cookie.Cookie.Name == te.cookieName { t.Errorf("Cookie still exists or an error occurred.") } driver.DeleteSession() printObjectResult(resp) } } func Test_CookieDeleteCookie_CanDeleteAllCookies(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { t.Errorf("Session creation failed") } _, err = driver.Go("https://www.google.com") if err != nil { t.Errorf("Navigation failed") } resp, err := driver.DeleteCookie("") if err != nil || resp.State != "success" { t.Errorf("Error whilst deleting cookie or was not a success.") } cookies, err := driver.AllCookies() if err != nil || len(cookies.Cookies) != 0 { t.Errorf("Cookies still exist or error was returned.") } printObjectResult(resp) } ================================================ FILE: test/integration_tests/document_executescript_test.go ================================================ package integrationtests import "testing" func Test_DocumentExecuteScript_CanExecuteScriptsSuccessfully(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://news.ycombinator.com") if err != nil { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } resp, err := driver.ExecuteScript("return \"Test\";") if err != nil || resp.Response != "Test" { errorAndWrap(t, "Error was thrown whilst executing script or response was not correct", err) } printObjectResult(resp) } func Test_DocumentExecuteScriptAsync_CanExecuteScriptsSuccessfully(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://news.ycombinator.com") if err != nil { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } resp, err := driver.ExecuteScriptAsync("var callback = arguments[arguments.length - 1]; callback('Test');") if err != nil || resp.Response != "Test" { errorAndWrap(t, "Error was thrown whilst executing script or response was not correct", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/document_pagesource_test.go ================================================ package integrationtests import "testing" func Test_DocumentPageSource_PageSourceIsCorrectlyRetrieved(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://news.ycombinator.com") if err != nil { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } sauce, err := driver.PageSource() if err != nil || len(sauce.Source) == 0 { errorAndWrap(t, "Error was thrown or page source was empty", err) } printObjectResult(sauce) } ================================================ FILE: test/integration_tests/element_attribute_test.go ================================================ package integrationtests import ( "strings" "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementAttribute_CanRetrieveAttributeCorrectly(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By attr string val string }{ { url: "https://www.google.com", by: goselenium.ByCSSSelector("input#lst-ib"), attr: "maxlength", val: "2048", }, { url: "https://news.ycombinator.com", by: goselenium.ByCSSSelector("b.hnname > a"), attr: "href", val: "news", }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } att, err := el.Attribute(te.attr) if err != nil || !strings.Contains(att.Value, te.val) { errorAndWrap(t, "Error whilst retrieving attribute or attribute value was not correct", err) } driver.DeleteSession() printObjectResult(att) } } ================================================ FILE: test/integration_tests/element_clear_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementClear_ElementsAreClearedSuccessfully(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ { url: "https://bunsenapp.github.io/go-selenium/helpers/clear.html", by: goselenium.ByCSSSelector("input#should-clear"), }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Create session failed", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Navigating to URL failed", err) } el, err := driver.FindElement(te.by) if err != nil { errorAndWrap(t, "Retrieving element failed", err) } _, err = el.Clear() if err != nil { errorAndWrap(t, "Clearing element failed", err) } resp, err := el.Text() if err != nil || len(resp.Text) > 0 { errorAndWrap(t, "Retrieving text failed or text was not cleared", err) } driver.DeleteSession() printObjectResult(resp) } } ================================================ FILE: test/integration_tests/element_click_test.go ================================================ package integrationtests import ( "testing" "time" "github.com/bunsenapp/go-selenium" ) func Test_ElementClick_ClickSuccessfullyNavigates(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By expTitle string }{ { url: "https://www.google.com", by: goselenium.ByLinkText("Privacy"), expTitle: "Privacy Policy – Privacy & Terms – Google", }, { url: "https://news.ycombinator.com", by: goselenium.ByLinkText("new"), expTitle: "New Links | Hacker News", }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error visiting URL.", err) } el, err := driver.FindElement(te.by) if err != nil { errorAndWrap(t, "Error finding element", err) } _, err = el.Click() if err != nil { errorAndWrap(t, "Error clicking element", err) } // TODO: Unfortunate Selenium flaw - will need the helpers to get around // an explicit wait. Also occurs in Python library. time.Sleep(1 * time.Second) resp, err := driver.Title() if err != nil || resp.Title != te.expTitle { errorAndWrap(t, "Error retrieving title or title was not correct", err) } driver.DeleteSession() printObjectResult(resp) } } ================================================ FILE: test/integration_tests/element_cssclass_test.go ================================================ package integrationtests import ( "fmt" "strings" "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementCSSValue_CanGetCorrectCSSValue(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By cssName string cssVal string }{ { url: "https://www.google.com", by: goselenium.ByCSSSelector("input[name='btnK']"), cssName: "font-family", cssVal: "arial,sans-serif", }, { url: "https://news.ycombinator.com", by: goselenium.ByCSSSelector("a[href='news']"), cssName: "color", cssVal: "rgb(0, 0, 0)", }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } att, err := el.CSSValue(te.cssName) if err != nil || !strings.Contains(att.Value, te.cssVal) { fmt.Println(att) errorAndWrap(t, "Error whilst retrieving CSS class or value was not correct", err) } driver.DeleteSession() printObjectResult(att) } } func Test_ElementCSSValue_CSSValueThatDoesNotExistDoesNotCauseAnError(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By cssName string }{ { url: "https://www.google.com", by: goselenium.ByCSSSelector("input[name='btnK']"), cssName: "background", }, { url: "https://news.ycombinator.com", by: goselenium.ByCSSSelector("a[href='news']"), cssName: "border-radius", }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } att, err := el.CSSValue(te.cssName) if err != nil { fmt.Println(att) errorAndWrap(t, "Error whilst retrieving CSS class", err) } driver.DeleteSession() printObjectResult(att) } } ================================================ FILE: test/integration_tests/element_enabled_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementEnabled_EnabledElementIsReturnedCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://google.com") if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(goselenium.ByCSSSelector("input#lst-ib")) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.Enabled() if err != nil || !resp.Enabled { errorAndWrap(t, "Error whilst retrieving response or element was not enabled", err) } printObjectResult(resp) } func Test_ElementEnabled_DisabledElementIsReturnedCorrectly(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By exp bool }{ { url: "https://news.ycombinator.com", by: goselenium.ByCSSSelector("a[href='news']"), exp: true, }, { url: "https://bunsenapp.github.io/go-selenium/helpers/disabled.html", by: goselenium.ByCSSSelector("input"), exp: false, }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.Enabled() if err != nil || resp.Enabled != te.exp { errorAndWrap(t, "Error whilst retrieving response or the element's enabled property was not correct", err) } driver.DeleteSession() printObjectResult(resp) } } ================================================ FILE: test/integration_tests/element_findelement_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementFindElement_CanFindElementByCSSSelector(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.google.com", goselenium.ByCSSSelector("input#lst-ib")}, {"https://www.reddit.com", goselenium.ByCSSSelector("input[name=q]")}, {"https://news.ycombinator.com", goselenium.ByCSSSelector("#hnmain")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } printObjectResult(el) driver.DeleteSession() } } func Test_ElementFindElement_CanFindElementByLinkText(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.google.com", goselenium.ByLinkText("Gmail")}, {"https://www.reddit.com", goselenium.ByLinkText("new")}, {"https://news.ycombinator.com", goselenium.ByLinkText("submit")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } printObjectResult(el) driver.DeleteSession() } } func Test_ElementFindElement_CanFindElementByPartialLinkText(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.google.com", goselenium.ByPartialLinkText("Gmai")}, {"https://www.reddit.com", goselenium.ByPartialLinkText("ew")}, {"https://news.ycombinator.com", goselenium.ByPartialLinkText("ubmit")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } printObjectResult(el) driver.DeleteSession() } } func Test_ElementFindElement_CanFindElementByXPath(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.google.com", goselenium.ByXPath("//input[@id='lst-ib']")}, {"https://news.ycombinator.com", goselenium.ByXPath("//b[@class='hnname']/a[@href='news']")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } printObjectResult(el) driver.DeleteSession() } } ================================================ FILE: test/integration_tests/element_findelements_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementFindElements_CanFindElementsByCSSSelector(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.google.com", goselenium.ByCSSSelector("input")}, {"https://www.reddit.com", goselenium.ByCSSSelector("a")}, {"https://news.ycombinator.com", goselenium.ByCSSSelector(".storylink")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElements(te.by) if err != nil || el == nil || len(el) <= 1 { errorAndWrap(t, "Error whilst finding elements or element was not found", err) } printObjectResult(el) driver.DeleteSession() } } func Test_ElementFindElements_CanFindElementsByLinkText(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.reddit.com", goselenium.ByLinkText("share")}, {"https://news.ycombinator.com", goselenium.ByLinkText("hide")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElements(te.by) if err != nil || el == nil || len(el) <= 1 { errorAndWrap(t, "Error whilst finding elements or elements were not found", err) } printObjectResult(el) driver.DeleteSession() } } func Test_ElementFindElements_CanFindElementsByPartialLinkText(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.google.com", goselenium.ByPartialLinkText("a")}, {"https://www.reddit.com", goselenium.ByPartialLinkText("hi")}, {"https://news.ycombinator.com", goselenium.ByPartialLinkText("comment")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElements(te.by) if err != nil || el == nil || len(el) <= 1 { errorAndWrap(t, "Error whilst finding elements or elements were not found", err) } printObjectResult(el) driver.DeleteSession() } } func Test_ElementFindElements_CanFindElementsByXPath(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By }{ {"https://www.google.com", goselenium.ByXPath("//input")}, {"https://news.ycombinator.com", goselenium.ByXPath("//a")}, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElements(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding elements or element were not found", err) } printObjectResult(el) driver.DeleteSession() } } ================================================ FILE: test/integration_tests/element_rectangle_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementRectangle_SizeIsReturnedCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/size.html") if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(goselenium.ByCSSSelector("div")) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.Rectangle() if err != nil || resp.Rectangle.Width != 100 || resp.Rectangle.Height != 100 { errorAndWrap(t, "Error was returned or element's size was not correct.", err) } printObjectResult(resp) } func Test_ElementRectangle_PositionIsReturnedCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://google.com") if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(goselenium.ByCSSSelector("input#lst-ib")) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.Rectangle() if err != nil || resp.Rectangle.X == 0 || resp.Rectangle.Height == 0 { errorAndWrap(t, "Error was returned or element's size was not correct.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/element_selected_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementSelected_CheckedElementReturnsCorrectly(t *testing.T) { setUp() defer tearDown() tests := []goselenium.By{ goselenium.ByCSSSelector("input[name='i_am_checked']"), goselenium.ByCSSSelector("input[name='i_am_selected']"), } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/selected.html") if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.Selected() if err != nil || !resp.Selected { errorAndWrap(t, "Error was returned or element was not selected.", err) } driver.DeleteSession() printObjectResult(resp) } } func Test_ElementSelected_UncheckedElementReturnsCorrectly(t *testing.T) { setUp() defer tearDown() tests := []goselenium.By{ goselenium.ByCSSSelector("input[name='i_am_not_checked']"), goselenium.ByCSSSelector("input[name='i_am_not_selected']"), } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/selected.html") if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.Selected() if err != nil || resp.Selected { errorAndWrap(t, "Error was returned or element was selected.", err) } driver.DeleteSession() printObjectResult(resp) } } func Test_ElementSelected_RandomElementsDoNotError(t *testing.T) { setUp() defer tearDown() tests := []goselenium.By{ goselenium.ByCSSSelector("a.storylink"), goselenium.ByCSSSelector(".title"), } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://news.ycombinator.com") if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.Selected() if err != nil || resp.Selected { errorAndWrap(t, "Error was returned or element was selected.", err) } driver.DeleteSession() printObjectResult(resp) } } ================================================ FILE: test/integration_tests/element_sendkeys_test.go ================================================ package integrationtests import ( "strings" "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementSendKeys_CanSendKeysToInputField(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session", err) } _, err = driver.Go("https://www.google.com") if err != nil { errorAndWrap(t, "Error navigating to URL", err) } el, err := driver.FindElement(goselenium.ByCSSSelector("input#lst-ib")) if err != nil { errorAndWrap(t, "Error finding element", err) } _, err = el.SendKeys("test") if err != nil { errorAndWrap(t, "Error sending keys to element", err) } _, err = el.SendKeys(goselenium.EnterKey) if err != nil { errorAndWrap(t, "Error sending enter key to element", err) } url, err := driver.CurrentURL() if err != nil || !strings.Contains(url.URL, "test") { errorAndWrap(t, "Error retrieving current URL or it did not contain the correct value", err) } printObjectResult(url) } ================================================ FILE: test/integration_tests/element_tagname_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementTagName_CanRetrieveCorrectTagName(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By exp string }{ { url: "https://news.ycombinator.com", by: goselenium.ByCSSSelector("a[href='submit']"), exp: "a", }, { url: "https://google.com", by: goselenium.ByCSSSelector("input#lst-ib"), exp: "input", }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } resp, err := el.TagName() if err != nil || resp.Tag != te.exp { errorAndWrap(t, "Error was returned or tag name was incorrect.", err) } driver.DeleteSession() printObjectResult(resp) } } ================================================ FILE: test/integration_tests/element_text_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_ElementText_CorrectElementTextGetsReturned(t *testing.T) { setUp() defer tearDown() tests := []struct { url string by goselenium.By exp string }{ { url: "https://google.com", by: goselenium.ByCSSSelector("input#lst-ib"), exp: "", }, { url: "https://news.ycombinator.com", by: goselenium.ByCSSSelector("a[href='submit']"), exp: "submit", }, } for _, te := range tests { driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go(te.url) if err != nil { errorAndWrap(t, "Error thrown whilst visiting url.", err) } el, err := driver.FindElement(te.by) if err != nil || el == nil { errorAndWrap(t, "Error whilst finding element or element was not found", err) } txt, err := el.Text() if err != nil || txt.Text != te.exp { errorAndWrap(t, "Error whilst getting element text or text was not correct", err) } driver.DeleteSession() printObjectResult(txt) } } ================================================ FILE: test/integration_tests/helpers_elementpresent_test.go ================================================ package integrationtests import ( "testing" "time" goselenium "github.com/bunsenapp/go-selenium" ) func Test_ElementWaitUntilElementPresent_CanSucceed(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/element-present.html") if err != nil { errorAndWrap(t, "Error navigating to URL", err) } by := goselenium.ByCSSSelector("#not-present-div") resp := driver.Wait(goselenium.UntilElementPresent(by), 20*time.Second, 0) if !resp { errorAndWrap(t, "Error waiting for element to be visible or it timed out", err) } printObjectResult(resp) } func Test_ElementWaitUntilElementPresent_NotFoundPriorToTimeoutFails(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error creating session", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/element-present.html") if err != nil { errorAndWrap(t, "Error navigating to URL", err) } by := goselenium.ByCSSSelector("#not-present-div") resp := driver.Wait(goselenium.UntilElementPresent(by), 1*time.Second, 0) if resp { errorAndWrap(t, "Error was not thrown when it should have been", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/helpers_untilurlis_test.go ================================================ package integrationtests import ( "testing" "time" goselenium "github.com/bunsenapp/go-selenium" ) func Test_WaitUntilURLIs_WorksCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error whilst creating session", err) } _, err = driver.Go("https://bunsenapp.github.io/go-selenium/helpers/url-change.html") if err != nil { errorAndWrap(t, "Error whilst navigating", err) } ok := driver.Wait(goselenium.UntilURLIs("https://bunsenapp.github.io/test"), 30*time.Second, 0) if !ok { errorAndWrap(t, "Timeout was exceeded", nil) } } ================================================ FILE: test/integration_tests/navigate_back_test.go ================================================ package integrationtests import ( "strings" "testing" ) func Test_NavigateBack_NavigateBackWorksCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } goResp, err := driver.Go("https://news.ycombinator.com") if err != nil || goResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } goResp, err = driver.Go("https://google.co.uk") if err != nil || goResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } backResp, err := driver.Back() if err != nil || backResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating back or results was not a success.", err) } currentURLResp, err := driver.CurrentURL() if err != nil || !strings.HasPrefix(currentURLResp.URL, "https://news.ycombinator.com") { errorAndWrap(t, "Error was thrown or URL was not what it should have been.", err) } printObjectResult(currentURLResp) } ================================================ FILE: test/integration_tests/navigate_forward_test.go ================================================ package integrationtests import ( "strings" "testing" ) func Test_NavigateForward_NavigateFowardWorksCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } goResp, err := driver.Go("https://google.co.uk") if err != nil || goResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } goResp, err = driver.Go("https://news.ycombinator.com") if err != nil || goResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } backResp, err := driver.Back() if err != nil || backResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating backwards or results was not a success.", err) } forwardResp, err := driver.Forward() if err != nil || forwardResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating forwards or result was not a success.", err) } currentURLResp, err := driver.CurrentURL() if err != nil || !strings.HasPrefix(currentURLResp.URL, "https://news.ycombinator.com") { errorAndWrap(t, "Error was thrown or URL was not what it should have been.", err) } printObjectResult(currentURLResp) } ================================================ FILE: test/integration_tests/navigate_go_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_NavigateGo_CanNavigateSuccessfully(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } resp, err := driver.Go("https://www.google.com") if err != nil || resp.State != "success" { errorAndWrap(t, "Error was thrown or result was not a success.", err) } } func Test_NavigateGo_InvalidURLIsReturned(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } resp, err := driver.Go("www.google.com") if err != nil { if !goselenium.IsInvalidURLError(err) { errorAndWrap(t, "Error was thrown or result was not a success.", err) } } printObjectResult(resp) } func Test_NavigateGo_CanGetCurrentURL(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } _, err = driver.Go("https://github.com/") if err != nil { errorAndWrap(t, "Error was thrown when it shouldn't have been.", err) } resp, err := driver.CurrentURL() if err != nil || resp.URL != "https://github.com/" { errorAndWrap(t, "Error was thrown or URL was not what was sent.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/navigate_refresh_test.go ================================================ package integrationtests import ( "strings" "testing" ) func Test_NavigateRefresh_RefreshWorksCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } goResp, err := driver.Go("https://news.ycombinator.com") if err != nil || goResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } refreshResp, err := driver.Refresh() if err != nil || refreshResp.State != "success" { errorAndWrap(t, "Error was thrown whilst refreshing or result was not a success.", err) } currentURLResp, err := driver.CurrentURL() if err != nil || !strings.HasPrefix(currentURLResp.URL, "https://news.ycombinator.com") { errorAndWrap(t, "Error was thrown or URL was not what it should have been.", err) } printObjectResult(currentURLResp) } ================================================ FILE: test/integration_tests/navigate_title_test.go ================================================ package integrationtests import "testing" func Test_NavigateTitle_TitleCanBeRetrievedSuccessfully(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } goResp, err := driver.Go("https://google.com") if err != nil || goResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } titleResponse, err := driver.Title() if err != nil || titleResponse.Title != "Google" { errorAndWrap(t, "Error was thrown or URL was not what it should have been.", err) } printObjectResult(titleResponse) } ================================================ FILE: test/integration_tests/screenshot_screenshot_test.go ================================================ package integrationtests import "testing" func Test_ScreenshotScreenshot_ScreenshotCanBeTakenSuccessfully(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error thrown whilst creating session.", err) } goResp, err := driver.Go("https://google.com") if err != nil || goResp.State != "success" { errorAndWrap(t, "Error was thrown whilst navigating or result was not a success.", err) } scs, err := driver.Screenshot() if err != nil || scs.State != "success" || len(scs.EncodedImage) == 0 { errorAndWrap(t, "Error thrown whilst taking screenshot.", err) } dec, err := scs.ImageBytes() if err != nil || len(dec) == 0 { errorAndWrap(t, "Error thrown whilst getting image bytes of screenshot.", err) } printObjectResult(dec) } ================================================ FILE: test/integration_tests/session_create_test.go ================================================ package integrationtests import ( "strings" "testing" ) func Test_SessionCreate_ANewSessionCanBeCreated(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) session, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Creation of session yielded an error.", err) } else if session.SessionID == "" || session.Capabilities.BrowserName != "firefox" { errorAndWrap(t, "Returned object was not set correctly.", err) } printObjectResult(session) } func Test_SessionCreate_TrailingSlashIsAdded(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if strings.HasSuffix(driver.DriverURL(), "/") || err != nil { errorAndWrap(t, "Driver URL did not get a slash appended or an error occurred.", err) } } ================================================ FILE: test/integration_tests/session_delete_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_SessionDelete_CallingDeleteSessionMethodWithoutASessionIdResultsInAnError(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.DeleteSession() if err == nil || !goselenium.IsSessionIDError(err) { errorAndWrap(t, "Session error was not returned when it should have been.", err) } } func Test_SessionDelete_DeleteSessionMethodWorksCorrectly(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error returned whilst creating session", err) } resp, err := driver.DeleteSession() if err != nil || resp.State != "success" { errorAndWrap(t, "Error returned or state was not success whilst deleting session.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/session_general_test.go ================================================ package integrationtests import "testing" func Test_Session_CanCreateAndDeleteSession(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Creation of session yielded an error.", err) } _, err = driver.DeleteSession() if err != nil { errorAndWrap(t, "Creation of session yielded an error.", err) } } func Test_Session_CanCreateSessionAndGetStatus(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Creation of session yielded an error.", err) } resp, err := driver.SessionStatus() if err != nil || resp.State != "success" { errorAndWrap(t, "Error occurred or the state was not a success", err) } } ================================================ FILE: test/integration_tests/session_settimeout_test.go ================================================ package integrationtests import ( "testing" "github.com/bunsenapp/go-selenium" ) func Test_SessionSetTimeout_CallingSetTimeoutWithoutSessionCausesAnError(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.SetSessionTimeout(goselenium.SessionPageLoadTimeout(20000)) if err == nil || !goselenium.IsSessionIDError(err) { errorAndWrap(t, "Session error was not returned.", err) } } func Test_SessionSetTimeout_CanSetScriptTimeout(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error returned whilst creating session", err) } resp, err := driver.SetSessionTimeout(goselenium.SessionScriptTimeout(20000)) if err != nil || resp.State != "success" { errorAndWrap(t, "Error returned or state was not success whilst setting script timeout.", err) } printObjectResult(resp) } func Test_SessionSetTimeout_CanSetPageLoadTimeout(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error returned whilst creating session", err) } resp, err := driver.SetSessionTimeout(goselenium.SessionPageLoadTimeout(20000)) if err != nil || resp.State != "success" { errorAndWrap(t, "Error returned or state was not success whilst setting page load timeout.", err) } printObjectResult(resp) } func Test_SessionSetTimeout_CanSetImplicitWaitTimeout(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) _, err := driver.CreateSession() if err != nil { errorAndWrap(t, "Error returned whilst creating session", err) } resp, err := driver.SetSessionTimeout(goselenium.SessionImplicitWaitTimeout(20000)) if err != nil || resp.State != "success" { errorAndWrap(t, "Error returned or state was not success whilst setting implicit wait timeout.", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/session_status_test.go ================================================ package integrationtests import "testing" func Test_SessionStatus_CanRetrieveStatusOfDriverSuccessfully(t *testing.T) { setUp() defer tearDown() driver := createDriver(t) resp, err := driver.SessionStatus() if err != nil || resp.State != "success" { errorAndWrap(t, "Error occurred or state is incorrect", err) } printObjectResult(resp) } ================================================ FILE: test/integration_tests/test.go ================================================ package integrationtests import ( "fmt" "os" "os/exec" "strconv" "testing" "time" "github.com/bunsenapp/go-selenium" "github.com/pkg/errors" ) func setUp() { command := exec.Command("docker", "run", "-d", "--name=goselenium-tests", "-p=4444:4444", "selenium/standalone-firefox") command.CombinedOutput() time.Sleep(2000 * time.Millisecond) } func tearDown() { command := exec.Command("docker", "rm", "goselenium-tests", "-f") command.CombinedOutput() } func errorAndWrap(t *testing.T, message string, oldError error) { if oldError == nil { t.Errorf(errors.New(message).Error()) } else { err := errors.Wrap(oldError, message) t.Errorf(err.Error()) } } func printObjectResult(obj interface{}) { envResult := os.Getenv("GOSELENIUM_TEST_DETAIL") shouldShowDetailedResults, err := strconv.ParseBool(envResult) if shouldShowDetailedResults && err == nil { fmt.Println(fmt.Sprintf("Object returned: %+v", obj)) } } func createDriver(t *testing.T) goselenium.WebDriver { caps := goselenium.Capabilities{} caps.SetBrowser(goselenium.FirefoxBrowser()) driver, err := goselenium.NewSeleniumWebDriver("http://localhost:4444/wd/hub/", caps) if err != nil { t.Errorf("Driver creation threw an error.") } return driver } ================================================ FILE: web_driver.go ================================================ package goselenium import "time" // Keyboard keys converted from the ASCII code. const ( UnidentifiedKey = string('\uE000') CancelKey = string('\uE001') HelpKey = string('\uE002') BackspaceKey = string('\uE003') TabKey = string('\uE004') ClearKey = string('\uE005') ReturnKey = string('\uE006') EnterKey = string('\uE007') ShiftKey = string('\uE008') ControlKey = string('\uE009') AltKey = string('\uE00A') PauseKey = string('\uE00B') EscapeKey = string('\uE00C') SpaceKey = string('\uE00D') PageUpKey = string('\uE00E') PageDownKey = string('\uE00F') EndKey = string('\uE010') HomeKey = string('\uE011') ArrowLeftKey = string('\uE012') ArrowUpKey = string('\uE013') ArrowRightKey = string('\uE014') ArrowDownKey = string('\uE015') InsertKey = string('\uE016') DeleteKey = string('\uE017') SemiColonKey = string('\uE018') EqualsKey = string('\uE019') AsteriskKey = string('\uE024') PlusKey = string('\uE025') CommaKey = string('\uE026') MinusKey = string('\uE027') PeriodKey = string('\uE028') ForwardSlashKey = string('\uE029') F1Key = string('\uE031') F2Key = string('\uE032') F3Key = string('\uE033') F4Key = string('\uE034') F5Key = string('\uE035') F6Key = string('\uE036') F7Key = string('\uE037') F8Key = string('\uE038') F9Key = string('\uE039') F10Key = string('\uE03A') F11Key = string('\uE03B') F12Key = string('\uE03C') MetaKey = string('\uE03D') ZenkakuHankakuKey = string('\uE040') ) // Error codes that are returned from Selenium. Infer that the // type of the error returned is CommunicationError, then do a comparison // on the err.Response.State field to one of the below constants. const ( ElementNotSelectable = "element not selectable" ElementNotInteractable = "element not interactable" InsecureCertificate = "insecure certificate" InvalidArgument = "invalid argument" InvalidCookieDomain = "invalid cookie domain" InvalidCoordinates = "invalid coordinates" InvalidElementState = "invalid element state" InvalidSelector = "invalid selector" InvalidSessionID = "invalid session id" JavascriptError = "javascript error" MoveTargetOutOfBounds = "move target out of bounds" NoSuchAlert = "no such alert" NoSuchCookie = "no such cookie" NoSuchElement = "no such element" NoSuchFrame = "no such frame" NoSuchWindow = "no such window" ScriptTimeout = "script timeout" SessionNotCreated = "session not created" StaleElementReference = "stale element reference" TimeoutError = "timeout" UnableToSetCookie = "unable to set cookie" UnableToCaptureScreen = "unable to capture screen" UnexpectedAlertOpen = "unexpected alert open" UnknownCommand = "unknown command" UnknownError = "unknown error" UnknownMethod = "unknown method" UnsupportedOperation = "unsupported operation" ) // WebDriver is an interface which adheres to the W3C specification // for WebDrivers (https://w3c.github.io/webdriver/webdriver-spec.html). type WebDriver interface { /* PROPERTY ACCESS METHODS */ // DriverURL returns the URL where the W3C compliant web driver is hosted. DriverURL() string /* SESSION METHODS */ // CreateSession creates a session in the remote driver with the // desired capabilities. CreateSession() (*CreateSessionResponse, error) // DeleteSession deletes the current session associated with the web driver. DeleteSession() (*DeleteSessionResponse, error) // SessionStatus gets the status about whether a remove end is in a state // which it can create new sessions. SessionStatus() (*SessionStatusResponse, error) // SetSessionTimeout sets a timeout for one of the 3 options. // Call SessionScriptTimeout() to generate a script timeout. // Call SessionPageLoadTimeout() to generate a page load timeout. // Call SessionImplicitWaitTimeout() to generate an implicit wait timeout. SetSessionTimeout(to Timeout) (*SetSessionTimeoutResponse, error) /* NAVIGATION METHODS */ // Go forces the browser to perform a GET request on a URL. Go(url string) (*GoResponse, error) // CurrentURL returns the current URL of the top level browsing context. CurrentURL() (*CurrentURLResponse, error) // Back instructs the web driver to go one step back in the page history. Back() (*BackResponse, error) // Forward instructs the web driver to go one step forward in the page history. Forward() (*ForwardResponse, error) // Refresh instructs the web driver to refresh the page that it is currently on. Refresh() (*RefreshResponse, error) // Title gets the title of the current page of the web driver. Title() (*TitleResponse, error) /* COMMAND METHODS */ // WindowHandle retrieves the current active browsing string for the current session. WindowHandle() (*WindowHandleResponse, error) // CloseWindow closes the current active window (see WindowHandle() for what // window that will be). CloseWindow() (*CloseWindowResponse, error) // SwitchToWindow switches the current browsing context to a specified window // handle. SwitchToWindow(handle string) (*SwitchToWindowResponse, error) // WindowHandles gets all of the window handles for the current session. // To retrieve the currently active window handle, see WindowHandle(). WindowHandles() (*WindowHandlesResponse, error) // SwitchToFrame switches to a frame determined by the "by" parameter. // You can use ByIndex to find the frame to switch to. Any other // By implementation will yield an InvalidByParameter error. SwitchToFrame(by By) (*SwitchToFrameResponse, error) // SwitchToParentFrame switches to the parent of the current top level // browsing context. SwitchToParentFrame() (*SwitchToParentFrameResponse, error) // WindowSize retrieves the current browser window size for the // active session. WindowSize() (*WindowSizeResponse, error) // SetWindowSize sets the current browser window size for the active // session. SetWindowSize(dimensions *Dimensions) (*SetWindowSizeResponse, error) // Maximize increases the current browser window to its maximum size. MaximizeWindow() (*MaximizeWindowResponse, error) /* ELEMENT METHODS */ // FindElement finds an element via a By implementation (i.e. CSS selector, // x-path). Attempting to find via index will result in an argument error // being thrown. FindElement(by By) (Element, error) // FindElements works the same way as FindElement but can return more than // one result. FindElements(by By) ([]Element, error) /* DOCUMENT HANDLING METHODS */ // PageSource retrieves the outerHTML value of the current URL. PageSource() (*PageSourceResponse, error) // ExecuteScript executes a Javascript script on the currently active // page. ExecuteScript(script string) (*ExecuteScriptResponse, error) // ExecuteScriptAsync executes a Javascript script asynchronously on the // currently active page. If you do not have experience with this call, // there is an example below. // // The async handler runs on the concept of a callback; meaning it will run // your code asynchronously and if it completes, will call the callback. // // Selenium helpfully provides a callback function which is passed in // to the 'arguments' array that you can access within your script. The // callback function is always the LAST element of the array. You can // access it like the below: // var callback = arguments[arguments.length - 1]; // The callback function also accepts one argument as a parameter, this // can be anything and will be assigned to the Response property of // ExecuteScriptResponse. // // An example: // var callback = arguments[arguments.length - 1]; // doLongWindedTask(); // callback(); ExecuteScriptAsync(script string) (*ExecuteScriptResponse, error) /* COOKIE METHODS */ // AllCookies returns all cookies associated with the active URL of the // current browsing context. AllCookies() (*AllCookiesResponse, error) // Cookie gets a single named cookie associated with the active URL of the // current browsing context. Cookie(name string) (*CookieResponse, error) // AddCookie adds a cookie to the current browsing context. AddCookie(c *Cookie) (*AddCookieResponse, error) // DeleteCookie deletes a cookie from the current browsing session. If name // is passed as an empty string, all cookies for the current address will // be deleted. DeleteCookie(name string) (*DeleteCookieResponse, error) /* ALERT METHODS */ // DismissAlert dismisses an alert if there is one present. If not, it will // throw an error. DismissAlert() (*DismissAlertResponse, error) // AcceptAlertResponse accepts an alert if there is one present. If not, // it will throw an error. AcceptAlert() (*AcceptAlertResponse, error) // AlertText gets the text associated with the current alert. If there is // not an alert, it will throw an error. AlertText() (*AlertTextResponse, error) // SendAlertText enters the text specified into the value box. // // If the prompt is of type 'alert' or 'confirm', a communication error // with code 'element not interactable' will be returned. // // If the prompt is anything other than 'prompt', a communication error with // code 'unsupported operation' will be returned. SendAlertText(text string) (*SendAlertTextResponse, error) /* SCREEN CAPTURE METHODS */ // Screenshot takes a screenshot of the window of the current top level // browsing context. The image returned will be a PNG image. Screenshot() (*ScreenshotResponse, error) /* HELPER METHODS */ // Wait repeats an action until the action yields a valid result or // until the timeout is reached. If the timeout is reached without // the until function returning a satisfactory result, this method // will return false. // // time.Sleep will be called with the sleep parameter after every // u iteration. Wait(u Until, timeout time.Duration, sleep time.Duration) bool } // Element is an interface which specifies what all WebDriver elements // must do. Any requests which involve this element (i.e. FindElements that // are children of the current element) will be specified. Anything not related // will exist within the WebDriver interface/implementation. type Element interface { // ID is the assigned ID for the element returned from the Selenium driver. ID() string // Selected gets whether or not the current element is selected. This only // makes sense for inputs such as radio buttons and checkboxes. Selected() (*ElementSelectedResponse, error) // Attribute retrieves an attribute (i.e. href, class) of the current // active element. Attribute(att string) (*ElementAttributeResponse, error) // CSSValue retrieves a CSS property associated with the current element. // As an example, this could be the 'background' or 'font-family' properties. CSSValue(prop string) (*ElementCSSValueResponse, error) // Text gets the value of element.innerText for the current element. Text() (*ElementTextResponse, error) // TagName gets the HTML element name (i.e. p, div) of the currently selected // element. TagName() (*ElementTagNameResponse, error) // Rectangle gets the dimensions and co-ordinates of the currently selected // element. Rectangle() (*ElementRectangleResponse, error) // Enabled gets whether or not the current selected elemented is enabled. Enabled() (*ElementEnabledResponse, error) // Click clicks the currently selected element. Please note, you may have to // implement your own wait to ensure the page actually navigates. This is due to // Selenium having no idea whether or not your click will be interrupted by JS. // Alternatively, you can use the WaitUntil(TitleEquals("title"), 20) to // automatically wait until the page title has changed. Click() (*ElementClickResponse, error) // Clear clears the currently selected element according to the specification. Clear() (*ElementClearResponse, error) // SendKeys sends a set of keystrokes to the currently selected element. SendKeys(keys string) (*ElementSendKeysResponse, error) } // Timeout is an interface which specifies what all timeout requests must follow. type Timeout interface { // Type is the type of the timeout that is being used. Type() string // Timeout is the timeout in milliseconds. Timeout() int } // By is an interface that defines what all 'ByX' methods must return. type By interface { // Type is the type of by (i.e. id, xpath, class, name, index). Type() string // Value is the actual value to retrieve something by (i.e. #test, 1). Value() interface{} }