rsel 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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