david-capybara 0.3.8
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/History.txt +87 -0
- data/README.rdoc +389 -0
- data/lib/capybara.rb +52 -0
- data/lib/capybara/cucumber.rb +32 -0
- data/lib/capybara/driver/base.rb +48 -0
- data/lib/capybara/driver/celerity_driver.rb +143 -0
- data/lib/capybara/driver/culerity_driver.rb +25 -0
- data/lib/capybara/driver/rack_test_driver.rb +272 -0
- data/lib/capybara/driver/selenium_driver.rb +156 -0
- data/lib/capybara/dsl.rb +60 -0
- data/lib/capybara/node.rb +60 -0
- data/lib/capybara/rails.rb +17 -0
- data/lib/capybara/save_and_open_page.rb +33 -0
- data/lib/capybara/searchable.rb +54 -0
- data/lib/capybara/server.rb +114 -0
- data/lib/capybara/session.rb +262 -0
- data/lib/capybara/spec/driver.rb +162 -0
- data/lib/capybara/spec/fixtures/capybara.jpg +0 -0
- data/lib/capybara/spec/fixtures/test_file.txt +1 -0
- data/lib/capybara/spec/public/canvas.jpg +0 -0
- data/lib/capybara/spec/public/jquery-ui.js +35 -0
- data/lib/capybara/spec/public/jquery.js +19 -0
- data/lib/capybara/spec/public/test.js +33 -0
- data/lib/capybara/spec/session.rb +81 -0
- data/lib/capybara/spec/session/all_spec.rb +69 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +64 -0
- data/lib/capybara/spec/session/check_spec.rb +67 -0
- data/lib/capybara/spec/session/choose_spec.rb +26 -0
- data/lib/capybara/spec/session/click_button_spec.rb +236 -0
- data/lib/capybara/spec/session/click_link_spec.rb +118 -0
- data/lib/capybara/spec/session/click_spec.rb +24 -0
- data/lib/capybara/spec/session/current_url_spec.rb +8 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +108 -0
- data/lib/capybara/spec/session/find_button_spec.rb +16 -0
- data/lib/capybara/spec/session/find_by_id_spec.rb +16 -0
- data/lib/capybara/spec/session/find_field_spec.rb +22 -0
- data/lib/capybara/spec/session/find_link_spec.rb +17 -0
- data/lib/capybara/spec/session/find_spec.rb +57 -0
- data/lib/capybara/spec/session/has_button_spec.rb +32 -0
- data/lib/capybara/spec/session/has_content_spec.rb +106 -0
- data/lib/capybara/spec/session/has_css_spec.rb +107 -0
- data/lib/capybara/spec/session/has_field_spec.rb +96 -0
- data/lib/capybara/spec/session/has_link_spec.rb +33 -0
- data/lib/capybara/spec/session/has_select_spec.rb +89 -0
- data/lib/capybara/spec/session/has_table_spec.rb +96 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +123 -0
- data/lib/capybara/spec/session/headers.rb +19 -0
- data/lib/capybara/spec/session/javascript.rb +204 -0
- data/lib/capybara/spec/session/locate_spec.rb +59 -0
- data/lib/capybara/spec/session/select_spec.rb +83 -0
- data/lib/capybara/spec/session/uncheck_spec.rb +21 -0
- data/lib/capybara/spec/session/unselect_spec.rb +54 -0
- data/lib/capybara/spec/session/within_spec.rb +153 -0
- data/lib/capybara/spec/test_app.rb +75 -0
- data/lib/capybara/spec/views/buttons.erb +4 -0
- data/lib/capybara/spec/views/fieldsets.erb +29 -0
- data/lib/capybara/spec/views/form.erb +235 -0
- data/lib/capybara/spec/views/frame_one.erb +8 -0
- data/lib/capybara/spec/views/frame_two.erb +8 -0
- data/lib/capybara/spec/views/postback.erb +13 -0
- data/lib/capybara/spec/views/tables.erb +122 -0
- data/lib/capybara/spec/views/with_html.erb +46 -0
- data/lib/capybara/spec/views/with_js.erb +39 -0
- data/lib/capybara/spec/views/with_scope.erb +36 -0
- data/lib/capybara/spec/views/with_simple_html.erb +1 -0
- data/lib/capybara/spec/views/within_frames.erb +10 -0
- data/lib/capybara/version.rb +3 -0
- data/lib/capybara/wait_until.rb +28 -0
- data/lib/capybara/xpath.rb +180 -0
- data/spec/capybara_spec.rb +18 -0
- data/spec/driver/celerity_driver_spec.rb +16 -0
- data/spec/driver/culerity_driver_spec.rb +12 -0
- data/spec/driver/rack_test_driver_spec.rb +17 -0
- data/spec/driver/remote_culerity_driver_spec.rb +23 -0
- data/spec/driver/remote_selenium_driver_spec.rb +18 -0
- data/spec/driver/selenium_driver_spec.rb +11 -0
- data/spec/dsl_spec.rb +140 -0
- data/spec/save_and_open_page_spec.rb +43 -0
- data/spec/searchable_spec.rb +66 -0
- data/spec/server_spec.rb +53 -0
- data/spec/session/celerity_session_spec.rb +27 -0
- data/spec/session/culerity_session_spec.rb +25 -0
- data/spec/session/rack_test_session_spec.rb +33 -0
- data/spec/session/selenium_session_spec.rb +25 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/wait_until_spec.rb +28 -0
- data/spec/xpath_spec.rb +180 -0
- metadata +260 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<form action="/form" method="post">
|
|
2
|
+
<table id="agent_table">
|
|
3
|
+
<caption>Agent</caption>
|
|
4
|
+
|
|
5
|
+
<tr>
|
|
6
|
+
<td>
|
|
7
|
+
<label for="form_agent_name">Name</label>
|
|
8
|
+
</td>
|
|
9
|
+
<td>
|
|
10
|
+
<input type="text" name="form[agent_name]" value="James" id="form_agent_name"/>
|
|
11
|
+
</td>
|
|
12
|
+
</tr>
|
|
13
|
+
|
|
14
|
+
<tr>
|
|
15
|
+
<td colspan="2">
|
|
16
|
+
<input type="submit" value="Create"/>
|
|
17
|
+
</td>
|
|
18
|
+
</tr>
|
|
19
|
+
</table>
|
|
20
|
+
</form>
|
|
21
|
+
|
|
22
|
+
<form action="/form" method="post">
|
|
23
|
+
<table id="girl_table">
|
|
24
|
+
<caption>Girl</caption>
|
|
25
|
+
|
|
26
|
+
<tr>
|
|
27
|
+
<td>
|
|
28
|
+
<label for="form_girl_name">Name</label>
|
|
29
|
+
</td>
|
|
30
|
+
<td>
|
|
31
|
+
<input type="text" name="form[girl_name]" value="Vesper" id="form_girl_name"/>
|
|
32
|
+
</td>
|
|
33
|
+
</tr>
|
|
34
|
+
|
|
35
|
+
<tr>
|
|
36
|
+
<td colspan="2">
|
|
37
|
+
<input type="submit" value="Create"/>
|
|
38
|
+
</td>
|
|
39
|
+
</tr>
|
|
40
|
+
</table>
|
|
41
|
+
</form>
|
|
42
|
+
|
|
43
|
+
<form action="/form" method="post">
|
|
44
|
+
<table id="villain_table">
|
|
45
|
+
<caption>Villain</caption>
|
|
46
|
+
|
|
47
|
+
<tr>
|
|
48
|
+
<td>
|
|
49
|
+
<label for="form_villain_name">Name</label>
|
|
50
|
+
</td>
|
|
51
|
+
<td>
|
|
52
|
+
<input type="text" name="form[villain_name]" value="Ernst" id="form_villain_name"/>
|
|
53
|
+
</td>
|
|
54
|
+
</tr>
|
|
55
|
+
|
|
56
|
+
<tr>
|
|
57
|
+
<td colspan="2">
|
|
58
|
+
<input type="submit" value="Create"/>
|
|
59
|
+
</td>
|
|
60
|
+
</tr>
|
|
61
|
+
</table>
|
|
62
|
+
</form>
|
|
63
|
+
|
|
64
|
+
<table>
|
|
65
|
+
<caption>Ransom</caption>
|
|
66
|
+
|
|
67
|
+
<thead>
|
|
68
|
+
<tr>
|
|
69
|
+
<th>Year</th>
|
|
70
|
+
<th>Governmental</th>
|
|
71
|
+
<th>Private</th>
|
|
72
|
+
</tr>
|
|
73
|
+
</thead>
|
|
74
|
+
|
|
75
|
+
<tbody>
|
|
76
|
+
<tr>
|
|
77
|
+
<th scope="row">2007</th>
|
|
78
|
+
<td>$300</td>
|
|
79
|
+
<td>$100</td>
|
|
80
|
+
</tr>
|
|
81
|
+
<tr>
|
|
82
|
+
<th scope="row">2008</th>
|
|
83
|
+
<td>$123</td>
|
|
84
|
+
<td>$897</td>
|
|
85
|
+
</tr>
|
|
86
|
+
<tr>
|
|
87
|
+
<th scope="row">2009</th>
|
|
88
|
+
<td>$543</td>
|
|
89
|
+
<td>$99</td>
|
|
90
|
+
</tr>
|
|
91
|
+
</tbody>
|
|
92
|
+
</table>
|
|
93
|
+
|
|
94
|
+
<table>
|
|
95
|
+
<caption>Deaths</caption>
|
|
96
|
+
|
|
97
|
+
<thead>
|
|
98
|
+
<tr>
|
|
99
|
+
<th>Year</th>
|
|
100
|
+
<th>Sharks with lasers</th>
|
|
101
|
+
<th>Flaming volcano</th>
|
|
102
|
+
</tr>
|
|
103
|
+
</thead>
|
|
104
|
+
|
|
105
|
+
<tbody>
|
|
106
|
+
<tr>
|
|
107
|
+
<th scope="row">2007</th>
|
|
108
|
+
<td>66</td>
|
|
109
|
+
<td>7</td>
|
|
110
|
+
</tr>
|
|
111
|
+
<tr>
|
|
112
|
+
<th scope="row">2008</th>
|
|
113
|
+
<td>123</td>
|
|
114
|
+
<td>12</td>
|
|
115
|
+
</tr>
|
|
116
|
+
<tr>
|
|
117
|
+
<th scope="row">2009</th>
|
|
118
|
+
<td>913</td>
|
|
119
|
+
<td>13</td>
|
|
120
|
+
</tr>
|
|
121
|
+
</tbody>
|
|
122
|
+
</table>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<h1>This is a test</h1>
|
|
2
|
+
|
|
3
|
+
<p id="first">
|
|
4
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
|
5
|
+
tempor incididunt ut <a href="/with_simple_html" title="awesome title" class="simple">labore</a>
|
|
6
|
+
et dolore magna aliqua. Ut enim ad minim veniam,
|
|
7
|
+
quis nostrud exercitation <a href="/foo" id="foo">ullamco</a> laboris nisi
|
|
8
|
+
ut aliquip ex ea commodo consequat.
|
|
9
|
+
<a href="/with_simple_html"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="awesome image" /></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p id="second">
|
|
13
|
+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
|
14
|
+
dolore eu fugiat <a href="/redirect" id="red">Redirect</a> pariatur. Excepteur sint occaecat cupidatat non proident,
|
|
15
|
+
sunt in culpa qui officia
|
|
16
|
+
text with
|
|
17
|
+
whitespace
|
|
18
|
+
id est laborum.
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p>
|
|
22
|
+
<input type="text" id="test_field" value="monkey"/>
|
|
23
|
+
<a href="/redirect_back">BackToMyself</a>
|
|
24
|
+
<a title="twas a fine link" href="/redirect">A link came first</a>
|
|
25
|
+
<a title="a fine link" href="/with_simple_html">A link</a>
|
|
26
|
+
<a title="a fine link with data method" data-method="delete" href="/delete">A link with data-method</a>
|
|
27
|
+
<a>No Href</a>
|
|
28
|
+
<a href="">Blank Href</a>
|
|
29
|
+
<a href="#">Blank Anchor</a>
|
|
30
|
+
<a href="#anchor">Anchor</a>
|
|
31
|
+
<a href="/with_simple_html#anchor">Anchor on different page</a>
|
|
32
|
+
<a href="/with_html#anchor">Anchor on same page</a>
|
|
33
|
+
<input type="text" value="" id="test_field">
|
|
34
|
+
<input type="text" checked="checked" id="checked_field">
|
|
35
|
+
<a href="/redirect"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="very fine image" /></a>
|
|
36
|
+
<a href="/with_simple_html"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="fine image" /></a>
|
|
37
|
+
<img src="canvas.jpg" usemap="#testmap" height="523" witdh="501">
|
|
38
|
+
<map name="testmap">
|
|
39
|
+
<area href="/with_simple_html" shape="rect" coords="109,240,129,259" alt="Image Map"/>
|
|
40
|
+
</map>
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<div id="hidden" style="display: none;">
|
|
44
|
+
<div id="hidden_via_ancestor">Inside element with hidden ancestor</div>
|
|
45
|
+
<a href="/with_simple_html" title="awesome title" class="simple">hidden link</a>
|
|
46
|
+
</div>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
|
2
|
+
<head>
|
|
3
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
|
4
|
+
<title>with_js</title>
|
|
5
|
+
<script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
|
|
6
|
+
<script src="/jquery-ui.js" type="text/javascript" charset="utf-8"></script>
|
|
7
|
+
<script src="/test.js" type="text/javascript" charset="utf-8"></script>
|
|
8
|
+
</head>
|
|
9
|
+
|
|
10
|
+
<body id="with_js">
|
|
11
|
+
<h1>FooBar</h1>
|
|
12
|
+
|
|
13
|
+
<p id="change">This is text</p>
|
|
14
|
+
<div id="drag">
|
|
15
|
+
<p>This is a draggable element.</p>
|
|
16
|
+
</div>
|
|
17
|
+
<div id="drop">
|
|
18
|
+
<p>It should be dropped here.</p>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<p><a href="#" id="clickable">Click me</a></p>
|
|
22
|
+
|
|
23
|
+
<p>
|
|
24
|
+
<select id="waiter">
|
|
25
|
+
<option>Foo</option>
|
|
26
|
+
<option>My Waiting Option</option>
|
|
27
|
+
</select>
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
<p>
|
|
31
|
+
<input type="text" name="with_focus_event" value="" id="with_focus_event"/>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<p>
|
|
35
|
+
<input type="checkbox" id="checkbox_with_event"/>
|
|
36
|
+
</p>
|
|
37
|
+
</body>
|
|
38
|
+
</html>
|
|
39
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<h1>This page is used for testing various scopes</h1>
|
|
2
|
+
|
|
3
|
+
<p id="for_foo">
|
|
4
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
|
|
5
|
+
incididunt ut labore et dolore magna aliqua. Ut enim ad minim venia.
|
|
6
|
+
<a href="/redirect">Go</a>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<div id="for_bar">
|
|
10
|
+
<ul>
|
|
11
|
+
<li>With Simple HTML: <a href="/with_simple_html">Go</a>
|
|
12
|
+
<form action="/redirect" method="post" accept-charset="utf-8">
|
|
13
|
+
<p>
|
|
14
|
+
<label for="simple_first_name">First Name</label>
|
|
15
|
+
<input type="text" name="first_name" value="John" id="simple_first_name"/>
|
|
16
|
+
</p>
|
|
17
|
+
<p><input type="submit" value="Go"/></p>
|
|
18
|
+
</form>
|
|
19
|
+
</li>
|
|
20
|
+
<li>Bar: <a href="/foo">Go</a>
|
|
21
|
+
<form action="/form" method="post" accept-charset="utf-8">
|
|
22
|
+
<p>
|
|
23
|
+
<label for="bar_first_name">First Name</label>
|
|
24
|
+
<input type="text" name="form[first_name]" value="Peter" id="bar_first_name"/>
|
|
25
|
+
</p>
|
|
26
|
+
<p><input type="submit" value="Go"/></p>
|
|
27
|
+
</form>
|
|
28
|
+
</li>
|
|
29
|
+
</ul>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div id="another_foo">
|
|
33
|
+
<ul>
|
|
34
|
+
<li>With Simple HTML: <a href="/">Go</a>
|
|
35
|
+
</ul>
|
|
36
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Bar
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Capybara
|
|
2
|
+
#Provides timeout similar to standard library Timeout, but avoids threads
|
|
3
|
+
class WaitUntil
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
|
|
7
|
+
def timeout(seconds = 1, driver = nil, &block)
|
|
8
|
+
start_time = Time.now
|
|
9
|
+
|
|
10
|
+
result = nil
|
|
11
|
+
|
|
12
|
+
until result
|
|
13
|
+
return result if result = yield
|
|
14
|
+
|
|
15
|
+
delay = seconds - (Time.now - start_time)
|
|
16
|
+
if delay <= 0
|
|
17
|
+
raise TimeoutError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
driver && driver.wait_until(delay)
|
|
21
|
+
|
|
22
|
+
sleep(0.05)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
module Capybara
|
|
2
|
+
# this is a class for generating XPath queries, use it like this:
|
|
3
|
+
# Xpath.text_field('foo').link('blah').to_s
|
|
4
|
+
# this will generate an XPath that matches either a text field or a link
|
|
5
|
+
class XPath
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def escape(string)
|
|
9
|
+
if string.include?("'")
|
|
10
|
+
string = string.split("'", -1).map do |substr|
|
|
11
|
+
"'#{substr}'"
|
|
12
|
+
end.join(%q{,"'",})
|
|
13
|
+
"concat(#{string})"
|
|
14
|
+
else
|
|
15
|
+
"'#{string}'"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def wrap(path)
|
|
20
|
+
if path.is_a?(self)
|
|
21
|
+
path
|
|
22
|
+
else
|
|
23
|
+
new(path.to_s)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def respond_to?(method)
|
|
28
|
+
new.respond_to?(method)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def method_missing(*args)
|
|
32
|
+
new.send(*args)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
attr_reader :paths
|
|
37
|
+
|
|
38
|
+
def initialize(*paths)
|
|
39
|
+
@paths = paths
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def scope(scope)
|
|
43
|
+
XPath.new(*paths.map { |p| scope + p })
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_s
|
|
47
|
+
@paths.join(' | ')
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def append(path)
|
|
51
|
+
XPath.new(*[@paths, XPath.wrap(path).paths].flatten)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def prepend(path)
|
|
55
|
+
XPath.new(*[XPath.wrap(path).paths, @paths].flatten)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def from_css(css)
|
|
59
|
+
append(Nokogiri::CSS.xpath_for(css).first)
|
|
60
|
+
end
|
|
61
|
+
alias_method :for_css, :from_css
|
|
62
|
+
|
|
63
|
+
def field(locator, options={})
|
|
64
|
+
if options[:with]
|
|
65
|
+
fillable_field(locator, options)
|
|
66
|
+
else
|
|
67
|
+
xpath = fillable_field(locator)
|
|
68
|
+
xpath = xpath.input_field(:file, locator, options)
|
|
69
|
+
xpath = xpath.checkbox(locator, options)
|
|
70
|
+
xpath = xpath.radio_button(locator, options)
|
|
71
|
+
xpath.select(locator, options)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def fillable_field(locator, options={})
|
|
76
|
+
text_area(locator, options).text_field(locator, options)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def content(locator)
|
|
80
|
+
append("/descendant-or-self::*[contains(normalize-space(.),#{s(locator)})]")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def table(locator, options={})
|
|
84
|
+
conditions = ""
|
|
85
|
+
if options[:rows]
|
|
86
|
+
row_conditions = options[:rows].map do |row|
|
|
87
|
+
row = row.map { |column| "*[self::td or self::th][text()=#{s(column)}]" }.join(sibling)
|
|
88
|
+
"tr[./#{row}]"
|
|
89
|
+
end.join(sibling)
|
|
90
|
+
conditions << "[.//#{row_conditions}]"
|
|
91
|
+
end
|
|
92
|
+
append("//table[@id=#{s(locator)} or contains(caption,#{s(locator)})]#{conditions}")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def fieldset(locator)
|
|
96
|
+
append("//fieldset[@id=#{s(locator)} or contains(legend,#{s(locator)})]")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def link(locator)
|
|
100
|
+
xpath = append("//a[@href][@id=#{s(locator)} or contains(.,#{s(locator)}) or contains(@title,#{s(locator)}) or img[contains(@alt,#{s(locator)})]]")
|
|
101
|
+
xpath = xpath.prepend("//a[@href][text()=#{s(locator)} or @title=#{s(locator)} or img[@alt=#{s(locator)}]]")
|
|
102
|
+
xpath.prepend("//area[@href][@alt=#{s(locator)} or @coords=#{s(locator)}]")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def button(locator)
|
|
106
|
+
xpath = append("//input[@type='submit' or @type='image' or @type='button'][@id=#{s(locator)} or contains(@value,#{s(locator)})]")
|
|
107
|
+
xpath = xpath.append("//button[@id=#{s(locator)} or contains(@value,#{s(locator)}) or contains(.,#{s(locator)})]")
|
|
108
|
+
xpath = xpath.prepend("//input[@type='submit' or @type='image' or @type='button'][@value=#{s(locator)}]")
|
|
109
|
+
xpath = xpath.prepend("//input[@type='image'][@alt=#{s(locator)} or contains(@alt,#{s(locator)})]")
|
|
110
|
+
xpath = xpath.prepend("//button[@value=#{s(locator)} or text()=#{s(locator)}]")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def text_field(locator, options={})
|
|
114
|
+
options = options.merge(:value => options[:with]) if options.has_key?(:with)
|
|
115
|
+
add_field(locator, "//input[@type!='radio' and @type!='checkbox' and @type!='hidden']", options)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def text_area(locator, options={})
|
|
119
|
+
options = options.merge(:text => options[:with]) if options.has_key?(:with)
|
|
120
|
+
add_field(locator, "//textarea", options)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def select(locator, options={})
|
|
124
|
+
add_field(locator, "//select", options)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def checkbox(locator, options={})
|
|
128
|
+
input_field(:checkbox, locator, options)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def radio_button(locator, options={})
|
|
132
|
+
input_field(:radio, locator, options)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def file_field(locator, options={})
|
|
136
|
+
input_field(:file, locator, options)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
protected
|
|
140
|
+
|
|
141
|
+
def input_field(type, locator, options={})
|
|
142
|
+
options = options.merge(:value => options[:with]) if options.has_key?(:with)
|
|
143
|
+
add_field(locator, "//input[@type='#{type}']", options)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# place this between to nodes to indicate that they should be siblings
|
|
147
|
+
def sibling
|
|
148
|
+
'/following-sibling::*[1]/self::'
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def add_field(locator, field, options={})
|
|
152
|
+
postfix = extract_postfix(options)
|
|
153
|
+
xpath = append("#{field}[@id=#{s(locator)}]#{postfix}")
|
|
154
|
+
xpath = xpath.append("#{field}[@name=#{s(locator)}]#{postfix}")
|
|
155
|
+
xpath = xpath.append("#{field}[@id=//label[contains(.,#{s(locator)})]/@for]#{postfix}")
|
|
156
|
+
xpath = xpath.append("//label[contains(.,#{s(locator)})]#{field}#{postfix}")
|
|
157
|
+
xpath.prepend("#{field}[@id=//label[text()=#{s(locator)}]/@for]#{postfix}")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def extract_postfix(options)
|
|
161
|
+
options.inject("") do |postfix, (key, value)|
|
|
162
|
+
case key
|
|
163
|
+
when :value then postfix += "[@value=#{s(value)}]"
|
|
164
|
+
when :text then postfix += "[text()=#{s(value)}]"
|
|
165
|
+
when :checked then postfix += "[@checked]"
|
|
166
|
+
when :unchecked then postfix += "[not(@checked)]"
|
|
167
|
+
when :options then postfix += value.map { |o| "[.//option/text()=#{s(o)}]" }.join
|
|
168
|
+
when :selected then postfix += [value].flatten.map { |o| "[.//option[@selected]/text()=#{s(o)}]" }.join
|
|
169
|
+
end
|
|
170
|
+
postfix
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Sanitize a String for putting it into an xpath query
|
|
175
|
+
def s(string)
|
|
176
|
+
XPath.escape(string)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end
|
|
180
|
+
end
|