package selenium
- Alphabetic
- Public
- All
Type Members
-
trait
Chrome extends WebBrowser with Driver with ScreenshotCapturer
WebBrowser
subtrait that defines an implicitWebDriver
for Chrome (anorg.openqa.selenium.chrome.ChromeDriver
). -
trait
Driver extends AnyRef
Trait declaring a
webDriver
field that enables tests to be abstracted across different kinds ofWebDriver
s.Trait declaring a
webDriver
field that enables tests to be abstracted across different kinds ofWebDriver
s.This trait enables you to place tests that you want to run in multiple browsers in a trait with a self type of
WebBrowser with Driver
, like this:trait MyBrowserTests { this: WebBrowser with Driver => // Your browser tests }
Then you can create concrete subclasses for each actual browser you want to run those tests in:
class MyBrowserTestsWithChrome extends MyBrowserTests with Chrome class MyBrowserTestsWithSafari extends MyBrowserTests with Safari class MyBrowserTestsWithInternetExplorer extends MyBrowserTests with InternetExplorer class MyBrowserTestsWithFirefox extends MyBrowserTests with Firefox
-
trait
Firefox extends WebBrowser with Driver with ScreenshotCapturer
WebBrowser
subtrait that defines an implicitWebDriver
for Firefox (anorg.openqa.selenium.firefox.FirefoxDriver
).WebBrowser
subtrait that defines an implicitWebDriver
for Firefox (anorg.openqa.selenium.firefox.FirefoxDriver
).The
FirefoxDriver
uses theFirefoxProfile
defined asfirefoxProfile
. By default this is just anew FirefoxProfile
. You can mutate this object to modify the profile, or overridefirefoxProfile
. -
trait
HtmlUnit extends WebBrowser with Driver with ScreenshotCapturer
WebBrowser
subtrait that defines an implicitWebDriver
for HTMLUnit (anorg.openqa.selenium.htmlunit.HtmlUnitDriver
), with JavaScript enabled by default.WebBrowser
subtrait that defines an implicitWebDriver
for HTMLUnit (anorg.openqa.selenium.htmlunit.HtmlUnitDriver
), with JavaScript enabled by default.Note: You can disable JavaScript with:
webDriver.setJavascriptEnabled(false)
-
trait
InternetExplorer extends WebBrowser with Driver with ScreenshotCapturer
WebBrowser
subtrait that defines an implicitWebDriver
for Internet Explorer (anorg.openqa.selenium.ie.InternetExplorerDriver
). -
trait
Page extends AnyRef
Trait that facilitates using the page object pattern with the ScalaTest Selenium DSL.
Trait that facilitates using the page object pattern with the ScalaTest Selenium DSL.
If you use the page object pattern, mixing trait
Page
into your page classes will allow you to use thego to
syntax with your page objects. Here's an example:class HomePage extends Page { val url = "localhost:9000/index.html" }
val homePage = new HomePage go to homePage -
trait
Safari extends WebBrowser with Driver with ScreenshotCapturer
WebBrowser
subtrait that defines an implicitWebDriver
for Safari (anorg.openqa.selenium.safari.SafariDriver
). -
trait
WebBrowser extends AnyRef
Trait that provides a domain specific language (DSL) for writing browser-based tests using Selenium.
Trait that provides a domain specific language (DSL) for writing browser-based tests using Selenium.
To use ScalaTest's Selenium DSL, mix trait
WebBrowser
into your test class. This trait provides the DSL in its entirety except for one missing piece: an implicitorg.openqa.selenium.WebDriver
. One way to provide the missing implicit driver is to declare one as a member of your test class, like this:import org.scalatest._ import selenium._ import org.openqa.selenium._ import htmlunit._
class BlogSpec extends FlatSpec with Matchers with WebBrowser {
implicit val webDriver: WebDriver = new HtmlUnitDriver
val host = "http://localhost:9000/"
"The blog app home page" should "have the correct title" in { go to (host + "index.html") pageTitle should be ("Awesome Blog") } }For convenience, however, ScalaTest provides a
WebBrowser
subtrait containing an implicitWebDriver
for each driver provided by Selenium. Thus a simpler way to use theHtmlUnit
driver, for example, is to extend ScalaTest'sHtmlUnit
trait, like this:import org.scalatest._ import selenium._
class BlogSpec extends FlatSpec with Matchers with HtmlUnit {
val host = "http://localhost:9000/"
"The blog app home page" should "have the correct title" in { go to (host + "index.html") pageTitle should be ("Awesome Blog") } }The web driver traits provided by ScalaTest are:
Driver WebBrowser
subtraitGoogle Chrome Chrome
Mozilla Firefox Firefox
HtmlUnit HtmlUnit
Microsoft Internet Explorer InternetExplorer
Apple Safari Safari
Navigation
You can ask the browser to retrieve a page (go to a URL) like this:
go to "http://www.artima.com"
Note: If you are using the page object pattern, you can also go to a page using the
Page
instance, as illustrated in the section on page objects below.Once you have retrieved a page, you can fill in and submit forms, query for the values of page elements, and make assertions. In the following example, selenium will go to
http://www.google.com
, fill in the text box withCheese!
, press the submit button, and wait for result returned from an AJAX call:go to "http://www.google.com" click on "q" enter("Cheese!") submit() // Google's search is rendered dynamically with JavaScript. eventually { pageTitle should be ("Cheese! - Google Search") }
In the above example, the
"q"
used in “click on "q"
” can be either the id or name of an element. ScalaTest's Selenium DSL will try to lookup by id first. If it cannot find any element with an id equal to"q"
, it will then try lookup by name"q"
.Alternatively, you can be more specific:
click on id("q") // to lookup by id "q" click on name("q") // to lookup by name "q"
In addition to
id
andname
, you can use the following approaches to lookup elements, just as you can do with Selenium'sorg.openqa.selenium.By
class:xpath
className
cssSelector
linkText
partialLinkText
tagName
For example, you can select by link text with:
click on linkText("click here!")
If an element is not found via any form of lookup, evaluation will complete abruptly with a
TestFailedException
.Getting and setting input element values
ScalaTest's Selenium DSL provides a clear, simple syntax for accessing and updating the values of input elements such as text fields, radio buttons, checkboxes, selection lists, and the input types introduced in HTML5. If a requested element is not found, or if it is found but is not of the requested type, an exception will immediately result causing the test to fail.
The most common way to access field value is through the
value
property, which is supported by the following input types:Tag Name Input Type Lookup Method input
text
textField
textarea
-
textArea
input
password
pwdField
input
email
emailField
input
color
colorField
input
date
dateField
input
datetime
dateTimeField
input
datetime-local
dateTimeLocalField
input
month
monthField
input
number
numberField
input
range
rangeField
input
search
searchField
input
tel
telField
input
time
timeField
input
url
urlField
input
week
weekField
You can change a input field's value by assigning it via the
=
operator, like this:textField("q").value = "Cheese!"
And you can access a input field's value by simply invoking
value
on it:textField("q").value should be ("Cheese!")
If the text field is empty,
value
will return an empty string (""
).You can use the same syntax with other type of input fields by replacing
textField
withLookup Method
listed in table above, for example to use text area:textArea("body").value = "I saw something cool today!" textArea("body").value should be ("I saw something cool today!")
or with a password field:
pwdField("secret").value = "Don't tell anybody!" pwdField("secret").value should be ("Don't tell anybody!")
Alternate Way for Data Entry
An alternate way to enter data into a input fields is to use
enter
orpressKeys
. Although both ofenter
andpressKeys
send characters to the active element,pressKeys
can be used on any kind of element, whereasenter
can only be used on text entry fields, which include:textField
textArea
pwdField
emailField
searchField
telField
urlField
Another difference is that
enter
will clear the text field or area before sending the characters, effectively replacing any currently existing text with the new text passed toenter
. By contrast,pressKeys
does not do any clearing—it just appends more characters to any existing text. You can backup withpressKeys
, however, by sending explicit backspace characters,"\u0008"
.To use these commands, you must first click on the input field you are interested in to give it the focus. Here's an example:
click on "q" enter("Cheese!")
Here's a (contrived) example of using
pressKeys
with backspace to fix a typo:click on "q" // q is the name or id of a text field or text area enter("Cheesey!") // Oops, meant to say Cheese! pressKeys("\u0008\u0008") // Send two backspaces; now the value is Cheese pressKeys("!") // Send the missing exclamation point; now the value is Cheese!
Radio buttons
Radio buttons work together in groups. For example, you could have a group of radio buttons, like this:
<input type="radio" id="opt1" name="group1" value="Option 1"> Option 1</input> <input type="radio" id="opt2" name="group1" value="Option 2"> Option 2</input> <input type="radio" id="opt3" name="group1" value="Option 3"> Option 3</input>
You can select an option in either of two ways:
radioButtonGroup("group1").value = "Option 2" radioButtonGroup("group1").selection = Some("Option 2")
Likewise, you can read the currently selected value of a group of radio buttons in two ways:
radioButtonGroup("group1").value should be ("Option 2") radioButtonGroup("group1").selection should be (Some("Option 2"))
If the radio button has no selection at all,
selection
will returnNone
whereasvalue
will throw aTestFailedException
. By usingvalue
, you are indicating you expect a selection, and if there isn't a selection that should result in a failed test.If you would like to work with
RadioButton
element directly, you can select it by callingradioButton
:click on radioButton("opt1")
you can check if an option is selected by calling
isSelected
:radioButton("opt1").isSelected should be (true)
to get the value of radio button, you can call
value
:radioButton("opt1").value should be ("Option 1")
Checkboxes
A checkbox in one of two states: selected or cleared. Here's how you select a checkbox:
checkbox("cbx1").select()
And here's how you'd clear one:
checkbox("cbx1").clear()
You can access the current state of a checkbox with
isSelected
:checkbox("cbx1").isSelected should be (true)
Single-selection dropdown lists
Given the following single-selection dropdown list:
<select id="select1"> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select>
You could select
Option 2
in either of two ways:singleSel("select1").value = "option2" singleSel("select1").selection = Some("option2")
To clear the selection, either invoke
clear
or setselection
toNone
:singleSel("select1").clear() singleSel("select1").selection = None
You can read the currently selected value of a single-selection list in the same manner as radio buttons:
singleSel("select1").value should be ("option2") singleSel("select1").selection should be (Some("option2"))
If the single-selection list has no selection at all,
selection
will returnNone
whereasvalue
will throw aTestFailedException
. By usingvalue
, you are indicating you expect a selection, and if there isn't a selection that should result in a failed test.Multiple-selection lists
Given the following multiple-selection list:
<select name="select2" multiple="multiple"> <option value="option4">Option 4</option> <option value="option5">Option 5</option> <option value="option6">Option 6</option> </select>
You could select
Option 5
andOption 6
like this:multiSel("select2").values = Seq("option5", "option6")
The previous command would essentially clear all selections first, then select
Option 5
andOption 6
. If instead you want to not clear any existing selection, just additionally selectOption 5
andOption 6
, you can use the+=
operator, like this.multiSel("select2").values += "option5" multiSel("select2").values += "option6"
To clear a specific option, pass its name to
clear
:multiSel("select2").clear("option5")
To clear all selections, call
clearAll
:multiSel("select2").clearAll()
You can access the current selections with
values
, which returns an immutableIndexedSeq[String]
:multiSel("select2").values should have size 2 multiSel("select2").values(0) should be ("option5") multiSel("select2").values(1) should be ("option6")
Clicking and submitting
You can click on any element with “
click on
” as shown previously:click on "aButton" click on name("aTextField")
If the requested element is not found,
click on
will throw an exception, failing the test.Clicking on a input element will give it the focus. If current focus is in on an input element within a form, you can submit the form by calling
submit
:submit()
Switching
You can switch to a popup alert bo using the following code:
switch to alertBox
to switch to a frame, you could:
switch to frame(0) // switch by index switch to frame("name") // switch by name
If you have reference to a window handle (can be obtained from calling windowHandle/windowHandles), you can switch to a particular window by:
switch to window(windowHandle)
You can also switch to active element and default content:
switch to activeElement switch to defaultContent
Navigation history
In real web browser, you can press the 'Back' button to go back to previous page. To emulate that action in your test, you can call
goBack
:goBack()
To emulate the 'Forward' button, you can call:
goForward()
And to refresh or reload the current page, you can call:
reloadPage()
Cookies!
To create a new cookie, you'll say:
add cookie ("cookie_name", "cookie_value")
to read a cookie value, you do:
cookie("cookie_name").value should be ("cookie_value") // If value is undefined, throws TFE right then and there. Never returns null.
In addition to the common use of name-value cookie, you can pass these extra fields when creating the cookie, available ways are:
cookie(name: String, value: String) cookie(name: String, value: String, path: String) cookie(name: String, value: String, path: String, expiry: Date) cookie(name: String, value: String, path: String, expiry: Date, domain: String) cookie(name: String, value: String, path: String, expiry: Date, domain: String, secure: Boolean)
and to read those extra fields:
cookie("cookie_name").value // Read cookie's value cookie("cookie_name").path // Read cookie's path cookie("cookie_name").expiry // Read cookie's expiry cookie("cookie_name").domain // Read cookie's domain cookie("cookie_name").isSecure // Read cookie's isSecure flag
In order to delete a cookie, you could use the following code:
delete cookie "cookie_name"
or to delete all cookies in the same domain:-
delete all cookies
To get the underlying Selenium cookie, you can use
underlying
:cookie("cookie_name").underlying.validate() // call the validate() method on underlying Selenium cookie
Other useful element properties
All element types (
textField
,textArea
,radioButton
,checkbox
,singleSel
,multiSel
) support the following useful properties:Method Description location
The XY location of the top-left corner of this Element
.size
The width/height size of this Element
.isDisplayed
Indicates whether this Element
is displayed.isEnabled
Indicates whether this Element
is enabled.isSelected
Indicates whether this Element
is selected.tagName
The tag name of this element. underlying
The underlying WebElement
wrapped by thisElement
.attribute(name: String)
The attribute value of the given attribute name of this element, wrapped in a Some
, orNone
if no such attribute exists on thisElement
.text
Returns the visible (i.e., not hidden by CSS) text of this element, including sub-elements, without any leading or trailing whitespace. Implicit wait
To set Selenium's implicit wait timeout, you can call the
implicitlyWait
method:implicitlyWait(Span(10, Seconds))
Invoking this method sets the amount of time the driver will wait when searching for an element that is not immediately present. For more information, see the documentation for method
implicitlyWait
.Page source and current URL
It is possible to get the html source of currently loaded page, using:
pageSource
and if needed, get the current URL of currently loaded page:
currentUrl
Screen capture
You can capture screen using the following code:
val file = capture
By default, the captured image file will be saved in temporary folder (returned by java.io.tmpdir property), with random file name ends with .png extension. You can specify a fixed file name:
capture to "MyScreenShot.png"
or
capture to "MyScreenShot"
Both will result in a same file name
MyScreenShot.png
.You can also change the target folder screenshot file is written to, by saying:
setCaptureDir("/home/your_name/screenshots")
If you want to capture a screenshot when something goes wrong (e.g. test failed), you can use
withScreenshot
:withScreenshot { assert("Gold" == "Silver", "Expected gold, but got silver") }
In case the test code fails, you'll see the screenshot location appended to the error message, for example:
Expected gold but got silver; screenshot capture in /tmp/AbCdEfGhIj.png
Using the page object pattern
If you use the page object pattern, mixing trait
Page
into your page classes will allow you to use thego to
syntax with your page objects. Here's an example:class HomePage extends Page { val url = "http://localhost:9000/index.html" }
val homePage = new HomePage go to homePageExecuting JavaScript
To execute arbitrary JavaScript, for example, to test some JavaScript functions on your page, pass it to
executeScript
:go to (host + "index.html") val result1 = executeScript("return document.title;") result1 should be ("Test Title") val result2 = executeScript("return 'Hello ' + arguments[0]", "ScalaTest") result2 should be ("Hello ScalaTest")
To execute an asynchronous bit of JavaScript, pass it to
executeAsyncScript
. You can set the script timeout withsetScriptTimeout
:val script = """ var callback = arguments[arguments.length - 1]; window.setTimeout(function() {callback('Hello ScalaTest')}, 500); """ setScriptTimeout(1 second) val result = executeAsyncScript(script) result should be ("Hello ScalaTest")
Querying for elements
You can query for arbitrary elements via
find
andfindAll
. Thefind
method returns the first matching element, wrapped in aSome
, orNone
if no element is found. ThefindAll
method returns an immutableIndexedSeq
of all matching elements. If no elements match the query,findAll
returns an emptyIndexedSeq
. These methods allow you to perform rich queries usingfor
expressions. Here are some examples:val ele: Option[Element] = find("q")
val eles: colection.immutable.IndexedSeq[Element] = findAll(className("small")) for (e <- eles; if e.tagName != "input") e should be ('displayed) val textFields = eles filter { tf.isInstanceOf[TextField] }Cleaning up
To close the current browser window, and exit the driver if the current window was the only one remaining, use
close
:close()
To close all windows, and exit the driver, use
quit
:quit()
Alternate forms
Although statements like “
delete all cookies
” fit well with matcher statements like “title should be ("Cheese!")
”, they do not fit as well with the simple method call form of assertions. If you prefer, you can avoid operator notation and instead use alternatives that take the form of plain-old method calls. Here's an example:goTo("http://www.google.com") clickOn("q") textField("q").value = "Cheese!" submit() // Google's search is rendered dynamically with JavaScript. eventually(assert(pageTitle === "Cheese! - Google Search"))
Here's a table showing the complete list of alternatives:
operator notation method call go to (host + "index.html")
goTo(host + "index.html")
click on "aButton"
clickOn("aButton")
switch to activeElement
switchTo(activeElement)
add cookie ("cookie_name", "cookie_value")
addCookie("cookie_name", "cookie_value")
delete cookie "cookie_name"
deleteCookie("cookie_name")
delete all cookies
deleteAllCookies()
capture to "MyScreenShot"
captureTo("MyScreenShot")
Value Members
-
object
Chrome extends Chrome
Companion object that facilitates the importing of
Chrome
members as an alternative to mixing it in.Companion object that facilitates the importing of
Chrome
members as an alternative to mixing it in. One use case is to importChrome
members so you can use them in the Scala interpreter. -
object
Firefox extends Firefox
Companion object that facilitates the importing of
Firefox
members as an alternative to mixing it in.Companion object that facilitates the importing of
Firefox
members as an alternative to mixing it in. One use case is to importFirefox
members so you can use them in the Scala interpreter. -
object
HtmlUnit extends HtmlUnit
Companion object that facilitates the importing of
HtmlUnit
members as an alternative to mixing it in.Companion object that facilitates the importing of
HtmlUnit
members as an alternative to mixing it in. One use case is to importHtmlUnit
members so you can use them in the Scala interpreter. -
object
InternetExplorer extends InternetExplorer
Companion object that facilitates the importing of
InternetExplorer
members as an alternative to mixing it in.Companion object that facilitates the importing of
InternetExplorer
members as an alternative to mixing it in. One use case is to importInternetExplorer
members so you can use them in the Scala interpreter. -
object
Safari extends Safari
Companion object that facilitates the importing of
Safari
members as an alternative to mixing it in.Companion object that facilitates the importing of
Safari
members as an alternative to mixing it in. One use case is to importSafari
members so you can use them in the Scala interpreter. -
object
WebBrowser extends WebBrowser
Companion object that facilitates the importing of
WebBrowser
members as an alternative to mixing it in.Companion object that facilitates the importing of
WebBrowser
members as an alternative to mixing it in. One use case is to importWebBrowser
members so you can use them in the Scala interpreter.