rsel 0.1.0 → 0.1.1
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/.gitignore +3 -0
- data/.yardopts +12 -2
- data/Rakefile +26 -0
- data/docs/development.md +23 -0
- data/docs/examples.md +27 -0
- data/docs/fitnesse.md +4 -4
- data/docs/history.md +20 -0
- data/lib/rsel/selenium_test.rb +628 -56
- data/lib/rsel/support.rb +150 -0
- data/rsel.gemspec +5 -3
- data/spec/selenium_test_spec.rb +1484 -30
- data/spec/support_spec.rb +261 -0
- data/test/views/index.erb +1 -0
- data/test/views/slowtext.erb +27 -0
- metadata +35 -6
data/spec/support_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
2
2
|
|
3
|
+
require 'xpath'
|
4
|
+
|
3
5
|
describe Rsel::Support do
|
4
6
|
describe "#loc" do
|
5
7
|
it "returns Selenium-style locators unchanged" do
|
@@ -35,6 +37,14 @@ describe Rsel::Support do
|
|
35
37
|
loc('foo')
|
36
38
|
end.should raise_error
|
37
39
|
end
|
40
|
+
|
41
|
+
it "accepts within for css locators" do
|
42
|
+
loc("css=.boss", '', {:within => "employees"}).should == "css=#employees .boss"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "accepts in_row for css locators" do
|
46
|
+
loc("css=td.salary", '', {:in_row => "Eric"}).should == "css=tr:contains(\"Eric\") td.salary"
|
47
|
+
end
|
38
48
|
end
|
39
49
|
|
40
50
|
describe "#xpath" do
|
@@ -43,6 +53,257 @@ describe Rsel::Support do
|
|
43
53
|
xpath('junk', 'hello')
|
44
54
|
end.should raise_error
|
45
55
|
end
|
56
|
+
|
57
|
+
it "applies within scope" do
|
58
|
+
# Quick-and-dirty: Just ensure the scoping phrase appears in the xpath
|
59
|
+
xpath('link', 'Edit', :within => '#first_div').should include('#first_div')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "applies in_row scope" do
|
63
|
+
# Quick-and-dirty: Just ensure the scoping phrase appears in the xpath
|
64
|
+
xpath('link', 'Edit', :in_row => 'Eric').should include('Eric')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#escape_for_hash" do
|
69
|
+
context "escapes when" do
|
70
|
+
it "escapes semicolon to colon" do
|
71
|
+
escape_for_hash('\\' + ";").should == ":"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "escapes single-quote to comma" do
|
75
|
+
escape_for_hash('\\' + "'").should == ","
|
76
|
+
end
|
77
|
+
|
78
|
+
it "escapes left-bracket to left-brace" do
|
79
|
+
escape_for_hash('\\' + "[").should == "{"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "escapes right-bracket to right-brace" do
|
83
|
+
escape_for_hash('\\' + "]").should == "}"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "escapes backslash" do
|
87
|
+
escape_for_hash('\\\\').should == '\\'
|
88
|
+
end
|
89
|
+
|
90
|
+
it "handles a DOS path" do
|
91
|
+
escape_for_hash('c\\;\\*.bat').should == 'c:\\*.bat'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "does not escape when" do
|
96
|
+
it "sees a lone semicolon" do
|
97
|
+
escape_for_hash(";").should == ";"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "sees a lone single-quote" do
|
101
|
+
escape_for_hash("'").should == "'"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "sees a lone left-bracket" do
|
105
|
+
escape_for_hash("[").should == "["
|
106
|
+
end
|
107
|
+
|
108
|
+
it "sees a lone right-bracket" do
|
109
|
+
escape_for_hash("]").should == "]"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "sees a backslash before semicolon" do
|
113
|
+
escape_for_hash('\\\\' + ";").should == "\\;"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "sees a backslash before single-quote" do
|
117
|
+
escape_for_hash('\\\\' + "'").should == "\\'"
|
118
|
+
end
|
119
|
+
|
120
|
+
it "sees a backslash before left-bracket" do
|
121
|
+
escape_for_hash('\\\\' + "[").should == "\\["
|
122
|
+
end
|
123
|
+
|
124
|
+
it "sees a backslash before right-bracket" do
|
125
|
+
escape_for_hash('\\\\' + "]").should == "\\]"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "handles a single backslash" do
|
129
|
+
escape_for_hash('\\').should == '\\'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "#normalize_ids" do
|
136
|
+
it "converts keys to lowercase" do
|
137
|
+
ids = {
|
138
|
+
"First Name" => "Eric",
|
139
|
+
"PIN" => "123",
|
140
|
+
}
|
141
|
+
normalize_ids(ids)
|
142
|
+
ids.should == {
|
143
|
+
"first name" => "Eric",
|
144
|
+
"pin" => "123",
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
it "escapes all keys using #escape_for_hash" do
|
149
|
+
ids = {
|
150
|
+
'with\[brackets\]' => 'Foo',
|
151
|
+
}
|
152
|
+
normalize_ids(ids)
|
153
|
+
ids.should == {
|
154
|
+
'with{brackets}' => 'Foo',
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
158
|
+
it "escapes values but leaves case alone" do
|
159
|
+
ids = {
|
160
|
+
'foo' => 'with\;colon',
|
161
|
+
}
|
162
|
+
normalize_ids(ids)
|
163
|
+
ids.should == {
|
164
|
+
'foo' => 'with:colon',
|
165
|
+
}
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#strip_tags" do
|
170
|
+
it "strips anchor tags from links" do
|
171
|
+
html = '<a href="http://example.com/">http://example.com</a>'
|
172
|
+
strip_tags(html).should == 'http://example.com'
|
173
|
+
end
|
174
|
+
|
175
|
+
it "leaves plain text alone" do
|
176
|
+
html = 'http://example.com'
|
177
|
+
strip_tags(html).should == 'http://example.com'
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#xpath_expressions" do
|
182
|
+
it "breaks down XPath::Union into XPath::Expressions" do
|
183
|
+
foo = XPath::HTML.option('foo')
|
184
|
+
bar = XPath::HTML.option('bar')
|
185
|
+
baz = XPath::HTML.option('baz')
|
186
|
+
union = XPath::Union.new(foo, bar, baz)
|
187
|
+
xpath_expressions(union).should == [foo, bar, baz]
|
188
|
+
end
|
189
|
+
|
190
|
+
it "returns [expr] for a single XPath::Expression" do
|
191
|
+
foo = XPath::HTML.option('foo')
|
192
|
+
xpath_expressions(foo).should == [foo]
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "#apply_scope" do
|
197
|
+
it "returns an xpath string with one element scoped inside another" do
|
198
|
+
row = XPath::HTML.send('table_row', 'foo')
|
199
|
+
link = XPath::HTML.send('link', 'bar')
|
200
|
+
union = XPath::Union.new(row.child(link))
|
201
|
+
apply_scope(row, link).should == union.to_s
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#string_is_true?" do
|
206
|
+
it "returns true for true strings" do
|
207
|
+
["", "1", "check", "checked", "on", "select", "selected", "true", "yes"].each do |s|
|
208
|
+
string_is_true?(s).should be_true
|
209
|
+
end
|
210
|
+
end
|
211
|
+
it "is case-insensitive" do
|
212
|
+
["Check", "Checked", "On", "Select", "Selected", "True", "Yes"].each do |s|
|
213
|
+
string_is_true?(s).should be_true
|
214
|
+
end
|
215
|
+
end
|
216
|
+
it "returns false for other strings" do
|
217
|
+
["False", "WRONG!", "NoNSEnSe$%$@^@!^!%", "0", "null"].each do |s|
|
218
|
+
string_is_true?(s).should be_false
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "#selenium_compare" do
|
224
|
+
context "returns true when" do
|
225
|
+
it "gets most identical strings" do
|
226
|
+
selenium_compare("","").should be_true
|
227
|
+
selenium_compare("This","This").should be_true
|
228
|
+
end
|
229
|
+
it "gets exact:ly identical strings" do
|
230
|
+
selenium_compare("","exact:").should be_true
|
231
|
+
selenium_compare("This","exact:This").should be_true
|
232
|
+
end
|
233
|
+
it "gets matching globs" do
|
234
|
+
selenium_compare("", "*").should be_true
|
235
|
+
selenium_compare("anything", "*").should be_true
|
236
|
+
selenium_compare("Neffing", "Nef*").should be_true
|
237
|
+
end
|
238
|
+
it "gets matching labeled globs" do
|
239
|
+
selenium_compare("", "glob:*").should be_true
|
240
|
+
selenium_compare("anything", "glob:*").should be_true
|
241
|
+
selenium_compare("Neffing", "glob:Nef*").should be_true
|
242
|
+
end
|
243
|
+
it "gets matching regexes" do
|
244
|
+
selenium_compare("", "regexp:.*").should be_true
|
245
|
+
selenium_compare("anything", "regexp:.*").should be_true
|
246
|
+
selenium_compare("Neffing", "regexp:^Nef[a-z]*$").should be_true
|
247
|
+
end
|
248
|
+
it "gets matching case-insensitive regexes" do
|
249
|
+
selenium_compare("", "regexpi:.*").should be_true
|
250
|
+
selenium_compare("Neffing", "regexpi:^nef[A-Z]*$").should be_true
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
context "returns false when" do
|
255
|
+
it "gets most differing strings" do
|
256
|
+
selenium_compare("","!").should be_false
|
257
|
+
selenium_compare("&","").should be_false
|
258
|
+
selenium_compare("This","That").should be_false
|
259
|
+
end
|
260
|
+
it "gets exact:ly different strings" do
|
261
|
+
selenium_compare("","exact:!").should be_false
|
262
|
+
selenium_compare("&","exact:").should be_false
|
263
|
+
selenium_compare("This","exact:That").should be_false
|
264
|
+
end
|
265
|
+
it "gets non-matching globs" do
|
266
|
+
selenium_compare("No", "?").should be_false
|
267
|
+
selenium_compare("Netting", "Nef*").should be_false
|
268
|
+
end
|
269
|
+
it "gets non-matching labeled globs" do
|
270
|
+
selenium_compare("No", "glob:?").should be_false
|
271
|
+
selenium_compare("Netting", "glob:Nef*").should be_false
|
272
|
+
end
|
273
|
+
it "gets non-matching regexes" do
|
274
|
+
selenium_compare("1", "regexp:^[a-z]*$").should be_false
|
275
|
+
selenium_compare("Netting", "regexp:^Nef[a-z]*$").should be_false
|
276
|
+
selenium_compare("Neffing", "regexp:^nef[A-Z]*$").should be_false
|
277
|
+
end
|
278
|
+
it "gets non-matching case-insensitive regexes" do
|
279
|
+
selenium_compare("1", "regexpi:^[a-z]*$").should be_false
|
280
|
+
selenium_compare("Netting", "regexpi:^nef[A-Z]*$").should be_false
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
describe "#xpath_sanitize" do
|
286
|
+
it "escapes one single-quote" do
|
287
|
+
result = xpath_sanitize("Bob's water")
|
288
|
+
result.should == %Q{concat('Bob', "'", 's water')}
|
289
|
+
end
|
290
|
+
|
291
|
+
it "escapes two single-quotes" do
|
292
|
+
result = xpath_sanitize("Bob's on the water's edge")
|
293
|
+
result.should == %Q{concat('Bob', "'", 's on the water', "'", 's edge')}
|
294
|
+
end
|
295
|
+
|
296
|
+
it "leaves strings without single-quotes alone" do
|
297
|
+
result = xpath_sanitize("bobs in the water")
|
298
|
+
result.should == %Q{'bobs in the water'}
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe "#xpath_row_containing" do
|
303
|
+
it "returns an XPath for a table row containing multiple strings" do
|
304
|
+
result = xpath_row_containing(['abc', 'def'])
|
305
|
+
result.should == %Q{//tr[contains(., 'abc') and contains(., 'def')]}
|
306
|
+
end
|
46
307
|
end
|
47
308
|
end
|
48
309
|
|
data/test/views/index.erb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
<html>
|
2
|
+
<head><title>Late text page</title>
|
3
|
+
<script>
|
4
|
+
function createtext() {
|
5
|
+
var mydiv = document.createElement('P');
|
6
|
+
mydiv.id = 'newtext';
|
7
|
+
mydiv.innerHTML = 'The text is here!';
|
8
|
+
document.body.appendChild(mydiv);
|
9
|
+
setTimeout(hidetext, 2000);
|
10
|
+
}
|
11
|
+
function showtext() {
|
12
|
+
document.getElementById('newtext').style.display = '';
|
13
|
+
setTimeout(hidetext, 2000);
|
14
|
+
}
|
15
|
+
function hidetext() {
|
16
|
+
document.getElementById('newtext').style.display = 'none';
|
17
|
+
setTimeout(showtext, 2000);
|
18
|
+
}
|
19
|
+
</script>
|
20
|
+
</head>
|
21
|
+
<body onload="setTimeout(createtext, 2000);">
|
22
|
+
<h1>Late text page</h1>
|
23
|
+
<p>The text is coming...</p>
|
24
|
+
</body>
|
25
|
+
</html>
|
26
|
+
|
27
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Marcus French
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date:
|
20
|
+
date: 2012-01-04 00:00:00 -07:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -123,9 +123,23 @@ dependencies:
|
|
123
123
|
type: :development
|
124
124
|
version_requirements: *id007
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: rdiscount
|
127
127
|
prerelease: false
|
128
128
|
requirement: &id008 !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
hash: 3
|
134
|
+
segments:
|
135
|
+
- 0
|
136
|
+
version: "0"
|
137
|
+
type: :development
|
138
|
+
version_requirements: *id008
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rspec
|
141
|
+
prerelease: false
|
142
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
129
143
|
none: false
|
130
144
|
requirements:
|
131
145
|
- - ">="
|
@@ -137,7 +151,21 @@ dependencies:
|
|
137
151
|
- 0
|
138
152
|
version: 2.2.0
|
139
153
|
type: :development
|
140
|
-
version_requirements: *
|
154
|
+
version_requirements: *id009
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: rcov
|
157
|
+
prerelease: false
|
158
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
hash: 3
|
164
|
+
segments:
|
165
|
+
- 0
|
166
|
+
version: "0"
|
167
|
+
type: :development
|
168
|
+
version_requirements: *id010
|
141
169
|
description: " Rsel provides a Slim fixture for running Selenium tests, with\n step methods written in Ruby.\n"
|
142
170
|
email: epierce@automation-excellence.com
|
143
171
|
executables: []
|
@@ -185,6 +213,7 @@ files:
|
|
185
213
|
- test/views/index.erb
|
186
214
|
- test/views/readonly_form.erb
|
187
215
|
- test/views/slow.erb
|
216
|
+
- test/views/slowtext.erb
|
188
217
|
- test/views/table.erb
|
189
218
|
- test/views/thanks.erb
|
190
219
|
has_rdoc: true
|