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.
@@ -31,6 +31,8 @@ module Rsel
31
31
  def loc(locator, kind='', scope={})
32
32
  if locator.empty?
33
33
  raise ArgumentError, "locator is required."
34
+ elsif locator =~ /^css=/ && scope != {}
35
+ return csspath(locator, scope)
34
36
  elsif locator =~ /^(id=|name=|dom=|xpath=|link=|css=)/
35
37
  return locator
36
38
  else
@@ -38,6 +40,35 @@ module Rsel
38
40
  end
39
41
  end
40
42
 
43
+ # Return a Selenium-style CSS extending the given CSS with a locator.
44
+ #
45
+ # @param [String] locator
46
+ # A Selenium-style locator beginning with `css=`. All other values
47
+ # are ignored. (Meaning the locator is returned as passed.)
48
+ # @param [Hash] scope
49
+ # Keywords to restrict the scope of matching elements
50
+ # @option scope [String] :within
51
+ # Restrict scope to elements having this id, matching `locator` only if
52
+ # it's contained within an element with this id.
53
+ # @option scope [String] :in_row
54
+ # Restrict scope to a table row containing this text, matching `locator`
55
+ # only if that locator is in the same row as the given text.
56
+ #
57
+ # @example
58
+ # xpath('link', 'Log in')
59
+ # xpath('button', 'Submit')
60
+ # xpath('field', 'First name')
61
+ # xpath('table_row', ['First', 'Last'])
62
+ #
63
+ def csspath(locator, scope={})
64
+ return locator unless locator =~ /^css=/ && scope != {}
65
+ if scope[:within]
66
+ locator[4,0] = "##{scope[:within]} "
67
+ elsif scope[:in_row]
68
+ locator[4,0] = "tr:contains(\"#{scope[:in_row]}\") "
69
+ end
70
+ return locator
71
+ end
41
72
 
42
73
  # Return a Selenium-style xpath generated by calling `XPath::HTML.<kind>`
43
74
  # with the given `locator`. If `scope` options are provided, the xpath is
@@ -113,6 +144,125 @@ module Rsel
113
144
  return [union]
114
145
  end
115
146
  end
