-
Notifications
You must be signed in to change notification settings - Fork 38
Getting started
# You have to include/import the Celerity library
require "rubygems"
require "celerity"
# Create a Browser object. Due to Watir compatibility Celerity::IE.new would also work.
# You can specify options, see HTTP://celerity.rubyforge.org/doc/classes/Celerity/IE.html#M000141
browser = Celerity::Browser.new
# Tell the browser object to go to HTTP://www.google.com
browser.goto('HTTP://www.google.com')
# Tell the browser object to find a text field with the name "q" and set the value to "Celerity"
browser.text_field(:name, 'q').value = 'Celerity'
# Tell the browser object to find a button with the name "btnG" and click it
browser.button(:name, 'btnG').click
# Output "yay" if the page we are on includes the text "celerity.rubyforge.org"
puts "yay" if browser.text.include? 'celerity.rubyforge.org'
Celerity is all about inspecting and manipulating HTML elements. However, before we can start with the fun stuff, we have to include/import Celerity and create a Browser object.
# You have to include/import the Celerity library
require "rubygems"
require "celerity"
# Create a Browser object
browser = Celerity::Browser.new
# Browse to HTTP://www.google.com
browser.goto('HTTP://www.google.com')
Only four lines of code, and we’re all set! Now, let’s talk about how we can find an element we want to inspect or manipulate.
The general syntax for finding an element is:
browser_object.element_method(how_parameter, what_parameter)
ie. browser.link(:text, "Next")
which means the first <a>
element with the text “Next”.
There’s an element method for each supported element or group of elements, i.e. link
, div
, table
, form
, text_field
, select_list
or button
. For a full list of supported elements, see List of supported elements.
Note that the how parameter is always a symbol, meaning it has a :
in front of it ;)
The how parameter is generally the HTML attribute you want to search by. To find a <form>
element with the id new_user_, you would do something like @browser.form(:id, "newuser"). To find the first frame with _name="main"_ you can do @browser.frame(:name, "main")
. To find the first table cell with a column span of 3 (<td colspan="3"></td>
), you’d do browser.cell(:colspan, "3")
.
In addition to search by attributes, Celerity has a few special how parameters.
The :text parameters searches the “inside” of the element. It ignores HTML markup, but includes all text.
<div id="ex1">
<a id="yo1" href="HTTP://www.google.com">Google</a>
</div>
<div id="ex2">
<a id="yo2" href="HTTP://www.google.com">Google<img src="google.png" /></a>
</div>
<div id="ex3">
<a id="yo3" href="HTTP://www.google.com">Google <span>The best search engine</span></a>
</div>
browser.div(:id, "ex1").link(:text, "Google").id # Would return "yo1"
browser.div(:id, "ex2").link(:text, "Google").id # Would return "yo2", the <img> is ignored
# Would not work, because even though the <span> and </span> tags are ignored, the text inside of them is not.
# You can verify this by doing browser.link(:id, "yo3").text which returns "Google The best search engine"
browser.div(:id, "ex3").link(:text, "Google").id
The :index how parameter is very simple and extremely useful. It just allows you to get the nth element. browser.li(:index, 4)
means the 4th <li>
element on the page.
The :xpath how parameter let’s you use XPath (XML Path Language) to find an element.
browser.option(:xpath, "//option[@id='nor']")
The simple (but not very useful) example above would select the first <option>
element with the id nor.
- XPath on Wikipedia: http://en.wikipedia.org/wiki/XPath
- XPath tutorial: http://www.w3schools.com/xpath/default.asp
- XPath reference: http://www.w3schools.com/xpath/xpath_functions.asp
The what parameter is what you want to find, and for almost all how parameters it can be both a string or a regular expression, e.g. browser.p(:id, "lead")
which means the first <p>
element with id lead, or browser.link(:text, /ish/)
which means the first <a>
element that matches the regular expression /ish/
The exceptions:
-
:xpath
must be a string -
:index
must be an integer
You can nest the element methods to find element(s) inside another element.
<body>
<div>
<div id="content">
<p class="lead">Lead in.</p>
</div>
</div>
</body>
browser.div(:index, 1).div(:id, "content").p(:class, "lead").text
The example above would return “Lead in.”.
Celerity also supports searching by multiple criteria. Just use a hash:
criteria = {:class => "promo", :index => 4}
browser.div(criteria)
# or
browser.div({:class => "promo", :index => 4})
# or
browser.div(:class => "promo", :index => 4)
The example above locates the 4th <div>
element with the class of promo.
All supported HTML elements has their own collection method, e.g. spans
, forms
, lis
, tables
, h1s
and divs
. For a full list of supported elements, see the List of supported elements.
require "rubygems"
require "celerity"
browser = Celerity::Browser.new
browser.goto('HTTP://www.google.com')
puts browser.buttons
The example above produces something like:
tag: input
name: btnG
type: submit
value: Google Search
text: Google Search
tag: input
name: btnI
type: submit
value: I'm Feeling Lucky
text: I'm Feeling Lucky
Collection methods includes Enumerable, so you can call methods like each
, each_with_index
, select
and collect
on them. If you want to loop through all <form>
elements, you can do something like this:
browser.forms.each do |form|
puts form
end
If you want all <li>
elements that has an id that ends with ish, you could do:
li_elements = browser.lis.select { |li| li.id =~ /ish$/ }
In Celerity you can inspect all HTML attributes just by calling a method with the same name as the attribute you want. If the attribute doesn’t exist, the method will return an empty string, "".
browser.div(:index, 1).id # Returns the id attribute of the first <div> element
browser.form(:index, 1).name # Returns the name attribute of the first <form> element
browser.text_field(:id, "phone").maxlength # Returns the maxlength attribute of the first text field that has id="phone"
browser.div(:index, 1).class # Won't work as expected. See next paragraph.
However, there are some special cases:
browser.div(:index, 1).class_name # Since #class is an instance method in the Ruby Object class, we can't use it. You must use #class_name instead.
browser.div(:index, 1).text # Returns the text inside the element recursively
browser.text_field(:index, 1).type # Return the type attribute, but if the type attribute is missing or invalid, it will return "text" (conforming with the HTML standards)
The most common actions are
- Clicking a link
- Clicking a button
- Typing something in a text field
- Selecting something from a select list
# Clicks the first link that has a href attribute that matches the regular expression /delete_user\.jsp/
browser.link(:href, /delete_user\.jsp/).click
# Clicks the first button that has value="Click it"
browser.button(:value, "Click it").click
# Inputs "smith123" into the first text field that has id="username"
browser.text_field(:id, "username").value = "smith123"
# Types "smith123" into the first text field that has id="username" and triggers Javascript events after each character
browser.text_field(:id, "username").set("smith123")
Fun fact: The first method is more than six times faster than the second method, using a 10 byte string.
# Selects the Norway option from the first select list with id="country"
browser.select_list(:id, "country").select("Norway")
As each Ajax call runs in it’s own thread, the browser can’t (and shouldn’t) wait for it to finish. However, this sometimes causes problems in automated web testing. This is a typical example:
<form method="post" action="new_user.aspx">
<fieldset>
<select name="country" id="country" onchange="javascript:someAjaxCallThatUpdatesCountyList();">
<option>-- Choose a country</option>
<option>Norway</option>
<option>Sweden</option>
</select>
<select name="county" id="county">
<option>-- Choose a county</option>
</select>
<input type="submit" name="submit" id="submit" />
</fieldset>
</form>
When you select a country, an Ajax call is made with the purpose of updating the county list. If you wanted to use Celerity to submit this form you could do something like this:
require "rubygems"
require "celerity"
browser = Celerity::Browser.new
browser.goto('example.htm')
browser.select_list(:id, "country").select("Norway")
browser.select_list(:id, "county").option(:text, "Oslo").select # There are many equivalent ways to select an option, so don't be afraid if this looks unfamiliar
browser.button(:id, "submit").click
However, if you run this script, you might see something like this:
Celerity::Exception::UnknownObjectException in ...
Unable to locate object, using :text and "Oslo"
The Ajax call is not finished, therefore the select list has not been updated with the proper counties.
See this page
One solution is to wait until it exists, or more precisely; keep checking if it exists until it does – then stop checking and continue.
require "rubygems"
require "celerity"
browser = Celerity::Browser.new
browser.goto('example.htm')
browser.select_list(:id, "country").select("Norway")
sleep(0.1) until browser.select_list(:id, "county").option(:text, "Oslo").exists # Wait until it exists
browser.select_list(:id, "county").option(:text, "Oslo").select
browser.button(:id, "submit").click