warnold-selenium-client 1.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +338 -0
- data/examples/rspec/google_spec.rb +41 -0
- data/examples/script/google.rb +25 -0
- data/examples/testunit/google_test.rb +39 -0
- data/lib/nautilus/shell.rb +34 -0
- data/lib/selenium.rb +14 -0
- data/lib/selenium/client.rb +27 -0
- data/lib/selenium/client/base.rb +118 -0
- data/lib/selenium/client/driver.rb +11 -0
- data/lib/selenium/client/extensions.rb +118 -0
- data/lib/selenium/client/idiomatic.rb +488 -0
- data/lib/selenium/client/javascript_expression_builder.rb +116 -0
- data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
- data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
- data/lib/selenium/client/legacy_driver.rb +1711 -0
- data/lib/selenium/client/protocol.rb +104 -0
- data/lib/selenium/client/selenium_helper.rb +34 -0
- data/lib/selenium/command_error.rb +4 -0
- data/lib/selenium/protocol_error.rb +4 -0
- data/lib/selenium/rake/default_tasks.rb +17 -0
- data/lib/selenium/rake/remote_control_start_task.rb +71 -0
- data/lib/selenium/rake/remote_control_stop_task.rb +44 -0
- data/lib/selenium/rake/tasks.rb +6 -0
- data/lib/selenium/remote_control/remote_control.rb +35 -0
- data/lib/selenium/rspec/reporting/file_path_strategy.rb +78 -0
- data/lib/selenium/rspec/reporting/html_report.rb +155 -0
- data/lib/selenium/rspec/reporting/selenium_test_report_formatter.rb +88 -0
- data/lib/selenium/rspec/reporting/system_capture.rb +72 -0
- data/lib/selenium/rspec/rspec_extensions.rb +104 -0
- data/lib/selenium/rspec/spec_helper.rb +34 -0
- data/lib/tcp_socket_extension.rb +32 -0
- data/test/all_unit_tests.rb +3 -0
- metadata +102 -0
data/lib/selenium.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Legacy helper providing backward compatibility
|
2
|
+
|
3
|
+
# -----------------
|
4
|
+
# Original code by Aslak Hellesoy and Darren Hobbs
|
5
|
+
# This file has been automatically generated via XSL
|
6
|
+
# -----------------
|
7
|
+
|
8
|
+
require File.expand_path(File.dirname(__FILE__) + '/selenium/client')
|
9
|
+
|
10
|
+
# Backward compatibility
|
11
|
+
|
12
|
+
SeleniumHelper = Selenium::Client::SeleniumHelper
|
13
|
+
SeleniumCommandError = Selenium::CommandError
|
14
|
+
Selenium::SeleniumDriver = Selenium::Client::Driver
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#
|
2
|
+
# Helper requiring the basic selenium-client API (no RSpec goodness)
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'net/http'
|
6
|
+
require 'uri'
|
7
|
+
require 'cgi'
|
8
|
+
require "digest/md5"
|
9
|
+
require 'fileutils'
|
10
|
+
require 'tmpdir'
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/../tcp_socket_extension')
|
12
|
+
require File.expand_path(File.dirname(__FILE__) + '/../nautilus/shell')
|
13
|
+
require File.expand_path(File.dirname(__FILE__) + '/command_error')
|
14
|
+
require File.expand_path(File.dirname(__FILE__) + '/protocol_error')
|
15
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/protocol')
|
16
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/legacy_driver')
|
17
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/javascript_expression_builder')
|
18
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/javascript_frameworks/prototype')
|
19
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/javascript_frameworks/jquery')
|
20
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/extensions')
|
21
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/idiomatic')
|
22
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/base')
|
23
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/driver')
|
24
|
+
require File.expand_path(File.dirname(__FILE__) + '/client/selenium_helper')
|
25
|
+
require File.expand_path(File.dirname(__FILE__) + '/remote_control/remote_control')
|
26
|
+
require File.expand_path(File.dirname(__FILE__) + '/rake/remote_control_start_task')
|
27
|
+
require File.expand_path(File.dirname(__FILE__) + '/rake/remote_control_stop_task')
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Selenium
|
2
|
+
module Client
|
3
|
+
|
4
|
+
# Driver constructor and session management commands
|
5
|
+
module Base
|
6
|
+
include Selenium::Client::Protocol
|
7
|
+
include Selenium::Client::GeneratedDriver
|
8
|
+
include Selenium::Client::Extensions
|
9
|
+
include Selenium::Client::Idiomatic
|
10
|
+
|
11
|
+
attr_reader :host, :port, :browser_string, :browser_url,
|
12
|
+
:default_timeout_in_seconds,
|
13
|
+
:default_javascript_framework,
|
14
|
+
:highlight_located_element_by_default
|
15
|
+
|
16
|
+
#
|
17
|
+
# Create a new client driver
|
18
|
+
#
|
19
|
+
# Example:
|
20
|
+
#
|
21
|
+
# Selenium::Client::Driver.new \
|
22
|
+
# :host => "localhost",
|
23
|
+
# :port => 4444,
|
24
|
+
# :browser => "*firefox",
|
25
|
+
# :timeout_in_seconds => 10,
|
26
|
+
# :url => "http://localhost:3000",
|
27
|
+
#
|
28
|
+
# You can also set the default javascript framework used for :wait_for
|
29
|
+
# AJAX and effects semantics (:prototype is the default value):
|
30
|
+
#
|
31
|
+
# Selenium::Client::Driver.new \
|
32
|
+
# :host => "localhost",
|
33
|
+
# :port => 4444,
|
34
|
+
# :browser => "*firefox",
|
35
|
+
# :timeout_in_seconds => 10,
|
36
|
+
# :url => "http://localhost:3000",
|
37
|
+
# :javascript_framework => :jquery
|
38
|
+
#
|
39
|
+
# You can also enables automatic highlighting of located elements
|
40
|
+
# by passing the highlight_located_element option, e.g.
|
41
|
+
#
|
42
|
+
# Selenium::Client::Driver.new \
|
43
|
+
# :host => "localhost",
|
44
|
+
# :port => 4444,
|
45
|
+
# :browser => "*firefox",
|
46
|
+
# :highlight_located_element => true
|
47
|
+
#
|
48
|
+
def initialize(*args)
|
49
|
+
if args[0].kind_of?(Hash)
|
50
|
+
options = args[0]
|
51
|
+
@host = options[:host]
|
52
|
+
@port = options[:port].to_i
|
53
|
+
@browser_string = options[:browser]
|
54
|
+
@browser_url = options[:url]
|
55
|
+
@default_timeout_in_seconds = (options[:timeout_in_seconds] || 300).to_i
|
56
|
+
@default_javascript_framework = options[:javascript_framework] || :prototype
|
57
|
+
@highlight_located_element_by_default = options[:highlight_located_element] || false
|
58
|
+
else
|
59
|
+
@host = args[0]
|
60
|
+
@port = args[1].to_i
|
61
|
+
@browser_string = args[2]
|
62
|
+
@browser_url = args[3]
|
63
|
+
@default_timeout_in_seconds = (args[4] || 300).to_i
|
64
|
+
@default_javascript_framework = :prototype
|
65
|
+
@highlight_located_element_by_default = false
|
66
|
+
end
|
67
|
+
|
68
|
+
@extension_js = ""
|
69
|
+
@session_id = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def session_started?
|
73
|
+
not @session_id.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
# Starts a new browser session (launching a new browser matching
|
77
|
+
# configuration provided at driver creation time).
|
78
|
+
#
|
79
|
+
# Browser session specific option can also be provided. e.g.
|
80
|
+
#
|
81
|
+
# driver.start_new_browser_session(:captureNetworkTraffic => true)
|
82
|
+
#
|
83
|
+
def start_new_browser_session(options={})
|
84
|
+
options_as_string = options.collect {|key,value| "#{key.to_s}=#{value.to_s}"}.sort.join(";")
|
85
|
+
result = string_command "getNewBrowserSession", [@browser_string, @browser_url, @extension_js, options_as_string]
|
86
|
+
@session_id = result
|
87
|
+
# Consistent timeout on the remote control and driver side.
|
88
|
+
# Intuitive and this is what you want 90% of the time
|
89
|
+
self.remote_control_timeout_in_seconds = @default_timeout_in_seconds
|
90
|
+
self.highlight_located_element = true if highlight_located_element_by_default
|
91
|
+
end
|
92
|
+
|
93
|
+
def close_current_browser_session
|
94
|
+
remote_control_command "testComplete" if @session_id
|
95
|
+
@session_id = nil
|
96
|
+
end
|
97
|
+
|
98
|
+
def start
|
99
|
+
start_new_browser_session
|
100
|
+
end
|
101
|
+
|
102
|
+
def stop
|
103
|
+
close_current_browser_session
|
104
|
+
end
|
105
|
+
|
106
|
+
def chrome_backend?
|
107
|
+
["*chrome", "*firefox", "*firefox2", "*firefox3"].include?(@browser_string)
|
108
|
+
end
|
109
|
+
|
110
|
+
def javascript_extension=(new_javascript_extension)
|
111
|
+
@extension_js = new_javascript_extension
|
112
|
+
end
|
113
|
+
alias :set_extension_js :javascript_extension=
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Selenium
|
2
|
+
module Client
|
3
|
+
|
4
|
+
# Convenience methods not explicitely part of the protocol
|
5
|
+
module Extensions
|
6
|
+
|
7
|
+
# These for all Ajax request to finish (Only works if you are using prototype, the wait happens in the browser)
|
8
|
+
#
|
9
|
+
# See http://davidvollbracht.com/2008/6/4/30-days-of-tech-day-3-waitforajax for
|
10
|
+
# more background.
|
11
|
+
def wait_for_ajax(options={})
|
12
|
+
builder = JavascriptExpressionBuilder.new active_javascript_framework(options)
|
13
|
+
wait_for_condition builder.no_pending_ajax_requests.script,
|
14
|
+
options[:timeout_in_seconds]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Wait for all Prototype effects to be processed (the wait happens in the browser).
|
18
|
+
#
|
19
|
+
# Credits to http://github.com/brynary/webrat/tree/master
|
20
|
+
def wait_for_effects(options={})
|
21
|
+
builder = JavascriptExpressionBuilder.new active_javascript_framework(options)
|
22
|
+
wait_for_condition builder.no_pending_effects.script,
|
23
|
+
options[:timeout_in_seconds]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Wait for an element to be present (the wait happens in the browser).
|
27
|
+
def wait_for_element(locator, options={})
|
28
|
+
builder = JavascriptExpressionBuilder.new
|
29
|
+
builder.find_element(locator).append("element != null;")
|
30
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Wait for an element to NOT be present (the wait happens in the browser).
|
34
|
+
def wait_for_no_element(locator, options={})
|
35
|
+
builder = JavascriptExpressionBuilder.new
|
36
|
+
builder.find_element(locator).append("element == null;")
|
37
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Wait for some text to be present (the wait is happening browser side).
|
41
|
+
#
|
42
|
+
# wait_for_text will search for the given argument within the innerHTML
|
43
|
+
# of the current DOM. Note that this method treats a single string
|
44
|
+
# as a special case.
|
45
|
+
#
|
46
|
+
# ==== Parameters
|
47
|
+
# wait_for_text accepts an optional hash of parameters:
|
48
|
+
# * <tt>:element</tt> - a selenium locator for an element limiting
|
49
|
+
# the search scope.
|
50
|
+
# * <tt>:timeout_in_seconds</tt> - duration in seconds after which we
|
51
|
+
# time out if text cannot be found.
|
52
|
+
#
|
53
|
+
# ==== Regular Expressions
|
54
|
+
# In addition to plain strings, wait_for_text accepts regular expressions
|
55
|
+
# as the pattern specification.
|
56
|
+
#
|
57
|
+
# ==== Examples
|
58
|
+
# The following are equivalent, and will match "some text" anywhere
|
59
|
+
# within the document:
|
60
|
+
# wait_for_text "some text"
|
61
|
+
# wait_for_text /some text/
|
62
|
+
#
|
63
|
+
# This will match "some text" anywhere within the specified element:
|
64
|
+
# wait_for_text /some text/, :element => "container"
|
65
|
+
#
|
66
|
+
# This will match "some text" only if it exactly matches the complete
|
67
|
+
# innerHTML of the specified element:
|
68
|
+
# wait_for_text "some text", :element => "container"
|
69
|
+
#
|
70
|
+
def wait_for_text(pattern, options={})
|
71
|
+
builder = JavascriptExpressionBuilder.new
|
72
|
+
builder.find_text(pattern, options).append("text_match == true;")
|
73
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Wait for some text to NOT be present (the wait happens in the browser).
|
77
|
+
#
|
78
|
+
# See wait_for_text for usage details.
|
79
|
+
def wait_for_no_text(pattern, options={})
|
80
|
+
builder = JavascriptExpressionBuilder.new
|
81
|
+
builder.find_text(pattern, options).append("text_match == false;")
|
82
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Wait for a field to get a specific value (the wait happens in the browser).
|
86
|
+
def wait_for_field_value(locator, expected_value, options={})
|
87
|
+
builder = JavascriptExpressionBuilder.new
|
88
|
+
builder.find_element(locator).element_value_is(expected_value)
|
89
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Wait for a field to not have a specific value (the wait happens in the browser).
|
93
|
+
def wait_for_no_field_value(locator, expected_value, options={})
|
94
|
+
builder = JavascriptExpressionBuilder.new
|
95
|
+
builder.find_element(locator).element_value_is_not(expected_value)
|
96
|
+
wait_for_condition builder.script, options[:timeout_in_seconds]
|
97
|
+
end
|
98
|
+
|
99
|
+
# Wait for something to be visible (the wait happens in the browser).
|
100
|
+
def wait_for_visible(locator, options={})
|
101
|
+
builder = JavascriptExpressionBuilder.new
|
102
|
+
wait_for_condition builder.visible(locator).script, options[:timeout_in_seconds]
|
103
|
+
end
|
104
|
+
|
105
|
+
# Wait for something to not be visible (the wait happens in the browser).
|
106
|
+
def wait_for_not_visible(locator, options={})
|
107
|
+
builder = JavascriptExpressionBuilder.new
|
108
|
+
wait_for_condition builder.not_visible(locator).script, options[:timeout_in_seconds]
|
109
|
+
end
|
110
|
+
|
111
|
+
def active_javascript_framework(options)
|
112
|
+
options[:javascript_framework] || default_javascript_framework
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,488 @@
|
|
1
|
+
module Selenium
|
2
|
+
module Client
|
3
|
+
|
4
|
+
# Provide a more idiomatic API than the generated Ruby driver.
|
5
|
+
#
|
6
|
+
# Work in progress...
|
7
|
+
module Idiomatic
|
8
|
+
|
9
|
+
# Return the text content of an HTML element (rendered text shown to
|
10
|
+
# the user). Works for any HTML element that contains text.
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# This command uses either the textContent (Mozilla-like browsers)
|
14
|
+
# or the innerText (IE-like browsers) of the element, which is the
|
15
|
+
# rendered text shown to the user.
|
16
|
+
#
|
17
|
+
# * 'locator' is an Selenium element locator
|
18
|
+
#
|
19
|
+
def text(locator)
|
20
|
+
string_command "getText", [locator,]
|
21
|
+
end
|
22
|
+
alias :text_content :text
|
23
|
+
|
24
|
+
# Return the title of the current HTML page.
|
25
|
+
def title
|
26
|
+
string_command "getTitle"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the absolute URL of the current page.
|
30
|
+
def location
|
31
|
+
string_command "getLocation"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Waits for a new page to load.
|
35
|
+
#
|
36
|
+
# Selenium constantly keeps track of new pages loading, and sets a
|
37
|
+
# "newPageLoaded" flag when it first notices a page load. Running
|
38
|
+
# any other Selenium command after turns the flag to false. Hence,
|
39
|
+
# if you want to wait for a page to load, you must wait immediately
|
40
|
+
# after a Selenium command that caused a page-load.
|
41
|
+
#
|
42
|
+
# * 'timeout_in_seconds' is a timeout in seconds, after which this
|
43
|
+
# command will return with an error
|
44
|
+
def wait_for_page(timeout_in_seconds=nil)
|
45
|
+
remote_control_command "waitForPageToLoad",
|
46
|
+
[actual_timeout_in_milliseconds(timeout_in_seconds),]
|
47
|
+
end
|
48
|
+
alias_method :wait_for_page_to_load, :wait_for_page
|
49
|
+
|
50
|
+
# Waits for a popup window to appear and load up.
|
51
|
+
#
|
52
|
+
# window_id is the JavaScript window "name" of the window that will appear (not the text of the title bar)
|
53
|
+
# timeout_in_seconds is a timeout in seconds, after which the action will return with an error
|
54
|
+
def wait_for_popup(window_id, timeout_in_seconds=nil)
|
55
|
+
remote_control_command "waitForPopUp",
|
56
|
+
[window_id, actual_timeout_in_milliseconds(timeout_in_seconds) ,]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Flexible wait semantics. ait is happening browser side. Useful for testing AJAX application.
|
60
|
+
#
|
61
|
+
# * wait :wait_for => :page # will wait for a new page to load
|
62
|
+
# * wait :wait_for => :popup, :window => 'a window id' # will wait for a new popup window to appear. Also selects the popup window for you provide `:select => true`
|
63
|
+
# * wait :wait_for => :ajax # will wait for all ajax requests to be completed using semantics of default javascript framework
|
64
|
+
# * wait :wait_for => :ajax, :javascript_framework => :jquery # will wait for all ajax requests to be completed overriding default javascript framework
|
65
|
+
# * wait :wait_for => :effects # will wait for all javascript effects to be rendered using semantics of default javascript framework
|
66
|
+
# * wait :wait_for => :effects, :javascript_framework => :prototype # will wait for all javascript effects to be rendered overriding default javascript framework
|
67
|
+
# * wait :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
68
|
+
# * wait :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
69
|
+
# * wait :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
70
|
+
# * wait :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
|
71
|
+
# * wait :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
|
72
|
+
# * wait :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
73
|
+
# * wait :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
|
74
|
+
# * wait :wait_for => :no_text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to not be 'some text'
|
75
|
+
# * wait :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
|
76
|
+
# * wait :wait_for => :no_value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to not be 'some value'
|
77
|
+
# * wait :wait_for => :visible, :element => 'a_locator' # will wait for element to be visible
|
78
|
+
# * wait :wait_for => :not_visible, :element => 'a_locator' # will wait for element to not be visible
|
79
|
+
# * wait :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
|
80
|
+
#
|
81
|
+
# Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
|
82
|
+
# is used.
|
83
|
+
def wait_for(options)
|
84
|
+
if options[:wait_for] == :page
|
85
|
+
wait_for_page options[:timeout_in_seconds]
|
86
|
+
elsif options[:wait_for] == :ajax
|
87
|
+
wait_for_ajax options
|
88
|
+
elsif options[:wait_for] == :element
|
89
|
+
wait_for_element options[:element], options
|
90
|
+
elsif options[:wait_for] == :no_element
|
91
|
+
wait_for_no_element options[:element], options
|
92
|
+
elsif options[:wait_for] == :text
|
93
|
+
wait_for_text options[:text], options
|
94
|
+
elsif options[:wait_for] == :no_text
|
95
|
+
wait_for_no_text options[:text], options
|
96
|
+
elsif options[:wait_for] == :effects
|
97
|
+
wait_for_effects options
|
98
|
+
elsif options[:wait_for] == :popup
|
99
|
+
wait_for_popup options[:window], options[:timeout_in_seconds]
|
100
|
+
select_window options[:window] if options[:select]
|
101
|
+
elsif options[:wait_for] == :value
|
102
|
+
wait_for_field_value options[:element], options[:value], options
|
103
|
+
elsif options[:wait_for] == :no_value
|
104
|
+
wait_for_no_field_value options[:element], options[:value], options
|
105
|
+
elsif options[:wait_for] == :visible
|
106
|
+
wait_for_visible options[:element], options
|
107
|
+
elsif options[:wait_for] == :not_visible
|
108
|
+
wait_for_not_visible options[:element], options
|
109
|
+
elsif options[:wait_for] == :condition
|
110
|
+
wait_for_condition options[:javascript], options[:timeout_in_seconds]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Gets the entire text of the page.
|
115
|
+
def body_text
|
116
|
+
string_command "getBodyText"
|
117
|
+
end
|
118
|
+
|
119
|
+
# Clicks on a link, button, checkbox or radio button.
|
120
|
+
#
|
121
|
+
# 'locator' is an element locator
|
122
|
+
#
|
123
|
+
# Using 'options' you can automatically wait for an event to happen after the
|
124
|
+
# click. e.g.
|
125
|
+
#
|
126
|
+
# * click "a_locator", :wait_for => :page # will wait for a new page to load
|
127
|
+
# * click "a_locator", :wait_for => :popup, :window => 'a window id' # will wait for a new popup window to appear. Also selects the popup window for you provide `:select => true`
|
128
|
+
# * click "a_locator", :wait_for => :ajax # will wait for all ajax requests to be completed using semantics of default javascript framework
|
129
|
+
# * click "a_locator", :wait_for => :ajax, :javascript_framework => :jquery # will wait for all ajax requests to be completed overriding default javascript framework
|
130
|
+
# * click "a_locator", :wait_for => :effects # will wait for all javascript effects to be rendered using semantics of default javascript framework
|
131
|
+
# * click "a_locator", :wait_for => :effects, :javascript_framework => :prototype # will wait for all javascript effects to be rendered overriding default javascript framework
|
132
|
+
# * click "a_locator", :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
133
|
+
# * click "a_locator", :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
134
|
+
# * click "a_locator", :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
135
|
+
# * click "a_locator", :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
|
136
|
+
# * click "a_locator", :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
|
137
|
+
# * click "a_locator", :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
138
|
+
# * click "a_locator", :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
|
139
|
+
# * click "a_locator", :wait_for => :no_text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to not be 'some text'
|
140
|
+
# * click "a_locator", :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
|
141
|
+
# * click "a_locator", :wait_for => :no_value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to not be 'some value'
|
142
|
+
# * click "a_locator", :wait_for => :visible, :element => 'a_locator' # will wait for element to be visible
|
143
|
+
# * click "a_locator", :wait_for => :not_visible, :element => 'a_locator' # will wait for element to not be visible
|
144
|
+
# * click "a_locator", :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
|
145
|
+
#
|
146
|
+
# Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
|
147
|
+
# is used.
|
148
|
+
def click(locator, options={})
|
149
|
+
remote_control_command "click", [locator,]
|
150
|
+
wait_for options
|
151
|
+
end
|
152
|
+
|
153
|
+
# Verifies that the specified text pattern appears somewhere on the rendered page shown to the user.
|
154
|
+
#
|
155
|
+
# * 'pattern' is a pattern to match with the text of the page
|
156
|
+
def text?(pattern)
|
157
|
+
boolean_command "isTextPresent", [pattern,]
|
158
|
+
end
|
159
|
+
|
160
|
+
# Verifies that the specified element is somewhere on the page.
|
161
|
+
#
|
162
|
+
# * 'locator' is an element locator
|
163
|
+
def element?(locator)
|
164
|
+
boolean_command "isElementPresent", [locator,]
|
165
|
+
end
|
166
|
+
|
167
|
+
# Determines if the specified element is visible. An
|
168
|
+
# element can be rendered invisible by setting the CSS "visibility"
|
169
|
+
# property to "hidden", or the "display" property to "none", either for the
|
170
|
+
# element itself or one if its ancestors. This method will fail if
|
171
|
+
# the element is not present.
|
172
|
+
#
|
173
|
+
# 'locator' is an element locator
|
174
|
+
def visible?(locator)
|
175
|
+
boolean_command "isVisible", [locator,]
|
176
|
+
end
|
177
|
+
|
178
|
+
# Gets the (whitespace-trimmed) value of an input field
|
179
|
+
# (or anything else with a value parameter).
|
180
|
+
# For checkbox/radio elements, the value will be "on" or "off"
|
181
|
+
# depending on whether the element is checked or not.
|
182
|
+
#
|
183
|
+
# * 'locator' is an element locator
|
184
|
+
def field(locator)
|
185
|
+
string_command "getValue", [locator,]
|
186
|
+
end
|
187
|
+
|
188
|
+
# Alias for +field+
|
189
|
+
def value(locator)
|
190
|
+
field locator
|
191
|
+
end
|
192
|
+
|
193
|
+
# Returns whether a toggle-button (checkbox/radio) is checked.
|
194
|
+
# Fails if the specified element doesn't exist or isn't a toggle-button.
|
195
|
+
#
|
196
|
+
# * 'locator' is an element locator pointing to a checkbox or radio button
|
197
|
+
def checked?(locator)
|
198
|
+
boolean_command "isChecked", [locator,]
|
199
|
+
end
|
200
|
+
|
201
|
+
# Whether an alert occurred
|
202
|
+
def alert?
|
203
|
+
boolean_command "isAlertPresent"
|
204
|
+
end
|
205
|
+
|
206
|
+
# Retrieves the message of a JavaScript alert generated during the previous action,
|
207
|
+
# or fail if there were no alerts.
|
208
|
+
#
|
209
|
+
# Getting an alert has the same effect as manually clicking OK. If an
|
210
|
+
# alert is generated but you do not consume it with getAlert, the next Selenium action
|
211
|
+
# will fail.
|
212
|
+
#
|
213
|
+
# Under Selenium, JavaScript alerts will NOT pop up a visible alert
|
214
|
+
# dialog.
|
215
|
+
#
|
216
|
+
# Selenium does NOT support JavaScript alerts that are generated in a
|
217
|
+
# page's onload() event handler. In this case a visible dialog WILL be
|
218
|
+
# generated and Selenium will hang until someone manually clicks OK.
|
219
|
+
#
|
220
|
+
def alert
|
221
|
+
string_command "getAlert"
|
222
|
+
end
|
223
|
+
|
224
|
+
# Whether a confirmation has been auto-acknoledged (i.e. confirm() been called)
|
225
|
+
def confirmation?
|
226
|
+
boolean_command "isConfirmationPresent"
|
227
|
+
end
|
228
|
+
|
229
|
+
# Retrieves the message of a JavaScript confirmation dialog generated during
|
230
|
+
# the previous action.
|
231
|
+
#
|
232
|
+
# By default, the confirm function will return true, having the same effect
|
233
|
+
# as manually clicking OK. This can be changed by prior execution of the
|
234
|
+
# chooseCancelOnNextConfirmation command.
|
235
|
+
#
|
236
|
+
# If an confirmation is generated but you do not consume it with getConfirmation,
|
237
|
+
# the next Selenium action will fail.
|
238
|
+
#
|
239
|
+
# NOTE: under Selenium, JavaScript confirmations will NOT pop up a visible
|
240
|
+
# dialog.
|
241
|
+
#
|
242
|
+
# NOTE: Selenium does NOT support JavaScript confirmations that are
|
243
|
+
# generated in a page's onload() event handler. In this case a visible
|
244
|
+
# dialog WILL be generated and Selenium will hang until you manually click
|
245
|
+
# OK.
|
246
|
+
def confirmation
|
247
|
+
string_command "getConfirmation"
|
248
|
+
end
|
249
|
+
|
250
|
+
# Whether a prompt occurred
|
251
|
+
def prompt?
|
252
|
+
boolean_command "isPromptPresent"
|
253
|
+
end
|
254
|
+
|
255
|
+
# Retrieves the message of a JavaScript question prompt dialog generated during
|
256
|
+
# the previous action.
|
257
|
+
#
|
258
|
+
# Successful handling of the prompt requires prior execution of the
|
259
|
+
# answerOnNextPrompt command. If a prompt is generated but you
|
260
|
+
# do not get/verify it, the next Selenium action will fail.
|
261
|
+
#
|
262
|
+
# NOTE: under Selenium, JavaScript prompts will NOT pop up a visible
|
263
|
+
# dialog.
|
264
|
+
#
|
265
|
+
# NOTE: Selenium does NOT support JavaScript prompts that are generated in a
|
266
|
+
# page's onload() event handler. In this case a visible dialog WILL be
|
267
|
+
# generated and Selenium will hang until someone manually clicks OK.
|
268
|
+
def prompt
|
269
|
+
string_command "getPrompt"
|
270
|
+
end
|
271
|
+
|
272
|
+
# Returns the result of evaluating the specified JavaScript snippet whithin the browser.
|
273
|
+
# The snippet may have multiple lines, but only the result of the last line will be returned.
|
274
|
+
#
|
275
|
+
# Note that, by default, the snippet will run in the context of the "selenium"
|
276
|
+
# object itself, so <tt>this</tt> will refer to the Selenium object. Use <tt>window</tt> to
|
277
|
+
# refer to the window of your application, e.g. <tt>window.document.getElementById('foo')</tt>
|
278
|
+
# If you need to use
|
279
|
+
# a locator to refer to a single element in your application page, you can
|
280
|
+
# use <tt>this.browserbot.findElement("id=foo")</tt> where "id=foo" is your locator.
|
281
|
+
#
|
282
|
+
# * 'script' is the JavaScript snippet to run
|
283
|
+
def js_eval(script)
|
284
|
+
string_command "getEval", [script,]
|
285
|
+
end
|
286
|
+
|
287
|
+
# Set the Remote Control timeout (as opposed to the client side driver timeout).
|
288
|
+
# This timout specifies the amount of time that Selenium Core will wait for actions to complete.
|
289
|
+
#
|
290
|
+
# The default timeout is 30 seconds.
|
291
|
+
# 'timeout' is a timeout in seconds, after which the action will return with an error
|
292
|
+
#
|
293
|
+
# Actions that require waiting include "open" and the "waitFor*" actions.
|
294
|
+
def remote_control_timeout_in_seconds=(timeout_in_seconds)
|
295
|
+
remote_control_command "setTimeout", [actual_timeout_in_milliseconds(timeout_in_seconds),]
|
296
|
+
end
|
297
|
+
|
298
|
+
# Returns the text from a cell of a table. The cellAddress syntax
|
299
|
+
# tableLocator.row.column, where row and column start at 0.
|
300
|
+
#
|
301
|
+
# * 'tableCellAddress' is a cell address, e.g. "foo.1.4"
|
302
|
+
def table_cell_text(tableCellAddress)
|
303
|
+
string_command "getTable", [tableCellAddress,]
|
304
|
+
end
|
305
|
+
|
306
|
+
# Runs the specified JavaScript snippet repeatedly until it evaluates to "true".
|
307
|
+
# The snippet may have multiple lines, but only the result of the last line
|
308
|
+
# will be considered.
|
309
|
+
#
|
310
|
+
# Note that, by default, the snippet will be run in the runner's test window, not in the window
|
311
|
+
# of your application. To get the window of your application, you can use
|
312
|
+
# the JavaScript snippet <tt>selenium.browserbot.getCurrentWindow()</tt>, and then
|
313
|
+
# run your JavaScript in there
|
314
|
+
#
|
315
|
+
#
|
316
|
+
# * 'script' is the JavaScript snippet to run
|
317
|
+
# * 'timeout_in_seconds' is a timeout in seconds, after which this command will return with an error
|
318
|
+
def wait_for_condition(script, timeout_in_seconds = nil)
|
319
|
+
remote_control_command "waitForCondition",
|
320
|
+
[script, actual_timeout_in_milliseconds(timeout_in_seconds),]
|
321
|
+
end
|
322
|
+
|
323
|
+
# Simulates the user clicking the "back" button on their browser.
|
324
|
+
# Using 'options' you can automatically wait for an event to happen after the
|
325
|
+
# click. e.g.
|
326
|
+
#
|
327
|
+
# * go_back :wait_for => :page # will wait for a new page to load
|
328
|
+
# * go_back :wait_for => :popup, :window => 'a window id' # will wait for a new popup window to appear. Also selects the popup window for you provide `:select => true`
|
329
|
+
# * go_back :wait_for => :ajax # will wait for all ajax requests to be completed using semantics of default javascript framework
|
330
|
+
# * go_back :wait_for => :ajax, :javascript_framework => :jquery # will wait for all ajax requests to be completed overriding default javascript framework
|
331
|
+
# * go_back :wait_for => :effects # will wait for all javascript effects to be rendered using semantics of default javascript framework
|
332
|
+
# * go_back :wait_for => :effects, :javascript_framework => :prototype # will wait for all javascript effects to be rendered overriding default javascript framework
|
333
|
+
# * go_back :wait_for => :element, :element => 'new_element_id' # will wait for an element to be present/appear
|
334
|
+
# * go_back :wait_for => :no_element, :element => 'new_element_id' # will wait for an element to be not be present/disappear
|
335
|
+
# * go_back :wait_for => :text, :text => 'some text' # will wait for some text to be present/appear
|
336
|
+
# * go_back "a_locator", :wait_for => :text, :text => /A Regexp/ # will wait for some text to be present/appear
|
337
|
+
# * go_back :wait_for => :text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to be 'some text'
|
338
|
+
# * go_back :wait_for => :no_text, :text => 'some text' # will wait for the text to be not be present/disappear
|
339
|
+
# * go_back "a_locator", :wait_for => :no_text, :text => /A Regexp/ # will wait for the text to be not be present/disappear
|
340
|
+
# * go_back :wait_for => :no_text, :element => 'a_locator', :text => 'some text' # will wait for the content of 'a_locator' to not be 'some text'
|
341
|
+
# * go_back :wait_for => :condition, :javascript => 'some expression' # will wait for the javascript expression to be true
|
342
|
+
# * go_back :wait_for => :value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to be 'some value'
|
343
|
+
# * go_back :wait_for => :visible, :element => 'a_locator' # will wait for element to be visible
|
344
|
+
# * go_back :wait_for => :not_visible, :element => 'a_locator' # will wait for element to not be visible
|
345
|
+
# * go_back :wait_for => :no_value, :element => 'a_locator', :value => 'some value' # will wait for the field value of 'a_locator' to not be 'some value'
|
346
|
+
#
|
347
|
+
# Using options you can also define an explicit timeout (:timeout_in_seconds key). Otherwise the default driver timeout
|
348
|
+
# is used.
|
349
|
+
def go_back(options={})
|
350
|
+
remote_control_command "goBack"
|
351
|
+
wait_for options
|
352
|
+
end
|
353
|
+
|
354
|
+
# Return all cookies for the current page under test.
|
355
|
+
def cookies
|
356
|
+
string_command "getCookie"
|
357
|
+
end
|
358
|
+
|
359
|
+
# Returns the value of the cookie with the specified name, or throws an error if the cookie is not present.
|
360
|
+
#
|
361
|
+
# 'name' is the name of the cookie
|
362
|
+
def cookie(name)
|
363
|
+
string_command "getCookieByName", [name,]
|
364
|
+
end
|
365
|
+
|
366
|
+
# Returns true if a cookie with the specified name is present, or false otherwise.
|
367
|
+
#
|
368
|
+
# 'name' is the name of the cookie
|
369
|
+
def cookie?(name)
|
370
|
+
boolean_command "isCookiePresent", [name,]
|
371
|
+
end
|
372
|
+
|
373
|
+
# Create a new cookie whose path and domain are same with those of current page
|
374
|
+
# under test, unless you specified a path for this cookie explicitly.
|
375
|
+
#
|
376
|
+
# 'nameValuePair' is name and value of the cookie in a format "name=value"
|
377
|
+
# 'optionsString' is options for the cookie. Currently supported options include 'path', 'max_age' and 'domain'.
|
378
|
+
# the optionsString's format is "path=/path/, max_age=60, domain=.foo.com". The order of options are irrelevant, the unit of the value of 'max_age' is second. Note that specifying a domain that isn't a subset of the current domain will usually fail.
|
379
|
+
def create_cookie(name_value_pair, options="")
|
380
|
+
if options.kind_of? Hash
|
381
|
+
options = options.keys.collect {|key| "#{key}=#{options[key]}" }.sort.join(", ")
|
382
|
+
end
|
383
|
+
remote_control_command "createCookie", [name_value_pair,options,]
|
384
|
+
end
|
385
|
+
|
386
|
+
# Delete a named cookie with specified path and domain. Be careful; to delete a cookie, you
|
387
|
+
# need to delete it using the exact same path and domain that were used to create the cookie.
|
388
|
+
# If the path is wrong, or the domain is wrong, the cookie simply won't be deleted. Also
|
389
|
+
# note that specifying a domain that isn't a subset of the current domain will usually fail.
|
390
|
+
#
|
391
|
+
# Since there's no way to discover at runtime the original path and domain of a given cookie,
|
392
|
+
# we've added an option called 'recurse' to try all sub-domains of the current domain with
|
393
|
+
# all paths that are a subset of the current path. Beware; this option can be slow. In
|
394
|
+
# big-O notation, it operates in O(n*m) time, where n is the number of dots in the domain
|
395
|
+
# name and m is the number of slashes in the path.
|
396
|
+
#
|
397
|
+
# 'name' is the name of the cookie to be deleted
|
398
|
+
# 'optionsString' is options for the cookie. Currently supported options include 'path', 'domain' and 'recurse.' The optionsString's format is "path=/path/, domain=.foo.com, recurse=true". The order of options are irrelevant. Note that specifying a domain that isn't a subset of the current domain will usually fail.
|
399
|
+
def delete_cookie(name, options="")
|
400
|
+
if options.kind_of? Hash
|
401
|
+
ordered_keys = options.keys.sort {|a,b| a.to_s <=> b.to_s }
|
402
|
+
options = ordered_keys.collect {|key| "#{key}=#{options[key]}" }.join(", ")
|
403
|
+
end
|
404
|
+
remote_control_command "deleteCookie", [name,options,]
|
405
|
+
end
|
406
|
+
|
407
|
+
# Returns the IDs of all windows that the browser knows about.
|
408
|
+
def all_window_ids
|
409
|
+
string_array_command "getAllWindowIds"
|
410
|
+
end
|
411
|
+
|
412
|
+
|
413
|
+
# Returns the names of all windows that the browser knows about.
|
414
|
+
def all_window_names
|
415
|
+
string_array_command "getAllWindowNames"
|
416
|
+
end
|
417
|
+
|
418
|
+
|
419
|
+
# Returns the titles of all windows that the browser knows about.
|
420
|
+
def all_window_titles
|
421
|
+
string_array_command "getAllWindowTitles"
|
422
|
+
end
|
423
|
+
|
424
|
+
# Returns a string representation of the network traffic seen by the
|
425
|
+
# browser, including headers, AJAX requests, status codes, and timings.
|
426
|
+
# When this function is called, the traffic log is cleared, so the
|
427
|
+
# returned content is only the traffic seen since the last call.
|
428
|
+
#
|
429
|
+
# The network traffic is returned in the format it was requested. Valid
|
430
|
+
# values are: :json, :xml, or :plain.
|
431
|
+
#
|
432
|
+
# Warning: For browser_network_traffic to work you need to start your
|
433
|
+
# browser session with the option "captureNetworkTraffic=true", which
|
434
|
+
# will force ALL traffic to go to the Remote Control proxy even for
|
435
|
+
# more efficient browser modes like `*firefox` and `*safari`.
|
436
|
+
def browser_network_traffic(format = :plain)
|
437
|
+
raise "format must be :plain, :json, or :xml" \
|
438
|
+
unless [:plain, :json, :xml].include?(format)
|
439
|
+
|
440
|
+
remote_control_command "captureNetworkTraffic", [format.to_s]
|
441
|
+
end
|
442
|
+
|
443
|
+
# Allows choice of a specific XPath libraries for Xpath evualuation
|
444
|
+
# in the browser (e.g. to resolve XPath locators).
|
445
|
+
#
|
446
|
+
# `library_name' can be:
|
447
|
+
# * :ajaxslt : Google's library
|
448
|
+
# * :javascript-xpath : Cybozu Labs' faster library
|
449
|
+
# * :default : Selenium default library.
|
450
|
+
def browser_xpath_library=(library_name)
|
451
|
+
raise "library name must be :ajaxslt, :javascript-xpath, or :default" \
|
452
|
+
unless [:ajaxslt, :'javascript-xpath', :default].include?(library_name)
|
453
|
+
remote_control_command "useXpathLibrary", [library_name.to_s]
|
454
|
+
end
|
455
|
+
|
456
|
+
#
|
457
|
+
# Turn on/off the automatic hightlighting of the element driven or
|
458
|
+
# inspected by Selenium core. Useful when recording videos
|
459
|
+
#
|
460
|
+
def highlight_located_element=(enabled)
|
461
|
+
boolean = (true == enabled)
|
462
|
+
js_eval "selenium.browserbot.shouldHighlightLocatedElement = #{boolean}"
|
463
|
+
end
|
464
|
+
|
465
|
+
# Get execution delay in milliseconds, i.e. a pause delay following
|
466
|
+
# each selenium operation. By default, there is no such delay
|
467
|
+
# (value is 0).
|
468
|
+
def execution_delay
|
469
|
+
string_command "getSpeed"
|
470
|
+
end
|
471
|
+
|
472
|
+
# Set the execution delay in milliseconds, i.e. a pause delay following
|
473
|
+
# each selenium operation. By default, there is no such delay.
|
474
|
+
#
|
475
|
+
# Setting an execution can be useful to troubleshoot or capture videos
|
476
|
+
def execution_delay=(delay_in_milliseconds)
|
477
|
+
remote_control_command "setSpeed", [delay_in_milliseconds]
|
478
|
+
end
|
479
|
+
|
480
|
+
def actual_timeout_in_milliseconds(timeout_in_seconds)
|
481
|
+
actual_timeout = (timeout_in_seconds ||
|
482
|
+
default_timeout_in_seconds).to_i
|
483
|
+
actual_timeout * 1000
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
end
|
488
|
+
end
|