147
+
148
+
149
+ # Escape certain characters to generate characters that can't otherwise be
150
+ # used in FitNesse hashtables.
151
+ #
152
+ # * \; becomes :
153
+ # * \' becomes ,
154
+ # * \[ becomes {
155
+ # * \] becomes }
156
+ # * \\ becomes \
157
+ #
158
+ # @since 0.1.1
159
+ #
160
+ def escape_for_hash(text)
161
+ # ((?:\\\\)*) allows any extra pairs of "\"s to be saved.
162
+ text = text.gsub(/(^|[^\\])\\((?:\\\\)*);/, '\1\2:')
163
+ text = text.gsub(/(^|[^\\])\\((?:\\\\)*)'/, '\1\2,')
164
+ text = text.gsub(/(^|[^\\])\\((?:\\\\)*)\[/, '\1\2{')
165
+ text = text.gsub(/(^|[^\\])\\((?:\\\\)*)\]/, '\1\2}')
166
+ text = text.gsub(/\\\\/, '\\')
167
+ return text
168
+ end
169
+
170
+
171
+ # Normalize the given hash of name => locator mappings.
172
+ # Converts all keys to lowercase and calls {#escape_for_hash} on them.
173
+ #
174
+ def normalize_ids(ids)
175
+ ids = {} unless ids.is_a? Hash
176
+ ids.keys.each do |key|
177
+ new_key = escape_for_hash(key.to_s.downcase)
178
+ new_value = escape_for_hash(ids[key])
179
+ ids[new_key] = new_value
180
+
181
+ # Delete the old key if necessary
182
+ if new_key != key
183
+ ids.delete(key)
184
+ end
185
+ end
186
+ end
187
+
188
+
189
+ # Strip HTML tags from the given text. This can be used for converting
190
+ # URLs that FitNesse has marked up back into plain URLs.
191
+ #
192
+ # @param [String] text
193
+ # Text, possibly including markup, that you want to strip
194
+ #
195
+ # @since 0.1.1
196
+ #
197
+ def strip_tags(text)
198
+ return text.gsub(/<\/?[^>]*>/, '')
199
+ end
200
+
201
+ # This module defines helper methods for building XPath expressions
202
+ # copied from Kelp::XPaths
203
+ # Return an XPath for any table row containing all strings in `texts`,
204
+ # within the current context.
205
+ def xpath_row_containing(texts)
206
+ texts = [texts] if texts.class == String
207
+ conditions = texts.collect do |text|
208
+ "contains(., #{xpath_sanitize(text)})"
209
+ end.join(' and ')
210
+ return "//tr[#{conditions}]"
211
+ end
212
+
213
+ # Return the given text string in an XPath-safe form, with
214
+ # any single-quotes escaped by using the XPath `concat`
215
+ # function to combine them with the rest of the text.
216
+ #
217
+ # @example
218
+ # xpath_sanitize("Bob's")
219
+ # # => concat('Bob', "'", 's')
220
+ #
221
+ def xpath_sanitize(text)
222
+ # If there's nothing to escape, just wrap text in single-quotes
223
+ if !text.include?("'")
224
+ return "'#{text}'"
225
+ else
226
+ result = text.gsub(/'/, %{', "'", '})
227
+ return "concat('#{result}')"
228
+ end
229
+ end
230
+
231
+ # Convert a string like "yes", "true", "1", etc.
232
+ # Values currently recognized as true, case-insensitive:
233
+ # * [empty string]
234
+ # * 1
235
+ # * Check
236
+ # * Checked
237
+ # * On
238
+ # * Select
239
+ # * Selected
240
+ # * True
241
+ # * Yes
242
+ def string_is_true?(s)
243
+ return /^(?:yes|true|on|(?:check|select)(?:ed)?|1|)$/i === s
244
+ end
245
+
246
+ # Compare values like Selenium does, with regexpi? and globs.
247
+ # @param [String] text
248
+ # A string.
249
+ #
250
+ # @param [String] expected
251
+ # Another string. This one may have glob:, regexp:, etc.
252
+ #
253
+ def selenium_compare(text, expected)
254
+ if expected.sub!(/^regexp:/, '')
255
+ return /#{expected}/ === text
256
+ elsif expected.sub!(/^regexpi:/, '')
257
+ return /#{expected}/i === text
258
+ elsif expected.sub!(/^exact:/, '')
259
+ return text == expected
260
+ else
261
+ # Default is glob, whether or not glob: is present.
262
+ expected.sub!(/^glob:/, '')
263
+ return File.fnmatch(expected, text)
264
+ end
265
+ end
116
266
  end
117
267
  end
118
268
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rsel"
3
- s.version = "0.1.0"
3
+ s.version = "0.1.1"
4
4
  s.summary = "Runs Selenium tests from FitNesse"
5
5
  s.description = <<-EOS
6
6
  Rsel provides a Slim fixture for running Selenium tests, with
@@ -16,10 +16,12 @@ Gem::Specification.new do |s|
16
16
  s.add_dependency 'selenium-client'
17
17
 
18
18
  s.add_development_dependency 'rake', '0.8.7'
19
- s.add_development_dependency 'sinatra'
19
+ s.add_development_dependency 'sinatra' # For test webapp
20
20
  s.add_development_dependency 'mongrel'
21
- s.add_development_dependency 'yard'
21
+ s.add_development_dependency 'yard' # For documentation
22
+ s.add_development_dependency 'rdiscount' # For YARD / Markdown
22
23
  s.add_development_dependency 'rspec', '>= 2.2.0'
24
+ s.add_development_dependency 'rcov'
23
25
 
24
26
  s.files = `git ls-files`.split("\n")
25
27
  # Don't include .jar files in distribution
@@ -7,7 +7,7 @@ describe Rsel::SeleniumTest do
7
7
  end
8
8
 
9
9
  after(:all) do
10
- @st.close_browser
10
+ @st.close_browser('without showing errors')
11
11
  end
12
12
 
13
13
  context "initialization" do
@@ -19,6 +19,79 @@ describe Rsel::SeleniumTest do
19
19
  @st.url.should == "http://localhost:8070/"
20
20
  @st.browser.host.should == "localhost"
21
21
  @st.browser.port.should == 4444
22
+ @st.stop_on_failure.should == false
23
+ @st.found_failure.should == false
24
+ end
25
+
26
+ context "stop_on_failure option" do
27
+ it "can be initialized with a string" do
28
+ st = Rsel::SeleniumTest.new('localhost', :stop_on_failure => 'true')
29
+ st.stop_on_failure.should be_true
30
+ st = Rsel::SeleniumTest.new('localhost', :stop_on_failure => 'FALSE')
31
+ st.stop_on_failure.should be_false
32
+ end
33
+
34
+ it "can be initialized with a boolean" do
35
+ st = Rsel::SeleniumTest.new('localhost', :stop_on_failure => true)
36
+ st.stop_on_failure.should be_true
37
+ st = Rsel::SeleniumTest.new('localhost', :stop_on_failure => false)
38
+ st.stop_on_failure.should be_false
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ context "opening, closing, and maximizing" do
45
+ describe "#open_browser" do
46
+ # FIXME: This blows up for some unknown reason
47
+ #it "raises StopTestCannotConnect if the connection fails" do
48
+ #st = Rsel::SeleniumTest.new('bogus_host')
49
+ #lambda do
50
+ #st.open_browser
51
+ #end.should raise(Rsel::StopTestCannotConnect)
52
+ #end
53
+
54
+ # TODO: Find a cross-platform way of testing this
55
+ #it "uses the javascript-xpath library for *iexplore" do
56
+ #st = Rsel::SeleniumTest.new('localhost', :browser => '*iexplore')
57
+ #st.open_browser
58
+ #end
59
+ end
60
+
61
+ describe "#maximize_browser" do
62
+ it "returns true" do
63
+ st = Rsel::SeleniumTest.new('http://localhost:8070')
64
+ st.open_browser
65
+ st.maximize_browser.should be_true
66
+ st.close_browser
67
+ end
68
+ end
69
+
70
+ describe "#close_browser" do
71
+ before(:each) do
72
+ @st_temp = Rsel::SeleniumTest.new('http://localhost:8070')
73
+ @st_temp.open_browser
74
+ end
75
+
76
+ it "returns true if there are no errors" do
77
+ @st_temp.close_browser('and show errors').should be_true
78
+ end
79
+
80
+ it "returns true if there are errors, but show_errors is unset" do
81
+ @st_temp.see("Nonexistent words")
82
+ @st_temp.close_browser('').should be_true
83
+ end
84
+
85
+ # FIXME: Figure out why this fails. All rspec says is:
86
+ # Failure/Error: end.should raise(Rsel::StopTestStepFailed)
87
+ # Rsel::StopTestStepFailed:
88
+ # Rsel::StopTestStepFailed
89
+ #it "raises StopTestStepFailed if there are errors and show_errors is set" do
90
+ #@st_temp.see("Nonexistent words")
91
+ #lambda do
92
+ #@st_temp.close_browser('and show errors')
93
+ #end.should raise(Rsel::StopTestStepFailed)
94
+ #end
22
95
  end
23
96
  end
24
97
 
@@ -82,8 +155,10 @@ describe Rsel::SeleniumTest do
82
155
 
83
156
  context "fails when" do
84
157
  it "text is absent" do
158
+ @st.errors
85
159
  @st.see("Nonexistent").should be_false
86
160
  @st.see("Some bogus text").should be_false
161
+ @st.errors.should eq('')
87
162
  end
88
163
  end
89
164
 
@@ -103,8 +178,10 @@ describe Rsel::SeleniumTest do
103
178
 
104
179
  context "fails when" do
105
180
  it "text is present" do
181
+ @st.errors
106
182
  @st.do_not_see("Welcome").should be_false
107
183
  @st.do_not_see("This is a Sinatra webapp").should be_false
184
+ @st.errors.should eq('')
108
185
  end
109
186
  end
110
187
 
@@ -199,6 +276,257 @@ describe Rsel::SeleniumTest do
199
276
  end # links
200
277
 
201
278
 
279
+ context "temporal visibility" do
280
+ before(:each) do
281
+ @st.visit("/slowtext").should be_true
282
+ end
283
+
284
+ describe "#see_within_seconds" do
285
+ context "passes when" do
286
+ it "text is already present" do
287
+ @st.see("Late text page").should be_true
288
+ @st.see_within_seconds("The text is coming...", 10).should be_true
289
+ end
290
+ it "text appears in time" do
291
+ @st.see("The text is coming...").should be_true
292
+ @st.do_not_see("The text is here!").should be_true
293
+ @st.see_within_seconds("The text is here!", "10").should be_true
294
+ @st.see("The text is here!").should be_true
295
+ end
296
+ it "text appears within default time" do
297
+ @st.see("The text is coming...").should be_true
298
+ @st.do_not_see("The text is here!").should be_true
299
+ @st.see_within_seconds("The text is here!").should be_true
300
+ @st.see("The text is here!").should be_true
301
+ end
302
+ end
303
+
304
+ context "fails when" do
305
+ it "text appears too late" do
306
+ @st.see("The text is coming...").should be_true
307
+ @st.do_not_see("The text is here!").should be_true
308
+ @st.see_within_seconds("The text is here!", 1).should be_false
309
+ end
310
+ it "text never appears" do
311
+ @st.see_within_seconds("Nonexistent", 5).should be_false
312
+ end
313
+ end
314
+
315
+ it "is case-sensitive" do
316
+ @st.see_within_seconds("The text is here!", 5).should be_true
317
+ @st.see_within_seconds("The text IS HERE!", 5).should be_false
318
+ end
319
+ end
320
+
321
+ describe "#do_not_see_within_seconds" do
322
+ context "passes when" do
323
+ it "text is already absent" do
324
+ @st.see("Late text page").should be_true
325
+ @st.do_not_see_within_seconds("Some absent text", 10).should be_true
326
+ end
327
+ it "text disappears in time" do
328
+ @st.see_within_seconds("The text is here!", 10).should be_true
329
+ @st.do_not_see_within_seconds("The text is here!", "10").should be_true
330
+ @st.do_not_see("The text is here!").should be_true
331
+ end
332
+ it "text disappears within default time" do
333
+ @st.see_within_seconds("The text is here!", 10).should be_true
334
+ @st.do_not_see_within_seconds("The text is here!").should be_true
335
+ @st.do_not_see("The text is here!").should be_true
336
+ end
337
+ end
338
+
339
+ context "fails when" do
340
+ it "text disappears too late" do
341
+ @st.see_within_seconds("The text is here!", 10).should be_true
342
+ @st.do_not_see_within_seconds("The text is here!", 1).should be_false
343
+ end
344
+ it "text never disappears" do
345
+ @st.do_not_see_within_seconds("The text is coming...", 5).should be_false
346
+ end
347
+ end
348
+ end
349
+ end # temporal visibility
350
+
351
+
352
+ context "conditionals" do
353
+ before(:each) do
354
+ @st.visit("/").should be_true
355
+ end
356
+
357
+ describe "#if_i_see" do
358
+ context "passes when" do
359
+ it "sees text" do
360
+ @st.if_i_see("About this site").should be_true
361
+ @st.click("About this site").should be_true
362
+ @st.end_if.should be_true
363
+ end
364
+
365
+ it "is inside a passed block" do
366
+ @st.if_i_see("About this site").should be_true
367
+ @st.click("About this site").should be_true
368
+ @st.page_loads_in_seconds_or_less(10).should be_true
369
+ @st.if_i_see("This site is").should be_true
370
+ @st.see("is really cool.").should be_true
371
+ @st.end_if.should be_true
372
+ @st.end_if.should be_true
373
+ end
374
+ end
375
+
376
+ context "skips when" do
377
+ it "does not see text" do
378
+ @st.if_i_see("Bogus link").should be_nil
379
+ @st.click("Bogus link").should be_nil
380
+ @st.end_if.should be_true
381
+ end
382
+
383
+ it "is inside a skipped block" do
384
+ @st.if_i_see("Bogus link").should be_nil
385
+ @st.click("Bogus link").should be_nil
386
+ @st.if_i_see("About this site").should be_nil
387
+ @st.click("About this site").should be_nil
388
+ @st.end_if.should be_nil
389
+ @st.end_if.should be_true
390
+ end
391
+ end
392
+ end
393
+
394
+ describe "#if_parameter" do
395
+ context "passes when" do
396
+ it "sees yes" do
397
+ @st.if_parameter("yes").should be_true
398
+ @st.click("About this site").should be_true
399
+ @st.end_if.should be_true
400
+ end
401
+
402
+ it "sees true" do
403
+ @st.if_parameter("true").should be_true
404
+ @st.click("About this site").should be_true
405
+ @st.end_if.should be_true
406
+ end
407
+
408
+ it "sees YES" do
409
+ @st.if_parameter("YES").should be_true
410
+ @st.click("About this site").should be_true
411
+ @st.end_if.should be_true
412
+ end
413
+
414
+ it "sees TRUE" do
415
+ @st.if_parameter("TRUE").should be_true
416
+ @st.click("About this site").should be_true
417
+ @st.end_if.should be_true
418
+ end
419
+
420
+ it "is inside a passed block" do
421
+ @st.if_i_see("About this site").should be_true
422
+ @st.click("About this site").should be_true
423
+ @st.page_loads_in_seconds_or_less(10).should be_true
424
+ @st.if_parameter("True").should be_true
425
+ @st.see("is really cool.").should be_true
426
+ @st.end_if.should be_true
427
+ @st.end_if.should be_true
428
+ end
429
+ end
430
+
431
+ context "skips when" do
432
+ it "sees something other than yes or true" do
433
+ @st.if_parameter("Bogus").should be_nil
434
+ @st.click("Bogus link").should be_nil
435
+ @st.end_if.should be_true
436
+ end
437
+
438
+ it "is inside a skipped block" do
439
+ @st.if_parameter("Bogus link").should be_nil
440
+ @st.click("Bogus link").should be_nil
441
+ @st.if_parameter("TRUE").should be_nil
442
+ @st.click("About this site").should be_nil
443
+ @st.end_if.should be_nil
444
+ @st.end_if.should be_true
445
+ end
446
+ end
447
+ end
448
+
449
+ # TODO: if_is
450
+ describe "#if_is" do
451
+ context "passes when" do
452
+ it "sees the same string" do
453
+ @st.if_is("yes", 'yes').should be_true
454
+ @st.click("About this site").should be_true
455
+ @st.end_if.should be_true
456
+ end
457
+
458
+ it "sees a matching empty string" do
459
+ @st.if_is("",'').should be_true
460
+ @st.click("About this site").should be_true
461
+ @st.end_if.should be_true
462
+ end
463
+
464
+ it "is inside a passed block" do
465
+ @st.if_i_see("About this site").should be_true
466
+ @st.click("About this site").should be_true
467
+ @st.page_loads_in_seconds_or_less(10).should be_true
468
+ @st.if_is("True", "True").should be_true
469
+ @st.see("is really cool.").should be_true
470
+ @st.end_if.should be_true
471
+ @st.end_if.should be_true
472
+ end
473
+ end
474
+
475
+ context "skips when" do
476
+ it "sees different strings" do
477
+ @st.if_is("Ken", "Bogus").should be_nil
478
+ @st.click("Bogus link").should be_nil
479
+ @st.end_if.should be_true
480
+ end
481
+
482
+ it "is inside a skipped block" do
483
+ @st.if_is("Ken", "Bogus").should be_nil
484
+ @st.click("Bogus link").should be_nil
485
+ @st.if_is("True", "True").should be_nil
486
+ @st.click("About this site").should be_nil
487
+ @st.end_if.should be_nil
488
+ @st.end_if.should be_true
489
+ end
490
+ end
491
+ end
492
+
493
+ describe "#otherwise" do
494
+ context "skips when" do
495
+ it "its if was true" do
496
+ @st.if_i_see("About this site").should be_true
497
+ @st.click("About this site").should be_true
498
+ @st.otherwise.should be_nil
499
+ @st.click("Bogus link").should be_nil
500
+ @st.end_if.should be_true
501
+ end
502
+ end
503
+ context "passes when" do
504
+ it "its if was false" do
505
+ @st.if_i_see("Bogus link").should be_nil
506
+ @st.click("Bogus link").should be_nil
507
+ @st.otherwise.should be_true
508
+ @st.click("About this site").should be_true
509
+ @st.end_if.should be_true
510
+ end
511
+ end
512
+
513
+ context "fails when" do
514
+ it "does not have a matching if" do
515
+ @st.otherwise.should be_false
516
+ end
517
+ end
518
+ end
519
+
520
+ describe "#end_if" do
521
+ context "fails when" do
522
+ it "does not have a matching if" do
523
+ @st.end_if.should be_false
524
+ end
525
+ end
526
+ end
527
+ end # conditionals
528
+
529
+
202
530
  context "buttons" do
203
531
  before(:each) do
204
532
  @st.visit("/form").should be_true
@@ -721,7 +1049,7 @@ describe Rsel::SeleniumTest do
721
1049
  end
722
1050
  end
723
1051
 
724
- context "#radio_is_enabled" do
1052
+ describe "#radio_is_enabled" do
725
1053
  context "passes when" do
726
1054
  context "radiobutton with label" do
727
1055
  it "exists, and is enabled" do
@@ -758,6 +1086,44 @@ describe Rsel::SeleniumTest do
758
1086
  end
759
1087
  end
760
1088
  end
1089
+
1090
+ describe "#radio_is_disabled" do
1091
+ context "passes when" do
1092
+ context "radiobutton with label" do
1093
+ it "exists, and is disabled" do
1094
+ @st.select_radio("Briefs")
1095
+ @st.radio_is_disabled("Boxers").should be_true
1096
+ end
1097
+
1098
+ it "exists within scope, and is disabled" do
1099
+ @st.select_radio("Briefs", :within => "clothing")
1100
+ @st.radio_is_disabled("Boxers", :within => "clothing").should be_true
1101
+ end
1102
+
1103
+ it "exists in table row, and is disabled" do
1104
+ # TODO
1105
+ end
1106
+ end
1107
+ end
1108
+
1109
+ context "fails when" do
1110
+ context "radiobutton with label" do
1111
+ it "does not exist" do
1112
+ @st.radio_is_disabled("Naked").should be_false
1113
+ end
1114
+
1115
+ it "exists, but is enabled" do
1116
+ @st.select_radio("Briefs")
1117
+ @st.radio_is_disabled("Briefs").should be_false
1118
+ end
1119
+
1120
+ it "exists and is disabled, but not within scope" do
1121
+ @st.select_radio("Briefs", :within => "clothing")
1122
+ @st.radio_is_disabled("Briefs", :within => "food").should be_false
1123
+ end
1124
+ end
1125
+ end
1126
+ end
761
1127
  end # radiobuttons
762
1128
 
763
1129
 
@@ -899,6 +1265,1052 @@ describe Rsel::SeleniumTest do
899
1265
  end
900
1266
  end # dropdowns
901
1267
 
1268
+ # The same field operations, but with the generic set_field function...
1269
+ context "generic_fields" do
1270
+ # TODO: Remove entries that don't use "set_field" in the next 600 or so lines.
1271
+ describe "#set_field" do
1272
+ context "fields" do
1273
+ before(:each) do
1274
+ @st.visit("/form").should be_true
1275
+ end
1276
+
1277
+ context "#set_field with #type_into_field" do
1278
+ context "passes when" do
1279
+ context "text field with label" do
1280
+ it "exists" do
1281
+ @st.set_field("First name", "Eric").should be_true
1282
+ @st.set_field("Last name", "Pierce").should be_true
1283
+ end
1284
+ it "exists within scope" do
1285
+ @st.set_field("First name", "Eric", :within => 'person_form').should be_true
1286
+ @st.set_field("First name", "Andrea", :within => 'spouse_form').should be_true
1287
+ end
1288
+ end
1289
+
1290
+ context "text field with id" do
1291
+ it "exists" do
1292
+ @st.set_field("first_name", "Eric").should be_true
1293
+ @st.set_field("last_name", "Pierce").should be_true
1294
+ end
1295
+ end
1296
+
1297
+ context "textarea with label" do
1298
+ it "exists" do
1299
+ @st.set_field("Life story", "Blah blah blah").should be_true
1300
+ @st.set_field("Life story", "Jibber jabber").should be_true
1301
+ end
1302
+ end
1303
+
1304
+ context "textarea with id" do
1305
+ it "exists" do
1306
+ @st.set_field("biography", "Blah blah blah").should be_true
1307
+ @st.set_field("biography", "Jibber jabber").should be_true
1308
+ end
1309
+ end
1310
+ end
1311
+
1312
+ context "fails when" do
1313
+ it "no field with the given label or id exists" do
1314
+ @st.set_field("Middle name", "Matthew").should be_false
1315
+ @st.set_field("middle_name", "Matthew").should be_false
1316
+ end
1317
+
1318
+ it "field exists, but not within scope" do
1319
+ @st.set_field("Life story", "Long story",
1320
+ :within => 'spouse_form').should be_false
1321
+ end
1322
+
1323
+ it "field exists, but is read-only" do
1324
+ @st.visit("/readonly_form").should be_true
1325
+ @st.set_field("First name", "Eric").should be_false
1326
+ end
1327
+ end
1328
+ end
1329
+
1330
+ context "#set_field with #field_contains" do
1331
+ context "passes when" do
1332
+ context "text field with label" do
1333
+ it "equals the text" do
1334
+ @st.set_field("First name", "Marcus")
1335
+ @st.field_contains("First name", "Marcus").should be_true
1336
+ end
1337
+
1338
+ it "contains the text" do
1339
+ @st.set_field("First name", "Marcus")
1340
+ @st.field_contains("First name", "Marc").should be_true
1341
+ end
1342
+ end
1343
+
1344
+ context "textarea with label" do
1345
+ it "contains the text" do
1346
+ @st.set_field("Life story", "Blah dee blah")
1347
+ @st.field_contains("Life story", "blah").should be_true
1348
+ end
1349
+ end
1350
+ end
1351
+
1352
+ context "fails when" do
1353
+ context "text field with label" do
1354
+ it "does not contain the text" do
1355
+ @st.set_field("First name", "Marcus")
1356
+ @st.field_contains("First name", "Eric").should be_false
1357
+ end
1358
+ end
1359
+
1360
+ context "textarea with label" do
1361
+ it "does not contain the text" do
1362
+ @st.set_field("Life story", "Blah dee blah")
1363
+ @st.field_contains("Life story", "spam").should be_false
1364
+ end
1365
+ end
1366
+ end
1367
+ end
1368
+
1369
+ context "#set_field with #generic_field_equals" do
1370
+ context "passes when" do
1371
+ context "text field with label" do
1372
+ it "equals the text" do
1373
+ @st.set_field("First name", "Ken")
1374
+ @st.generic_field_equals("First name", "Ken").should be_true
1375
+ end
1376
+
1377
+ it "equals the text, and is within scope" do
1378
+ @st.set_field("First name", "Eric", :within => "person_form")
1379
+ @st.generic_field_equals("First name", "Eric", :within => "person_form")
1380
+ end
1381
+ end
1382
+
1383
+ context "textarea with label" do
1384
+ it "equals the text" do
1385
+ @st.set_field("Life story", "Blah dee blah")
1386
+ @st.generic_field_equals("Life story", "Blah dee blah").should be_true
1387
+ end
1388
+
1389
+ it "equals the text, and is within scope" do
1390
+ @st.set_field("Life story", "Blah dee blah",
1391
+ :within => "person_form")
1392
+ @st.generic_field_equals("Life story", "Blah dee blah",
1393
+ :within => "person_form").should be_true
1394
+ end
1395
+
1396
+ it "equals the text, and is in table row" do
1397
+ # TODO
1398
+ end
1399
+ end
1400
+ end
1401
+
1402
+ context "fails when" do
1403
+ context "text field with label" do
1404
+ it "does not exactly equal the text" do
1405
+ @st.set_field("First name", "Marcus")
1406
+ @st.generic_field_equals("First name", "Marc").should be_false
1407
+ end
1408
+ end
1409
+
1410
+ context "textarea with label" do
1411
+ it "does not exist" do
1412
+ @st.generic_field_equals("Third name", "Smith").should be_false
1413
+ end
1414
+
1415
+ it "does not exactly equal the text" do
1416
+ @st.set_field("Life story", "Blah dee blah")
1417
+ @st.generic_field_equals("Life story", "Blah dee").should be_false
1418
+ end
1419
+
1420
+ it "exactly equals the text, but is not within scope" do
1421
+ @st.set_field("First name", "Eric", :within => "person_form")
1422
+ @st.generic_field_equals("First name", "Eric", :within => "spouse_form").should be_false
1423
+ end
1424
+
1425
+ it "exactly equals the text, but is not in table row" do
1426
+ # TODO
1427
+ end
1428
+ end
1429
+ end
1430
+ end
1431
+ end # fields
1432
+
1433
+
1434
+ context "checkboxes" do
1435
+ before(:each) do
1436
+ @st.visit("/form").should be_true
1437
+ end
1438
+
1439
+ context "#set_field with #enable_checkbox" do
1440
+ context "passes when" do
1441
+ context "checkbox with label" do
1442
+ it "exists" do
1443
+ @st.set_field("I like cheese", "on").should be_true
1444
+ @st.set_field("I like salami", "on").should be_true
1445
+ @st.generic_field_equals("I like cheese", "on").should be_true
1446
+ @st.generic_field_equals("I like salami", "on").should be_true
1447
+ end
1448
+
1449
+ it "exists and is already checked" do
1450
+ @st.set_field("I like cheese", "on").should be_true
1451
+ @st.set_field("I like cheese", "on").should be_true
1452
+ @st.generic_field_equals("I like cheese", "on").should be_true
1453
+ end
1454
+
1455
+ it "exists within scope" do
1456
+ @st.set_field("I like cheese", "on", :within => "cheese_checkbox").should be_true
1457
+ @st.set_field("I like salami", "on", :within => "salami_checkbox").should be_true
1458
+ @st.generic_field_equals("I like cheese", "on", :within => "cheese_checkbox").should be_true
1459
+ @st.generic_field_equals("I like salami", "on", :within => "salami_checkbox").should be_true
1460
+ end
1461
+
1462
+ it "exists in table row" do
1463
+ @st.visit("/table")
1464
+ @st.set_field("Like", "on", :in_row => "Marcus").should be_true
1465
+ @st.generic_field_equals("Like", "on", :in_row => "Marcus").should be_true
1466
+ end
1467
+ end
1468
+
1469
+ context "checkbox with id=" do
1470
+ it "exists" do
1471
+ @st.set_field("id=like_cheese", "on").should be_true
1472
+ @st.generic_field_equals("id=like_cheese", "on").should be_true
1473
+ end
1474
+ end
1475
+
1476
+ context "checkbox with xpath=" do
1477
+ it "exists" do
1478
+ @st.set_field("xpath=//input[@id='like_cheese']", "on").should be_true
1479
+ @st.generic_field_equals("xpath=//input[@id='like_cheese']", "on").should be_true
1480
+ end
1481
+ end
1482
+ end
1483
+
1484
+ context "fails when" do
1485
+ context "checkbox with label" do
1486
+ it "does not exist" do
1487
+ @st.set_field("I dislike bacon", "on").should be_false
1488
+ @st.set_field("I like broccoli", "on").should be_false
1489
+ end
1490
+
1491
+ it "exists, but not within scope" do
1492
+ @st.set_field("I like cheese", "on", :within => "salami_checkbox").should be_false
1493
+ @st.set_field("I like salami", "on", :within => "cheese_checkbox").should be_false
1494
+ end
1495
+
1496
+ it "exists, but not in table row" do
1497
+ @st.visit("/table")
1498
+ @st.set_field("Like", "on", :in_row => "Eric").should be_false
1499
+ end
1500
+
1501
+ it "exists, but is read-only" do
1502
+ @st.visit("/readonly_form").should be_true
1503
+ @st.set_field("I like salami", "on").should be_false
1504
+ end
1505
+ end
1506
+ end
1507
+ end
1508
+
1509
+ context "#set_field with #disable_checkbox" do
1510
+ context "passes when" do
1511
+ context "checkbox with label" do
1512
+ it "exists" do
1513
+ @st.set_field("I like cheese", "off").should be_true
1514
+ @st.set_field("I like salami", "off").should be_true
1515
+ @st.generic_field_equals("I like cheese", "off").should be_true
1516
+ @st.generic_field_equals("I like salami", "off").should be_true
1517
+ end
1518
+
1519
+ it "exists and is already unchecked" do
1520
+ @st.set_field("I like cheese", "off").should be_true
1521
+ @st.set_field("I like cheese", "off").should be_true
1522
+ @st.generic_field_equals("I like cheese", "off").should be_true
1523
+ end
1524
+
1525
+ it "exists within scope" do
1526
+ @st.set_field("I like cheese", "off", :within => "cheese_checkbox").should be_true
1527
+ @st.set_field("I like salami", "off", :within => "preferences_form").should be_true
1528
+ @st.generic_field_equals("I like cheese", "off", :within => "cheese_checkbox").should be_true
1529
+ @st.generic_field_equals("I like salami", "off", :within => "preferences_form").should be_true
1530
+ end
1531
+
1532
+ it "exists in table row" do
1533
+ @st.visit("/table")
1534
+ @st.set_field("Like", "off", :in_row => "Marcus").should be_true
1535
+ @st.generic_field_equals("Like", "off", :in_row => "Marcus").should be_true
1536
+ end
1537
+ end
1538
+
1539
+ context "checkbox with id=" do
1540
+ it "exists" do
1541
+ @st.set_field("id=like_cheese", "off").should be_true
1542
+ @st.generic_field_equals("id=like_cheese", "off").should be_true
1543
+ end
1544
+ end
1545
+
1546
+ context "checkbox with xpath=" do
1547
+ it "exists" do
1548
+ @st.set_field("xpath=//input[@id='like_cheese']", "off").should be_true
1549
+ @st.generic_field_equals("xpath=//input[@id='like_cheese']", "off").should be_true
1550
+ end
1551
+ end
1552
+ end
1553
+
1554
+ context "fails when" do
1555
+ context "checkbox with label" do
1556
+ it "does not exist" do
1557
+ @st.set_field("I dislike bacon", "off").should be_false
1558
+ @st.set_field("I like broccoli", "off").should be_false
1559
+ end
1560
+
1561
+ it "exists, but not within scope" do
1562
+ @st.set_field("I like cheese", "off", :within => "salami_checkbox").should be_false
1563
+ @st.set_field("I like salami", "off", :within => "cheese_checkbox").should be_false
1564
+ end
1565
+
1566
+ it "exists, but not in table row" do
1567
+ @st.visit("/table")
1568
+ @st.set_field("Like", "off", :in_row => "Eric").should be_false
1569
+ end
1570
+
1571
+ it "exists, but is read-only" do
1572
+ @st.visit("/readonly_form").should be_true
1573
+ @st.set_field("I like cheese", "off").should be_false
1574
+ end
1575
+ end
1576
+ end
1577
+ end
1578
+
1579
+ context "#set_field with #checkbox_is_enabled" do
1580
+ context "passes when" do
1581
+ context "checkbox with label" do
1582
+ it "exists and is checked" do
1583
+ @st.set_field("I like cheese", "on").should be_true
1584
+ @st.checkbox_is_enabled("I like cheese").should be_true
1585
+ end
1586
+
1587
+ it "exists within scope and is checked" do
1588
+ @st.set_field("I like cheese", "on", :within => "cheese_checkbox").should be_true
1589
+ @st.checkbox_is_enabled("I like cheese", :within => "cheese_checkbox").should be_true
1590
+ end
1591
+
1592
+ it "exists in table row and is checked" do
1593
+ @st.visit("/table")
1594
+ @st.set_field("Like", "on", :in_row => "Ken").should be_true
1595
+ @st.checkbox_is_enabled("Like", :in_row => "Ken").should be_true
1596
+ end
1597
+
1598
+ it "exists and is checked, but read-only" do
1599
+ @st.visit("/readonly_form").should be_true
1600
+ @st.checkbox_is_enabled("I like cheese").should be_true
1601
+ end
1602
+ end
1603
+ end
1604
+
1605
+ context "fails when" do
1606
+ context "checkbox with label" do
1607
+ it "does not exist" do
1608
+ @st.checkbox_is_enabled("I dislike bacon").should be_false
1609
+ end
1610
+
1611
+ it "exists but is unchecked" do
1612
+ @st.set_field("I like cheese", "off").should be_true
1613
+ @st.checkbox_is_enabled("I like cheese").should be_false
1614
+ end
1615
+
1616
+ it "exists and is checked, but not within scope" do
1617
+ @st.set_field("I like cheese", "on", :within => "cheese_checkbox").should be_true
1618
+ @st.checkbox_is_enabled("I like cheese", :within => "salami_checkbox").should be_false
1619
+ end
1620
+
1621
+ it "exists and is checked, but not in table row" do
1622
+ @st.visit("/table")
1623
+ @st.set_field("Like", "on", :in_row => "Marcus").should be_true
1624
+ @st.checkbox_is_enabled("Like", :in_row => "Eric").should be_false
1625
+ end
1626
+ end
1627
+ end
1628
+ end
1629
+
1630
+ context "#set_field with #checkbox_is_disabled" do
1631
+ context "passes when" do
1632
+ context "checkbox with label" do
1633
+ it "exists and is unchecked" do
1634
+ @st.set_field("I like cheese", "off").should be_true
1635
+ @st.checkbox_is_disabled("I like cheese").should be_true
1636
+ end
1637
+
1638
+ it "exists within scope and is unchecked" do
1639
+ @st.set_field("I like cheese", "off", :within => "cheese_checkbox").should be_true
1640
+ @st.checkbox_is_disabled("I like cheese", :within => "cheese_checkbox").should be_true
1641
+ end
1642
+
1643
+ it "exists in table row and is unchecked" do
1644
+ @st.visit("/table")
1645
+ @st.set_field("Like", "off", :in_row => "Ken").should be_true
1646
+ @st.checkbox_is_disabled("Like", :in_row => "Ken").should be_true
1647
+ end
1648
+
1649
+ it "exists and is unchecked, but read-only" do
1650
+ @st.visit("/readonly_form").should be_true
1651
+ @st.checkbox_is_disabled("I like salami").should be_true
1652
+ end
1653
+ end
1654
+ end
1655
+
1656
+ context "fails when" do
1657
+ context "checkbox with label" do
1658
+ it "does not exist" do
1659
+ @st.checkbox_is_disabled("I dislike bacon").should be_false
1660
+ end
1661
+
1662
+ it "exists but is checked" do
1663
+ @st.set_field("I like cheese", "on").should be_true
1664
+ @st.checkbox_is_disabled("I like cheese").should be_false
1665
+ end
1666
+
1667
+ it "exists and is unchecked, but not within scope" do
1668
+ @st.set_field("I like cheese", "off", :within => "cheese_checkbox").should be_true
1669
+ @st.checkbox_is_disabled("I like cheese", :within => "salami_checkbox").should be_false
1670
+ end
1671
+
1672
+ it "exists and is unchecked, but not in table row" do
1673
+ @st.visit("/table")
1674
+ @st.set_field("Like", "off", :in_row => "Marcus").should be_true
1675
+ @st.checkbox_is_disabled("Like", :in_row => "Eric").should be_false
1676
+ end
1677
+ end
1678
+ end
1679
+ end
1680
+ end # checkboxes
1681
+
1682
+
1683
+ context "radiobuttons" do
1684
+ before(:each) do
1685
+ @st.visit("/form").should be_true
1686
+ end
1687
+
1688
+ context "#set_field with #select_radio" do
1689
+ context "passes when" do
1690
+ context "radiobutton with label" do
1691
+ it "exists" do
1692
+ @st.set_field("Briefs").should be_true
1693
+ end
1694
+
1695
+ it "exists within scope" do
1696
+ @st.set_field("Briefs", "", :within => "clothing").should be_true
1697
+ end
1698
+
1699
+ it "exists in table row" do
1700
+ # TODO
1701
+ end
1702
+ end
1703
+ end
1704
+
1705
+ context "fails when" do
1706
+ context "radiobutton with label" do
1707
+ it "does not exist" do
1708
+ @st.set_field("Naked", "").should be_false
1709
+ end
1710
+
1711
+ it "exists, but not within scope" do
1712
+ @st.set_field("Briefs", "", :within => "food").should be_false
1713
+ end
1714
+
1715
+ it "exists, but is read-only" do
1716
+ @st.visit("/readonly_form").should be_true
1717
+ @st.set_field("Boxers", "").should be_false
1718
+ end
1719
+
1720
+ it "exists, but not in table row" do
1721
+ # TODO
1722
+ end
1723
+ end
1724
+ end
1725
+ end
1726
+
1727
+ context "#set_field with #radio_is_enabled" do
1728
+ context "passes when" do
1729
+ context "radiobutton with label" do
1730
+ it "exists, and is enabled" do
1731
+ @st.set_field("Briefs")
1732
+ @st.radio_is_enabled("Briefs").should be_true
1733
+ end
1734
+
1735
+ it "exists within scope, and is enabled" do
1736
+ @st.set_field("Briefs", "", :within => "clothing")
1737
+ @st.radio_is_enabled("Briefs", :within => "clothing").should be_true
1738
+ end
1739
+
1740
+ it "exists in table row, and is enabled" do
1741
+ # TODO
1742
+ end
1743
+ end
1744
+ end
1745
+
1746
+ context "fails when" do
1747
+ context "radiobutton with label" do
1748
+ it "does not exist" do
1749
+ @st.radio_is_enabled("Naked").should be_false
1750
+ end
1751
+
1752
+ it "exists, but is not enabled" do
1753
+ @st.set_field("Briefs", "")
1754
+ @st.radio_is_enabled("Boxers").should be_false
1755
+ end
1756
+
1757
+ it "exists and is enabled, but not within scope" do
1758
+ @st.set_field("Briefs", "", :within => "clothing")
1759
+ @st.radio_is_enabled("Briefs", :within => "food").should be_false
1760
+ end
1761
+ end
1762
+ end
1763
+
1764
+ context "#set_field with #generic_field_equals for #radio_is_enabled" do
1765
+ context "passes when" do
1766
+ context "radiobutton with label" do
1767
+ it "exists, and is enabled" do
1768
+ @st.set_field("Briefs")
1769
+ @st.generic_field_equals("Briefs", "on").should be_true
1770
+ end
1771
+
1772
+ it "exists within scope, and is enabled" do
1773
+ @st.set_field("Briefs", "", :within => "clothing")
1774
+ @st.generic_field_equals("Briefs", "on", :within => "clothing").should be_true
1775
+ end
1776
+
1777
+ it "exists in table row, and is enabled" do
1778
+ # TODO
1779
+ end
1780
+ end
1781
+ end
1782
+
1783
+ context "fails when" do
1784
+ context "radiobutton with label" do
1785
+ it "does not exist" do
1786
+ @st.generic_field_equals("Naked", "on").should be_false
1787
+ end
1788
+
1789
+ it "exists, but is not enabled" do
1790
+ @st.set_field("Briefs", "")
1791
+ @st.generic_field_equals("Boxers", "on").should be_false
1792
+ end
1793
+
1794
+ it "exists and is enabled, but not within scope" do
1795
+ @st.set_field("Briefs", "", :within => "clothing")
1796
+ @st.generic_field_equals("Briefs", "on", :within => "food").should be_false
1797
+ end
1798
+ end
1799
+ end
1800
+ end
1801
+ end # radiobuttons
1802
+
1803
+
1804
+ context "dropdowns" do
1805
+ before(:each) do
1806
+ @st.visit("/form").should be_true
1807
+ end
1808
+
1809
+ context "#set_field with #select_from_dropdown" do
1810
+ context "passes when" do
1811
+ it "option exists in the dropdown" do
1812
+ @st.set_field("Height", "Tall").should be_true
1813
+ @st.set_field("Weight", "Medium").should be_true
1814
+ end
1815
+
1816
+ it "option exists in the dropdown within scope" do
1817
+ @st.set_field("Height", "Tall", :within => "spouse_form").should be_true
1818
+ end
1819
+
1820
+ it "option exists in the dropdown in table row" do
1821
+ @st.visit("/table")
1822
+ @st.set_field("Gender", "Male", :in_row => "Eric").should be_true
1823
+ end
1824
+ end
1825
+
1826
+ context "fails when" do
1827
+ it "no such dropdown exists" do
1828
+ @st.set_field("Eggs", "Over easy").should be_false
1829
+ end
1830
+
1831
+ it "dropdown exists, but the option doesn't" do
1832
+ @st.set_field("Height", "Giant").should be_false
1833
+ @st.set_field("Weight", "Obese").should be_false
1834
+ end
1835
+
1836
+ it "dropdown exists, but is read-only" do
1837
+ @st.visit("/readonly_form").should be_true
1838
+ @st.set_field("Height", "Tall").should be_false
1839
+ end
1840
+
1841
+ it "dropdown exists, but not within scope" do
1842
+ @st.set_field("Weight", "Medium", :within => "spouse_form").should be_false
1843
+ end
1844
+
1845
+ it "dropdown exists, but not in table row" do
1846
+ @st.visit("/table")
1847
+ @st.set_field("Gender", "Female", :in_row => "First name").should be_false
1848
+ end
1849
+ end
1850
+ end
1851
+
1852
+ context "#set_field with #dropdown_includes" do
1853
+ context "passes when" do
1854
+ it "option exists in the dropdown" do
1855
+ @st.dropdown_includes("Height", "Tall").should be_true
1856
+ @st.dropdown_includes("Weight", "Medium").should be_true
1857
+ end
1858
+
1859
+ it "option exists in a read-only dropdown" do
1860
+ @st.visit("/readonly_form").should be_true
1861
+ @st.dropdown_includes("Height", "Tall").should be_true
1862
+ end
1863
+ end
1864
+
1865
+ context "fails when" do
1866
+ it "dropdown exists, but the option doesn't" do
1867
+ @st.dropdown_includes("Height", "Giant").should be_false
1868
+ @st.dropdown_includes("Weight", "Obese").should be_false
1869
+ end
1870
+
1871
+ it "no such dropdown exists" do
1872
+ @st.dropdown_includes("Eggs", "Over easy").should be_false
1873
+ end
1874
+ end
1875
+ end
1876
+
1877
+ context "#set_field with #dropdown_equals" do
1878
+ context "passes when" do
1879
+ it "option is selected in the dropdown" do
1880
+ ["Short", "Average", "Tall"].each do |height|
1881
+ @st.set_field("Height", height)
1882
+ @st.dropdown_equals("Height", height).should be_true
1883
+ end
1884
+ end
1885
+
1886
+ it "option is selected in a read-only dropdown" do
1887
+ @st.visit("/readonly_form").should be_true
1888
+ @st.dropdown_equals("Height", "Average").should be_true
1889
+ end
1890
+
1891
+ it "option is selected in the dropdown, within scope" do
1892
+ ["Short", "Average", "Tall"].each do |height|
1893
+ @st.set_field("Height", height, :within => "spouse_form")
1894
+ @st.dropdown_equals("Height", height, :within => "spouse_form").should be_true
1895
+ end
1896
+ end
1897
+
1898
+ it "option is selected in the dropdown, in table row" do
1899
+ @st.visit("/table")
1900
+ ["Male", "Female"].each do |gender|
1901
+ @st.set_field("Gender", gender, :in_row => "Eric")
1902
+ @st.dropdown_equals("Gender", gender, :in_row => "Eric")
1903
+ end
1904
+ end
1905
+ end
1906
+
1907
+ context "fails when" do
1908
+ it "no such dropdown exists" do
1909
+ @st.dropdown_equals("Eggs", "Over easy").should be_false
1910
+ end
1911
+
1912
+ it "dropdown exists, but the option is not selected" do
1913
+ @st.set_field("Height", "Short")
1914
+ @st.dropdown_equals("Height", "Average").should be_false
1915
+ @st.dropdown_equals("Height", "Tall").should be_false
1916
+
1917
+ @st.set_field("Height", "Average")
1918
+ @st.dropdown_equals("Height", "Short").should be_false
1919
+ @st.dropdown_equals("Height", "Tall").should be_false
1920
+
1921
+ @st.set_field("Height", "Tall")
1922
+ @st.dropdown_equals("Height", "Short").should be_false
1923
+ @st.dropdown_equals("Height", "Average").should be_false
1924
+ end
1925
+
1926
+ it "dropdown exists, and option is selected, but not within scope" do
1927
+ @st.set_field("Height", "Tall", :within => "person_form")
1928
+ @st.set_field("Height", "Short", :within => "spouse_form")
1929
+ @st.dropdown_equals("Height", "Tall", :within => "spouse_form").should be_false
1930
+ end
1931
+
1932
+ it "dropdown exists, and option is selected, but not in table row" do
1933
+ @st.visit("/table")
1934
+ @st.set_field("Gender", "Female", :in_row => "Eric")
1935
+ @st.set_field("Gender", "Male", :in_row => "Marcus")
1936
+ @st.dropdown_equals("Gender", "Female", :in_row => "Marcus").should be_false
1937
+ end
1938
+ end
1939
+ end
1940
+
1941
+ context "#set_field with #generic_field_equals for #dropdown_equals" do
1942
+ context "passes when" do
1943
+ it "option is selected in the dropdown" do
1944
+ ["Short", "Average", "Tall"].each do |height|
1945
+ @st.set_field("Height", height)
1946
+ @st.generic_field_equals("Height", height).should be_true
1947
+ end
1948
+ end
1949
+
1950
+ it "option is selected in a read-only dropdown" do
1951
+ @st.visit("/readonly_form").should be_true
1952
+ @st.generic_field_equals("Height", "Average").should be_true
1953
+ end
1954
+
1955
+ it "option is selected in the dropdown, within scope" do
1956
+ ["Short", "Average", "Tall"].each do |height|
1957
+ @st.set_field("Height", height, :within => "spouse_form")
1958
+ @st.generic_field_equals("Height", height, :within => "spouse_form").should be_true
1959
+ end
1960
+ end
1961
+
1962
+ it "option is selected in the dropdown, in table row" do
1963
+ @st.visit("/table")
1964
+ ["Male", "Female"].each do |gender|
1965
+ @st.set_field("Gender", gender, :in_row => "Eric")
1966
+ @st.generic_field_equals("Gender", gender, :in_row => "Eric")
1967
+ end
1968
+ end
1969
+ end
1970
+
1971
+ context "fails when" do
1972
+ it "no such dropdown exists" do
1973
+ @st.generic_field_equals("Eggs", "Over easy").should be_false
1974
+ end
1975
+
1976
+ it "dropdown exists, but the option is not selected" do
1977
+ @st.set_field("Height", "Short")
1978
+ @st.generic_field_equals("Height", "Average").should be_false
1979
+ @st.generic_field_equals("Height", "Tall").should be_false
1980
+
1981
+ @st.set_field("Height", "Average")
1982
+ @st.generic_field_equals("Height", "Short").should be_false
1983
+ @st.generic_field_equals("Height", "Tall").should be_false
1984
+
1985
+ @st.set_field("Height", "Tall")
1986
+ @st.generic_field_equals("Height", "Short").should be_false
1987
+ @st.generic_field_equals("Height", "Average").should be_false
1988
+ end
1989
+
1990
+ it "dropdown exists, and option is selected, but not within scope" do
1991
+ @st.set_field("Height", "Tall", :within => "person_form")
1992
+ @st.set_field("Height", "Short", :within => "spouse_form")
1993
+ @st.generic_field_equals("Height", "Tall", :within => "spouse_form").should be_false
1994
+ end
1995
+
1996
+ it "dropdown exists, and option is selected, but not in table row" do
1997
+ @st.visit("/table")
1998
+ @st.set_field("Gender", "Female", :in_row => "Eric")
1999
+ @st.set_field("Gender", "Male", :in_row => "Marcus")
2000
+ @st.generic_field_equals("Gender", "Female", :in_row => "Marcus").should be_false
2001
+ end
2002
+ end
2003
+ end
2004
+ end # dropdowns
2005
+ end # set_field
2006
+
2007
+
2008
+ # TODO: Add test cases with scopes to the next three functions described.
2009
+ describe "#set_field_among" do
2010
+ before(:each) do
2011
+ @st.visit("/form").should be_true
2012
+ end
2013
+ context "passes when" do
2014
+ context "text field with label" do
2015
+ it "equals the page text" do
2016
+ @st.set_field_among("First name", "Marcus", "Last name" => "nowhere").should be_true
2017
+ @st.field_contains("First name", "Marcus").should be_true
2018
+ end
2019
+
2020
+ it "equals the page text and has no ids" do
2021
+ @st.set_field_among("First name", "Marcus", "").should be_true
2022
+ @st.field_contains("First name", "Marcus").should be_true
2023
+ end
2024
+
2025
+ it "equals the hash text" do
2026
+ @st.set_field_among("Last name", "Marcus", "Last name" => "First name").should be_true
2027
+ @st.field_contains("First name", "Marcus").should be_true
2028
+ end
2029
+
2030
+ it "equals the escaped hash text" do
2031
+ @st.set_field_among("Last:name", "Marcus", "Last\\;name" => "First name").should be_true
2032
+ @st.field_contains("First name", "Marcus").should be_true
2033
+ end
2034
+ end
2035
+ end
2036
+
2037
+ context "fails when" do
2038
+ context "text field with label" do
2039
+ it "does not exist" do
2040
+ @st.set_field_among("Third name", "Smith").should be_false
2041
+ end
2042
+
2043
+ it "has a hash value that does not exist" do
2044
+ @st.set_field_among("Last name", "Smith", "Last name" => "Third name").should be_false
2045
+ end
2046
+ end
2047
+ end
2048
+ end # set_field_among
2049
+
2050
+ describe "#field_equals_among" do
2051
+ before(:each) do
2052
+ @st.visit("/form").should be_true
2053
+ end
2054
+ context "passes when" do
2055
+ context "text field with label" do
2056
+ it "equals the page text" do
2057
+ @st.set_field_among("First name", "Marcus", "Last name" => "nowhere").should be_true
2058
+ @st.field_equals_among("First name", "Marcus", "Last name" => "nowhere").should be_true
2059
+ end
2060
+
2061
+ it "equals the page text and has no ids" do
2062
+ @st.set_field_among("First name", "Marcus", "").should be_true
2063
+ @st.field_equals_among("First name", "Marcus", "").should be_true
2064
+ end
2065
+
2066
+ it "equals the hash text" do
2067
+ @st.set_field_among("Last name", "Marcus", "Last name" => "First name").should be_true
2068
+ @st.field_equals_among("Last name", "Marcus", "Last name" => "First name").should be_true
2069
+ end
2070
+
2071
+ it "equals the escaped hash text" do
2072
+ @st.set_field_among("Last:name", "Marcus", "Last\\;name" => "First name").should be_true
2073
+ @st.field_equals_among("Last:name", "Marcus", "Last\\;name" => "First name").should be_true
2074
+ end
2075
+ end
2076
+ end
2077
+
2078
+ context "fails when" do
2079
+ context "text field with label" do
2080
+ it "does not exist" do
2081
+ @st.field_equals_among("Third name", "").should be_false
2082
+ end
2083
+
2084
+ it "has a hash value that does not exist" do
2085
+ @st.field_equals_among("Last name", "", "Last name" => "Third name").should be_false
2086
+ end
2087
+
2088
+ it "does not equal the expected text" do
2089
+ @st.field_equals_among("Last name", "Marcus", "Last name" => "First name").should be_false
2090
+ end
2091
+ end
2092
+ end
2093
+ end # field_equals_among
2094
+
2095
+ describe "#set_fields" do
2096
+ before(:each) do
2097
+ @st.visit("/form").should be_true
2098
+ end
2099
+ context "passes when" do
2100
+ context "text fields with labels" do
2101
+ it "sets one field" do
2102
+ @st.set_fields("First name" => "Marcus").should be_true
2103
+ @st.field_contains("First name", "Marcus").should be_true
2104
+ end
2105
+
2106
+ it "sets zero fields" do
2107
+ @st.set_fields("").should be_true
2108
+ end
2109
+
2110
+ it "sets several fields" do
2111
+ @st.set_fields("First name" => "Ken", "Last name" => "Brazier", "Life story" => "My story\\; I get testy a lot.").should be_true
2112
+ @st.field_contains("First name", "Ken").should be_true
2113
+ @st.field_contains("Last name", "Brazier").should be_true
2114
+ @st.field_contains("Life story", "story: I get testy").should be_true
2115
+ end
2116
+ end
2117
+ end
2118
+
2119
+ context "fails when" do
2120
+ context "text fields with labels" do
2121
+ it "cant find the first field" do
2122
+ @st.set_fields("Faust name" => "Ken", "Last name" => "Brazier").should be_false
2123
+ end
2124
+
2125
+ it "cant find the last field" do
2126
+ @st.set_fields("First name" => "Ken", "Lost name" => "Brazier").should be_false
2127
+ end
2128
+ end
2129
+ end
2130
+ end # set_fields
2131
+
2132
+ describe "#fields_equal" do
2133
+ before(:each) do
2134
+ @st.visit("/form").should be_true
2135
+ end
2136
+ context "passes when" do
2137
+ context "text fields with labels" do
2138
+ it "sets one field" do
2139
+ @st.set_fields("First name" => "Marcus").should be_true
2140
+ @st.fields_equal("First name" => "Marcus").should be_true
2141
+ end
2142
+
2143
+ it "sets zero fields" do
2144
+ @st.fields_equal("").should be_true
2145
+ end
2146
+
2147
+ it "sets several fields" do
2148
+ @st.set_fields("First name" => "Ken", "Last name" => "Brazier", "Life story" => "My story\\; I get testy a lot.").should be_true
2149
+ @st.fields_equal("First name" => "Ken", "Last name" => "Brazier", "Life story" => "My story\\; I get testy a lot.").should be_true
2150
+ end
2151
+ end
2152
+ end
2153
+
2154
+ context "fails when" do
2155
+ context "text fields with labels" do
2156
+ it "cant find the first field" do
2157
+ @st.fields_equal("Faust name" => "", "Last name" => "").should be_false
2158
+ end
2159
+
2160
+ it "cant find the last field" do
2161
+ @st.fields_equal("First name" => "", "Lost name" => "").should be_false
2162
+ end
2163
+
2164
+ it "fields are not equal" do
2165
+ @st.fields_equal("First name" => "Ken", "Last name" => "Brazier").should be_false
2166
+ end
2167
+ end
2168
+ end
2169
+ end # fields_equal
2170
+
2171
+
2172
+ describe "#set_fields_among" do
2173
+ before(:each) do
2174
+ @st.visit("/form").should be_true
2175
+ end
2176
+ context "passes when" do
2177
+ context "text fields with labels" do
2178
+ it "sets one field" do
2179
+ @st.set_fields_among({"First name" => "Marcus"}).should be_true
2180
+ @st.field_contains("First name", "Marcus").should be_true
2181
+ end
2182
+
2183
+ it "sets one field with string ids" do
2184
+ @st.set_fields_among({"First name" => "Marcus"}, "").should be_true
2185
+ @st.field_contains("First name", "Marcus").should be_true
2186
+ end
2187
+
2188
+ it "does nothing, but has ids" do
2189
+ @st.set_fields_among("", {"First name" => "Marcus"}).should be_true
2190
+ end
2191
+
2192
+ it "sets several fields" do
2193
+ @st.set_fields_among({"First name" => "Ken", "Last name" => "Brazier", "Life story" => "My story\\; I get testy a lot."})
2194
+ @st.field_contains("First name", "Ken").should be_true
2195
+ @st.field_contains("Last name", "Brazier").should be_true
2196
+ @st.field_contains("Life story", "story: I get testy").should be_true
2197
+ end
2198
+ end
2199
+ context "text fields with labels in a hash" do
2200
+ it "sets one field from a hash" do
2201
+ @st.set_fields_among({"Faust name" => "Marcus"}, {"Faust Name" => "First name", "LOST name" => "Last name"}).should be_true
2202
+ @st.field_contains("First name", "Marcus").should be_true
2203
+ end
2204
+
2205
+ it "sets many fields, some from a hash" do
2206
+ @st.set_fields_among({"Faust\\;name" => "Ken", :Lost => "Brazier", "Life story" => "I get testy a lot."},
2207
+ {"Faust\\;Name" => "First name", :LOST => "Last name"}).should be_true
2208
+ @st.field_contains("First name", "Ken").should be_true
2209
+ @st.field_contains("Last name", "Brazier").should be_true
2210
+ @st.field_contains("Life story", "testy").should be_true
2211
+ end
2212
+ end
2213
+ end
2214
+
2215
+ context "fails when" do
2216
+ context "text fields with labels" do
2217
+ it "cant find the first field" do
2218
+ @st.set_fields_among({"Faust name" => "Ken", "Last name" => "Brazier"}).should be_false
2219
+ end
2220
+
2221
+ it "cant find the last field" do
2222
+ @st.set_fields_among({"First name" => "Ken", "Lost name" => "Brazier"}).should be_false
2223
+ end
2224
+ end
2225
+ context "text fields with labels in a hash" do
2226
+ it "cant find the first field" do
2227
+ @st.set_fields_among({"Faust name" => "Ken", "Lost name" => "Brazier"},
2228
+ {"Faust Name" => "Lost name", "Lost name" => "Last name"}).should be_false
2229
+ end
2230
+
2231
+ it "cant find the last field" do
2232
+ @st.set_fields_among({"Faust name" => "Ken", "Lost name" => "Brazier"},
2233
+ {"Faust Name" => "First name", "Lost name" => "Faust name"}).should be_false
2234
+ end
2235
+ end
2236
+ end
2237
+ end # set_fields_among
2238
+ end # generic_fields
2239
+
2240
+
2241
+ describe "#fields_equal_among" do
2242
+ before(:each) do
2243
+ @st.visit("/form").should be_true
2244
+ end
2245
+ context "passes when" do
2246
+ context "text fields with labels" do
2247
+ it "sets one field" do
2248
+ @st.set_fields_among({"First name" => "Marcus"}).should be_true
2249
+ @st.fields_equal_among({"First name" => "Marcus"}).should be_true
2250
+ end
2251
+
2252
+ it "sets one field with string ids" do
2253
+ @st.set_fields_among({"First name" => "Marcus"}, "").should be_true
2254
+ @st.fields_equal_among({"First name" => "Marcus"}, "").should be_true
2255
+ end
2256
+
2257
+ it "does nothing, but has ids" do
2258
+ @st.fields_equal_among("", {"First name" => "Marcus"}).should be_true
2259
+ end
2260
+
2261
+ it "sets several fields" do
2262
+ @st.set_fields_among({"First name" => "Ken", "Last name" => "Brazier", "Life story" => "My story\\; I get testy a lot."}).should be_true
2263
+ @st.fields_equal_among({"First name" => "Ken", "Last name" => "Brazier", "Life story" => "My story\\; I get testy a lot."}).should be_true
2264
+ end
2265
+ end
2266
+ context "text fields with labels in a hash" do
2267
+ it "sets one field from a hash" do
2268
+ @st.set_fields_among({"Faust name" => "Marcus"}, {"Faust Name" => "First name", "LOST name" => "Last name"}).should be_true
2269
+ @st.fields_equal_among({"Faust name" => "Marcus"}, {"Faust Name" => "First name", "LOST name" => "Last name"}).should be_true
2270
+ end
2271
+
2272
+ it "sets many fields, some from a hash" do
2273
+ @st.set_fields_among({"Faust\\;name" => "Ken", :Lost => "Brazier", "Life story" => "I get testy a lot."},
2274
+ {"Faust\\;Name" => "First name", :LOST => "Last name"}).should be_true
2275
+ @st.fields_equal_among({"Faust\\;name" => "Ken", :Lost => "Brazier", "Life story" => "I get testy a lot."},
2276
+ {"Faust\\;Name" => "First name", :LOST => "Last name"}).should be_true
2277
+ end
2278
+ end
2279
+ end
2280
+
2281
+ context "fails when" do
2282
+ context "text fields with labels" do
2283
+ it "cant find the first field" do
2284
+ @st.fields_equal_among({"Faust name" => "Ken", "Last name" => "Brazier"}).should be_false
2285
+ end
2286
+
2287
+ it "cant find the last field" do
2288
+ @st.fields_equal_among({"First name" => "Ken", "Lost name" => "Brazier"}).should be_false
2289
+ end
2290
+ it "does not equal the expected values" do
2291
+ @st.fields_equal_among({"First name" => "Ken", "Last name" => "Brazier", "Life story" => "My story\\; I get testy a lot."}).should be_false
2292
+ end
2293
+ end
2294
+ context "text fields with labels in a hash" do
2295
+ it "cant find the first field" do
2296
+ @st.fields_equal_among({"Faust name" => "Ken", "Lost name" => "Brazier"},
2297
+ {"Faust Name" => "Lost name", "Lost name" => "Last name"}).should be_false
2298
+ end
2299
+
2300
+ it "cant find the last field" do
2301
+ @st.fields_equal_among({"Faust name" => "Ken", "Lost name" => "Brazier"},
2302
+ {"Faust Name" => "First name", "Lost name" => "Faust name"}).should be_false
2303
+ end
2304
+ it "does not equal the expected values" do
2305
+ @st.fields_equal_among({"Faust\\;name" => "Ken", :Lost => "Brazier", "Life story" => "I get testy a lot."},
2306
+ {"Faust\\;Name" => "First name", :LOST => "Last name"}).should be_false
2307
+ end
2308
+ end
2309
+ end
2310
+ end # set_fields_among
2311
+ end # generic_fields
2312
+
2313
+
902
2314
 
903
2315
  context "tables" do
904
2316
  before(:each) do
@@ -924,17 +2336,17 @@ describe Rsel::SeleniumTest do
924
2336
  @st.row_exists("Eric, Pierce").should be_true
925
2337
  @st.row_exists("Pierce, epierce@example.com").should be_true
926
2338
  end
2339
+
2340
+ it "cell values are not consecutive" do
2341
+ @st.row_exists("First name, Email").should be_true
2342
+ @st.row_exists("Eric, epierce@example.com").should be_true
2343
+ end
927
2344
  end
928
2345
 
929
2346
  context "fails when" do
930
2347
  it "no row exists" do
931
2348
  @st.row_exists("Middle name, Maiden name, Email").should be_false
932
2349
  end
933
-
934
- it "cell values are not consecutive" do
935
- @st.row_exists("First name, Email").should be_false
936
- @st.row_exists("Eric, epierce@example.com").should be_false
937
- end
938
2350
  end
939
2351
  end
940
2352
 
@@ -967,9 +2379,33 @@ describe Rsel::SeleniumTest do
967
2379
  end
968
2380
  end
969
2381
  end
2382
+
2383
+ describe "#pause_seconds" do
2384
+ it "returns true" do
2385
+ @st.pause_seconds(0).should == true
2386
+ @st.pause_seconds(1).should == true
2387
+ end
2388
+ end
970
2389
  end # waiting
971
2390
 
972
2391
 
2392
+ context "method inspection" do
2393
+ describe "respond_to?" do
2394
+ it "returns true if a method is explicitly defined" do
2395
+ @st.respond_to?('see').should == true
2396
+ end
2397
+
2398
+ it "returns true if the Selenium::Client::Driver defines the method" do
2399
+ @st.respond_to?('is_element_present').should == true
2400
+ end
2401
+
2402
+ it "returns false if the method isn't defined" do
2403
+ @st.respond_to?('junk').should == false
2404
+ end
2405
+ end
2406
+ end
2407
+
2408
+
973
2409
  context "stop on failure" do
974
2410
  before(:each) do
975
2411
  @st.visit("/").should be_true
@@ -995,9 +2431,12 @@ describe Rsel::SeleniumTest do
995
2431
  end
996
2432
 
997
2433
  it "when #see_title fails" do
2434
+ @st.errors # clear errors
998
2435
  @st.see_title("Wrong Title").should be_false
999
2436
  # Would pass, but previous step failed
1000
2437
  @st.see_title("Rsel Test Site").should be_false
2438
+ # Should see one and only one error.
2439
+ @st.errors.should eq("Page title is 'Rsel Test Site', not 'Wrong Title'")
1001
2440
  end
1002
2441
 
1003
2442
  it "when #do_not_see_title fails" do
@@ -1165,38 +2604,53 @@ describe Rsel::SeleniumTest do
1165
2604
  end # stop on failure
1166
2605
 
1167
2606
 
1168
- context "Selenium::Client::Driver wrapper" do
1169
- before(:each) do
1170
- @st.visit("/form").should be_true
1171
- end
2607
+ describe "#method_missing" do
2608
+ context "method is defined in Selenium::Client::Driver" do
2609
+ before(:each) do
2610
+ @st.visit("/form").should be_true
2611
+ end
2612
+
2613
+ context "method returning Boolean" do
2614
+ it "passes if method returns true" do
2615
+ @st.is_element_present("id=first_name").should be_true
2616
+ @st.is_visible("id=first_name").should be_true
2617
+ @st.is_text_present("This page has some random forms").should be_true
2618
+ end
1172
2619
 
1173
- context "method returning Boolean" do
1174
- it "passes if method returns true" do
1175
- @st.is_element_present("id=first_name").should be_true
1176
- @st.is_visible("id=first_name").should be_true
1177
- @st.is_text_present("This page has some random forms").should be_true
2620
+ it "fails if method returns false" do
2621
+ @st.is_element_present("id=bogus_id").should be_false
2622
+ @st.is_visible("id=bogus_id").should be_false
2623
+ @st.is_text_present("This text is not there").should be_false
2624
+ end
1178
2625
  end
1179
2626
 
1180
- it "fails if method returns false" do
1181
- @st.is_element_present("id=bogus_id").should be_false
1182
- @st.is_visible("id=bogus_id").should be_false
1183
- @st.is_text_present("This text is not there").should be_false
2627
+ context "method returning String" do
2628
+ it "returns the String" do
2629
+ @st.get_text("id=salami_checkbox").should eq("I like salami")
2630
+ end
1184
2631
  end
1185
- end
1186
2632
 
1187
- context "method not returning Boolean" do
1188
- it "passes if method doesn't raise an exception" do
1189
- @st.get_title.should be_true
1190
- @st.mouse_over("id=first_name").should be_true
2633
+ context "method not returning Boolean or String" do
2634
+ it "passes if method doesn't raise an exception" do
2635
+ @st.get_title.should be_true
2636
+ @st.mouse_over("id=first_name").should be_true
2637
+ end
2638
+
2639
+ it "fails if method raises an exception" do
2640
+ @st.double_click("id=bogus_id").should be_false
2641
+ @st.mouse_over("id=bogus_id").should be_false
2642
+ end
1191
2643
  end
2644
+ end # Selenium::Client::Driver
1192
2645
 
1193
- it "fails if method raises an exception" do
1194
- @st.double_click("id=bogus_id").should be_false
1195
- @st.mouse_over("id=bogus_id").should be_false
2646
+ context "method is not defined in Selenium::Client::Driver" do
2647
+ it "raises an exception" do
2648
+ lambda do
2649
+ @st.really_undefined_method
2650
+ end.should raise_error
1196
2651
  end
1197
2652
  end
1198
-
1199
- end # Selenium::Client::Driver wrapper
2653
+ end # method_missing
1200
2654
 
1201
2655
  end
1202
2656