rsel 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/docs/history.md +8 -0
- data/docs/scoping.md +43 -7
- data/docs/todo.md +1 -3
- data/lib/rsel/selenium_test.rb +83 -20
- data/rsel.gemspec +1 -1
- data/spec/selenium_test_spec.rb +277 -66
- data/test/app.rb +2 -14
- data/test/views/edit_eric.erb +7 -0
- data/test/views/edit_marcus.erb +7 -0
- data/test/views/favicon.ico.erb +0 -0
- data/test/views/form.erb +7 -1
- data/test/views/table.erb +44 -2
- metadata +7 -4
data/docs/history.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
Rsel History
|
2
2
|
============
|
3
3
|
|
4
|
+
0.0.4
|
5
|
+
-----
|
6
|
+
|
7
|
+
- Added `in_row` to scope, for narrowing scope to a specific table row
|
8
|
+
- Many more methods accept scope hash now
|
9
|
+
- Added (working) `radio_is_enabled` and `radio_is_disabled` methods
|
10
|
+
|
11
|
+
|
4
12
|
0.0.3
|
5
13
|
-----
|
6
14
|
|
data/docs/scoping.md
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
Scoping
|
2
|
-
|
2
|
+
=======
|
3
3
|
|
4
4
|
Several of the actions and verifications accept an optional hash of scoping
|
5
5
|
keywords, allowing you to be specific about what area of the page to operate
|
6
|
-
on.
|
7
|
-
|
6
|
+
on. This page describes how to use them.
|
7
|
+
|
8
|
+
|
9
|
+
within
|
10
|
+
------
|
11
|
+
|
12
|
+
Say you have a page of contact information with HTML that looks something like
|
13
|
+
this:
|
8
14
|
|
9
15
|
<div id="work">
|
10
16
|
<label for="work_phone">Phone number</label>
|
@@ -43,6 +49,36 @@ Yeah I know, we're still using an `id` which could be annoyingly long, but if
|
|
43
49
|
there are a lot of fields in each container, you only need to keep track of one
|
44
50
|
`id` instead of several.
|
45
51
|
|
52
|
+
|
53
|
+
in_row
|
54
|
+
------
|
55
|
+
|
56
|
+
Another kind of scoping that can be useful is `in_row`, which selects only the
|
57
|
+
elements that are in the same table row as a given piece of text. For example,
|
58
|
+
a common approach to editing or deleting items in a list is to place links next
|
59
|
+
to those items in an HTML table:
|
60
|
+
|
61
|
+
<table>
|
62
|
+
<tr><th>Name</th> <th>Actions</th></tr>
|
63
|
+
<tr><td>Eric</td> <td><a href="/edit/eric">Edit</a></td></tr>
|
64
|
+
<tr><td>Marcus</td> <td><a href="/edit/marcus">Edit</a></td></tr>
|
65
|
+
<tr><td>Ken</td> <td><a href="/edit/ken">Edit</a></td></tr>
|
66
|
+
</table>
|
67
|
+
|
68
|
+
Here, we have three "Edit" links. Clicking "Edit" without any scoping qualifier
|
69
|
+
is ambiguous, and would simply use the first match. If you want to click the
|
70
|
+
"Edit" link in a specific row, include an `in_row` scope with some text that is
|
71
|
+
unique to that row:
|
72
|
+
|
73
|
+
| Click | Edit | link | !{in_row:Marcus} |
|
74
|
+
|
75
|
+
This works for any method that accepts scoping qualifiers, so you can use it to
|
76
|
+
operate on checkboxes, dropdowns, or text fields as well.
|
77
|
+
|
78
|
+
|
79
|
+
Caveat
|
80
|
+
------
|
81
|
+
|
46
82
|
One important thing to note is that due to the way FitNesse Slim script tables
|
47
83
|
are evaluated, the scoping hash must be added after a cell that contains part
|
48
84
|
of the method name. Cells in these tables must contain alternating (function,
|
@@ -63,10 +99,10 @@ be treated as arguments. These are valid alternative ways of calling the same fu
|
|
63
99
|
The `SeleniumTest` method names were, for the most part, crafted so that the
|
64
100
|
alternating (function, argument) form reads the most naturally.
|
65
101
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
102
|
+
Additional scoping qualifiers may be added to Rsel if they prove useful. If you
|
103
|
+
have a use case that isn't covered by the existing scopes, please [submit an
|
104
|
+
issue](http://github.com/a-e/rsel/issues), or better yet, implement it yourself
|
105
|
+
and submit a pull request. See [Development](development.md) for more info.
|
70
106
|
|
71
107
|
Next: [Customization](custom.md)
|
72
108
|
|
data/docs/todo.md
CHANGED
@@ -7,8 +7,6 @@ To-do list
|
|
7
7
|
mark the step as failed)
|
8
8
|
- Find a way to abort a test if something goes catastrophically wrong (such as
|
9
9
|
being unable to connect to the Selenium server)
|
10
|
-
- Verify the presence of images,
|
11
|
-
- Click on images
|
12
|
-
- Support scoping qualifiers (somewhat like Kelp does)
|
10
|
+
- Verify the presence of images, allow clicking on images
|
13
11
|
|
14
12
|
Next: [History](history.md)
|
data/lib/rsel/selenium_test.rb
CHANGED
@@ -305,9 +305,10 @@ module Rsel
|
|
305
305
|
#
|
306
306
|
# @example
|
307
307
|
# | Field | First name | equals | Eric |
|
308
|
+
# | Field | First name | equals; | Eric | !{within:contact} |
|
308
309
|
#
|
309
|
-
def field_equals(locator, text)
|
310
|
-
@browser.field(xpath('field', locator)) == text
|
310
|
+
def field_equals(locator, text, scope={})
|
311
|
+
@browser.field(xpath('field', locator, scope)) == text
|
311
312
|
end
|
312
313
|
|
313
314
|
|
@@ -319,10 +320,11 @@ module Rsel
|
|
319
320
|
# @example
|
320
321
|
# | Click | Next |
|
321
322
|
# | Click | Logout |
|
323
|
+
# | Click; | Logout | !{within:header} |
|
322
324
|
#
|
323
|
-
def click(locator)
|
325
|
+
def click(locator, scope={})
|
324
326
|
return_error_status do
|
325
|
-
@browser.click(xpath('link_or_button', locator))
|
327
|
+
@browser.click(xpath('link_or_button', locator, scope))
|
326
328
|
end
|
327
329
|
end
|
328
330
|
|
@@ -338,6 +340,7 @@ module Rsel
|
|
338
340
|
# | Click | Logout | link |
|
339
341
|
# | Follow | Logout |
|
340
342
|
# | Click | Logout | link | !{within:header} |
|
343
|
+
# | Click | Edit | link | !{in_row:Eric} |
|
341
344
|
#
|
342
345
|
def click_link(locator, scope={})
|
343
346
|
return_error_status do
|
@@ -408,7 +411,7 @@ module Rsel
|
|
408
411
|
end
|
409
412
|
|
410
413
|
|
411
|
-
# Verify that a given checkbox
|
414
|
+
# Verify that a given checkbox is enabled (checked)
|
412
415
|
#
|
413
416
|
# @param [String] locator
|
414
417
|
# Label, value, or id of the checkbox to inspect
|
@@ -417,9 +420,7 @@ module Rsel
|
|
417
420
|
#
|
418
421
|
# @example
|
419
422
|
# | Checkbox | send me spam | is enabled |
|
420
|
-
# | Radio | medium | is enabled |
|
421
423
|
# | Checkbox | send me spam | is enabled | !{within:opt_in} |
|
422
|
-
# | Radio | medium | is enabled | !{within:shirt_size} |
|
423
424
|
#
|
424
425
|
def checkbox_is_enabled(locator, scope={})
|
425
426
|
xp = xpath('checkbox', locator, scope)
|
@@ -431,10 +432,34 @@ module Rsel
|
|
431
432
|
return enabled
|
432
433
|
end
|
433
434
|
end
|
434
|
-
alias_method :radio_is_enabled, :checkbox_is_enabled
|
435
435
|
|
436
436
|
|
437
|
-
# Verify that a given
|
437
|
+
# Verify that a given radio button is enabled (checked)
|
438
|
+
#
|
439
|
+
# @param [String] locator
|
440
|
+
# Label, value, or id of the radio button to inspect
|
441
|
+
# @param [Hash] scope
|
442
|
+
# Scoping keywords as understood by {#xpath}
|
443
|
+
#
|
444
|
+
# @example
|
445
|
+
# | Radio | medium | is enabled |
|
446
|
+
# | Radio | medium | is enabled | !{within:shirt_size} |
|
447
|
+
#
|
448
|
+
# @since 0.0.4
|
449
|
+
#
|
450
|
+
def radio_is_enabled(locator, scope={})
|
451
|
+
xp = xpath('radio_button', locator, scope)
|
452
|
+
begin
|
453
|
+
enabled = @browser.checked?(xp)
|
454
|
+
rescue
|
455
|
+
return false
|
456
|
+
else
|
457
|
+
return enabled
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
|
462
|
+
# Verify that a given checkbox is disabled (unchecked)
|
438
463
|
#
|
439
464
|
# @param [String] locator
|
440
465
|
# Label, value, or id of the checkbox to inspect
|
@@ -443,9 +468,7 @@ module Rsel
|
|
443
468
|
#
|
444
469
|
# @example
|
445
470
|
# | Checkbox | send me spam | is disabled |
|
446
|
-
# | Radio | medium | is disabled |
|
447
471
|
# | Checkbox | send me spam | is disabled | !{within:opt_in} |
|
448
|
-
# | Radio | medium | is disabled | !{within:shirt_size} |
|
449
472
|
#
|
450
473
|
def checkbox_is_disabled(locator, scope={})
|
451
474
|
xp = xpath('checkbox', locator, scope)
|
@@ -457,7 +480,31 @@ module Rsel
|
|
457
480
|
return !enabled
|
458
481
|
end
|
459
482
|
end
|
460
|
-
|
483
|
+
|
484
|
+
|
485
|
+
# Verify that a given radio button is disabled (unchecked)
|
486
|
+
#
|
487
|
+
# @param [String] locator
|
488
|
+
# Label, value, or id of the radio button to inspect
|
489
|
+
# @param [Hash] scope
|
490
|
+
# Scoping keywords as understood by {#xpath}
|
491
|
+
#
|
492
|
+
# @example
|
493
|
+
# | Radio | medium | is disabled |
|
494
|
+
# | Radio | medium | is disabled | !{within:shirt_size} |
|
495
|
+
#
|
496
|
+
# @since 0.0.4
|
497
|
+
#
|
498
|
+
def radio_is_disabled(locator, scope={})
|
499
|
+
xp = xpath('radio_button', locator, scope)
|
500
|
+
begin
|
501
|
+
enabled = @browser.checked?(xp)
|
502
|
+
rescue
|
503
|
+
return false
|
504
|
+
else
|
505
|
+
return !enabled
|
506
|
+
end
|
507
|
+
end
|
461
508
|
|
462
509
|
|
463
510
|
# Select a radio button.
|
@@ -508,7 +555,8 @@ module Rsel
|
|
508
555
|
#
|
509
556
|
# @since 0.0.2
|
510
557
|
#
|
511
|
-
def dropdown_includes(locator, option)
|
558
|
+
def dropdown_includes(locator, option, scope={})
|
559
|
+
# TODO: Apply scope
|
512
560
|
dropdown = XPath::HTML.select(locator)
|
513
561
|
opt = dropdown[XPath::HTML.option(option)]
|
514
562
|
opt_str = opt.to_s
|
@@ -528,7 +576,8 @@ module Rsel
|
|
528
576
|
#
|
529
577
|
# @since 0.0.2
|
530
578
|
#
|
531
|
-
def dropdown_equals(locator, option)
|
579
|
+
def dropdown_equals(locator, option, scope={})
|
580
|
+
# TODO: Apply scope
|
532
581
|
begin
|
533
582
|
selected = @browser.get_selected_label(xpath('select', locator))
|
534
583
|
rescue
|
@@ -582,6 +631,7 @@ module Rsel
|
|
582
631
|
begin
|
583
632
|
yield
|
584
633
|
rescue => e
|
634
|
+
#puts e.message
|
585
635
|
#puts e.backtrace
|
586
636
|
return false
|
587
637
|
else
|
@@ -604,6 +654,9 @@ module Rsel
|
|
604
654
|
# @option scope [String] :within
|
605
655
|
# Restrict scope to elements having this id, matching `locator` only if
|
606
656
|
# it's contained within an element with this id.
|
657
|
+
# @option scope [String] :in_row
|
658
|
+
# Restrict scope to a table row containing this text, matching `locator`
|
659
|
+
# only if that locator is in the same row as the given text.
|
607
660
|
#
|
608
661
|
# @example
|
609
662
|
# xpath('link', 'Log in')
|
@@ -615,12 +668,10 @@ module Rsel
|
|
615
668
|
loc_xp = XPath::HTML.send(kind, locator)
|
616
669
|
if scope[:within]
|
617
670
|
parent = XPath.descendant[XPath.attr(:id).equals(scope[:within])]
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
end
|
623
|
-
result = XPath::Union.new(*scoped_expressions).to_s
|
671
|
+
result = apply_scope(parent, loc_xp)
|
672
|
+
elsif scope[:in_row]
|
673
|
+
row = XPath.descendant(:tr)[XPath.contains(scope[:in_row])]
|
674
|
+
result = apply_scope(row, loc_xp)
|
624
675
|
else
|
625
676
|
result = loc_xp.to_s
|
626
677
|
end
|
@@ -628,6 +679,18 @@ module Rsel
|
|
628
679
|
end
|
629
680
|
|
630
681
|
|
682
|
+
# Restrict the scope of all XPath expressions in `inner` by prepending
|
683
|
+
# `container` to each of them, and return new union expression where
|
684
|
+
# `inner` matches only if it's a child of `container`.
|
685
|
+
#
|
686
|
+
def apply_scope(container, inner)
|
687
|
+
scoped_expressions = xpath_expressions(inner).collect do |expr|
|
688
|
+
container.child(expr)
|
689
|
+
end
|
690
|
+
return XPath::Union.new(*scoped_expressions).to_s
|
691
|
+
end
|
692
|
+
|
693
|
+
|
631
694
|
# Return an array of individual Expressions in the given XPath::Union, or
|
632
695
|
# just `[union]` if it has no sub-expressions. This is an ugly recursive
|
633
696
|
# hack, designed to allow splitting up unions into their constituents for
|
data/rsel.gemspec
CHANGED
data/spec/selenium_test_spec.rb
CHANGED
@@ -14,27 +14,34 @@ describe Rsel::SeleniumTest do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
|
17
|
-
context "
|
17
|
+
context "checkboxes" do
|
18
18
|
before(:each) do
|
19
19
|
@st.visit("/form").should be_true
|
20
20
|
end
|
21
21
|
|
22
22
|
describe "#enable_checkbox" do
|
23
|
-
context "
|
24
|
-
context "
|
25
|
-
it "
|
23
|
+
context "passes when" do
|
24
|
+
context "checkbox with label" do
|
25
|
+
it "exists" do
|
26
26
|
@st.enable_checkbox("I like cheese").should be_true
|
27
27
|
@st.enable_checkbox("I like salami").should be_true
|
28
28
|
end
|
29
29
|
|
30
|
-
it "
|
30
|
+
it "exists within scope" do
|
31
31
|
@st.enable_checkbox("I like cheese", :within => "cheese_checkbox").should be_true
|
32
32
|
@st.enable_checkbox("I like salami", :within => "salami_checkbox").should be_true
|
33
33
|
end
|
34
|
+
|
35
|
+
it "exists in table row" do
|
36
|
+
@st.visit("/table")
|
37
|
+
@st.enable_checkbox("Like", :in_row => "Marcus").should be_true
|
38
|
+
end
|
34
39
|
end
|
40
|
+
end
|
35
41
|
|
36
|
-
|
37
|
-
|
42
|
+
context "fails when" do
|
43
|
+
context "checkbox with label" do
|
44
|
+
it "does not exist" do
|
38
45
|
@st.enable_checkbox("I dislike bacon").should be_false
|
39
46
|
@st.enable_checkbox("I like broccoli").should be_false
|
40
47
|
end
|
@@ -43,26 +50,38 @@ describe Rsel::SeleniumTest do
|
|
43
50
|
@st.enable_checkbox("I like cheese", :within => "salami_checkbox").should be_false
|
44
51
|
@st.enable_checkbox("I like salami", :within => "cheese_checkbox").should be_false
|
45
52
|
end
|
53
|
+
|
54
|
+
it "exists, but not in table row" do
|
55
|
+
@st.visit("/table")
|
56
|
+
@st.enable_checkbox("Like", :in_row => "Eric").should be_false
|
57
|
+
end
|
46
58
|
end
|
47
59
|
end
|
48
60
|
end
|
49
61
|
|
50
62
|
describe "#disable_checkbox" do
|
51
|
-
context "
|
52
|
-
context "
|
53
|
-
it "
|
63
|
+
context "passes when" do
|
64
|
+
context "checkbox with label" do
|
65
|
+
it "exists" do
|
54
66
|
@st.disable_checkbox("I like cheese").should be_true
|
55
67
|
@st.disable_checkbox("I like salami").should be_true
|
56
68
|
end
|
57
69
|
|
58
|
-
it "
|
70
|
+
it "exists within scope" do
|
59
71
|
@st.disable_checkbox("I like cheese", :within => "cheese_checkbox").should be_true
|
60
72
|
@st.disable_checkbox("I like salami", :within => "preferences_form").should be_true
|
61
73
|
end
|
74
|
+
|
75
|
+
it "exists in table row" do
|
76
|
+
@st.visit("/table")
|
77
|
+
@st.disable_checkbox("Like", :in_row => "Marcus").should be_true
|
78
|
+
end
|
62
79
|
end
|
80
|
+
end
|
63
81
|
|
64
|
-
|
65
|
-
|
82
|
+
context "fails when" do
|
83
|
+
context "checkbox with label" do
|
84
|
+
it "does not exist" do
|
66
85
|
@st.disable_checkbox("I dislike bacon").should be_false
|
67
86
|
@st.disable_checkbox("I like broccoli").should be_false
|
68
87
|
end
|
@@ -71,13 +90,18 @@ describe Rsel::SeleniumTest do
|
|
71
90
|
@st.disable_checkbox("I like cheese", :within => "salami_checkbox").should be_false
|
72
91
|
@st.disable_checkbox("I like salami", :within => "cheese_checkbox").should be_false
|
73
92
|
end
|
93
|
+
|
94
|
+
it "exists, but not in table row" do
|
95
|
+
@st.visit("/table")
|
96
|
+
@st.disable_checkbox("Like", :in_row => "Eric").should be_false
|
97
|
+
end
|
74
98
|
end
|
75
99
|
end
|
76
100
|
end
|
77
101
|
|
78
102
|
describe "#checkbox_is_enabled" do
|
79
|
-
context "
|
80
|
-
context "
|
103
|
+
context "passes when" do
|
104
|
+
context "checkbox with label" do
|
81
105
|
it "exists and is checked" do
|
82
106
|
@st.enable_checkbox("I like cheese").should be_true
|
83
107
|
@st.checkbox_is_enabled("I like cheese").should be_true
|
@@ -87,9 +111,21 @@ describe Rsel::SeleniumTest do
|
|
87
111
|
@st.enable_checkbox("I like cheese", :within => "cheese_checkbox").should be_true
|
88
112
|
@st.checkbox_is_enabled("I like cheese", :within => "cheese_checkbox").should be_true
|
89
113
|
end
|
114
|
+
|
115
|
+
it "exists in table row and is checked" do
|
116
|
+
@st.visit("/table")
|
117
|
+
@st.enable_checkbox("Like", :in_row => "Ken").should be_true
|
118
|
+
@st.checkbox_is_enabled("Like", :in_row => "Ken").should be_true
|
119
|
+
end
|
90
120
|
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "fails when" do
|
124
|
+
context "checkbox with label" do
|
125
|
+
it "does not exist" do
|
126
|
+
@st.checkbox_is_enabled("I dislike bacon").should be_false
|
127
|
+
end
|
91
128
|
|
92
|
-
context "fails when" do
|
93
129
|
it "exists but is unchecked" do
|
94
130
|
@st.disable_checkbox("I like cheese").should be_true
|
95
131
|
@st.checkbox_is_enabled("I like cheese").should be_false
|
@@ -100,16 +136,18 @@ describe Rsel::SeleniumTest do
|
|
100
136
|
@st.checkbox_is_enabled("I like cheese", :within => "salami_checkbox").should be_false
|
101
137
|
end
|
102
138
|
|
103
|
-
it "
|
104
|
-
@st.
|
139
|
+
it "exists and is checked, but not in table row" do
|
140
|
+
@st.visit("/table")
|
141
|
+
@st.enable_checkbox("Like", :in_row => "Marcus").should be_true
|
142
|
+
@st.checkbox_is_enabled("Like", :in_row => "Eric").should be_false
|
105
143
|
end
|
106
144
|
end
|
107
145
|
end
|
108
146
|
end
|
109
147
|
|
110
148
|
describe "#checkbox_is_disabled" do
|
111
|
-
context "
|
112
|
-
context "
|
149
|
+
context "passes when" do
|
150
|
+
context "checkbox with label" do
|
113
151
|
it "exists and is unchecked" do
|
114
152
|
@st.disable_checkbox("I like cheese").should be_true
|
115
153
|
@st.checkbox_is_disabled("I like cheese").should be_true
|
@@ -119,9 +157,21 @@ describe Rsel::SeleniumTest do
|
|
119
157
|
@st.disable_checkbox("I like cheese", :within => "cheese_checkbox").should be_true
|
120
158
|
@st.checkbox_is_disabled("I like cheese", :within => "cheese_checkbox").should be_true
|
121
159
|
end
|
160
|
+
|
161
|
+
it "exists in table row and is unchecked" do
|
162
|
+
@st.visit("/table")
|
163
|
+
@st.disable_checkbox("Like", :in_row => "Ken").should be_true
|
164
|
+
@st.checkbox_is_disabled("Like", :in_row => "Ken").should be_true
|
165
|
+
end
|
122
166
|
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "fails when" do
|
170
|
+
context "checkbox with label" do
|
171
|
+
it "does not exist" do
|
172
|
+
@st.checkbox_is_disabled("I dislike bacon").should be_false
|
173
|
+
end
|
123
174
|
|
124
|
-
context "fails when" do
|
125
175
|
it "exists but is checked" do
|
126
176
|
@st.enable_checkbox("I like cheese").should be_true
|
127
177
|
@st.checkbox_is_disabled("I like cheese").should be_false
|
@@ -132,8 +182,89 @@ describe Rsel::SeleniumTest do
|
|
132
182
|
@st.checkbox_is_disabled("I like cheese", :within => "salami_checkbox").should be_false
|
133
183
|
end
|
134
184
|
|
185
|
+
it "exists and is unchecked, but not in table row" do
|
186
|
+
@st.visit("/table")
|
187
|
+
@st.disable_checkbox("Like", :in_row => "Marcus").should be_true
|
188
|
+
@st.checkbox_is_disabled("Like", :in_row => "Eric").should be_false
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
context "radiobuttons" do
|
197
|
+
before(:each) do
|
198
|
+
@st.visit("/form").should be_true
|
199
|
+
end
|
200
|
+
|
201
|
+
context "#select_radio" do
|
202
|
+
context "passes when" do
|
203
|
+
context "radiobutton with label" do
|
204
|
+
it "exists" do
|
205
|
+
@st.select_radio("Briefs").should be_true
|
206
|
+
end
|
207
|
+
|
208
|
+
it "exists within scope" do
|
209
|
+
@st.select_radio("Briefs", :within => "clothing").should be_true
|
210
|
+
end
|
211
|
+
|
212
|
+
it "exists in table row" do
|
213
|
+
# TODO
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context "fails when" do
|
219
|
+
context "radiobutton with label" do
|
135
220
|
it "does not exist" do
|
136
|
-
@st.
|
221
|
+
@st.select_radio("Naked").should be_false
|
222
|
+
end
|
223
|
+
|
224
|
+
it "exists, but not within scope" do
|
225
|
+
@st.select_radio("Briefs", :within => "food").should be_false
|
226
|
+
end
|
227
|
+
|
228
|
+
it "exists, but not in table row" do
|
229
|
+
# TODO
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context "#radio_is_enabled" do
|
236
|
+
context "passes when" do
|
237
|
+
context "radiobutton with label" do
|
238
|
+
it "exists, and is enabled" do
|
239
|
+
@st.select_radio("Briefs")
|
240
|
+
@st.radio_is_enabled("Briefs").should be_true
|
241
|
+
end
|
242
|
+
|
243
|
+
it "exists within scope, and is enabled" do
|
244
|
+
@st.select_radio("Briefs", :within => "clothing")
|
245
|
+
@st.radio_is_enabled("Briefs", :within => "clothing").should be_true
|
246
|
+
end
|
247
|
+
|
248
|
+
it "exists in table row, and is enabled" do
|
249
|
+
# TODO
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
context "fails when" do
|
255
|
+
context "radiobutton with label" do
|
256
|
+
it "does not exist" do
|
257
|
+
@st.radio_is_enabled("Naked").should be_false
|
258
|
+
end
|
259
|
+
|
260
|
+
it "exists, but is not enabled" do
|
261
|
+
@st.select_radio("Briefs")
|
262
|
+
@st.radio_is_enabled("Boxers").should be_false
|
263
|
+
end
|
264
|
+
|
265
|
+
it "exists and is enabled, but not within scope" do
|
266
|
+
@st.select_radio("Briefs", :within => "clothing")
|
267
|
+
@st.radio_is_enabled("Briefs", :within => "food").should be_false
|
137
268
|
end
|
138
269
|
end
|
139
270
|
end
|
@@ -156,9 +287,18 @@ describe Rsel::SeleniumTest do
|
|
156
287
|
it "option exists in the dropdown within scope" do
|
157
288
|
@st.select_from_dropdown("Tall", "Height", :within => "spouse_form").should be_true
|
158
289
|
end
|
290
|
+
|
291
|
+
it "option exists in the dropdown in table row" do
|
292
|
+
@st.visit("/table")
|
293
|
+
@st.select_from_dropdown("Male", "Gender", :in_row => "Eric").should be_true
|
294
|
+
end
|
159
295
|
end
|
160
296
|
|
161
297
|
context "fails when" do
|
298
|
+
it "no such dropdown exists" do
|
299
|
+
@st.select_from_dropdown("Over easy", "Eggs").should be_false
|
300
|
+
end
|
301
|
+
|
162
302
|
it "dropdown exists, but the option doesn't" do
|
163
303
|
@st.select_from_dropdown("Giant", "Height").should be_false
|
164
304
|
@st.select_from_dropdown("Obese", "Weight").should be_false
|
@@ -168,8 +308,9 @@ describe Rsel::SeleniumTest do
|
|
168
308
|
@st.select_from_dropdown("Medium", "Weight", :within => "spouse_form").should be_false
|
169
309
|
end
|
170
310
|
|
171
|
-
it "
|
172
|
-
@st.
|
311
|
+
it "dropdown exists, but not in table row" do
|
312
|
+
@st.visit("/table")
|
313
|
+
@st.select_from_dropdown("Female", "Gender", :in_row => "First name").should be_false
|
173
314
|
end
|
174
315
|
end
|
175
316
|
end
|
@@ -284,6 +425,12 @@ describe Rsel::SeleniumTest do
|
|
284
425
|
it "link exists within scope" do
|
285
426
|
@st.click_link("About this site", :within => "header").should be_true
|
286
427
|
end
|
428
|
+
|
429
|
+
it "link exists in table row" do
|
430
|
+
@st.visit("/table")
|
431
|
+
@st.click_link("Edit", :in_row => "Marcus").should be_true
|
432
|
+
@st.see_title("Editing Marcus").should be_true
|
433
|
+
end
|
287
434
|
end
|
288
435
|
|
289
436
|
context "fails when" do
|
@@ -294,6 +441,11 @@ describe Rsel::SeleniumTest do
|
|
294
441
|
it "link exists, but not within scope" do
|
295
442
|
@st.click_link("About this site", :within => "footer").should be_false
|
296
443
|
end
|
444
|
+
|
445
|
+
it "link exists, but not in table row" do
|
446
|
+
@st.visit("/table")
|
447
|
+
@st.click_link("Edit", :in_row => "Ken").should be_false
|
448
|
+
end
|
297
449
|
end
|
298
450
|
end
|
299
451
|
|
@@ -341,6 +493,10 @@ describe Rsel::SeleniumTest do
|
|
341
493
|
it "button exists within scope" do
|
342
494
|
@st.click_button("Submit person form", :within => "person_form").should be_true
|
343
495
|
end
|
496
|
+
|
497
|
+
it "button exists in table row" do
|
498
|
+
# TODO
|
499
|
+
end
|
344
500
|
end
|
345
501
|
|
346
502
|
context "fails when" do
|
@@ -352,22 +508,33 @@ describe Rsel::SeleniumTest do
|
|
352
508
|
@st.click_button("Submit person form", :within => "spouse_form").should be_false
|
353
509
|
end
|
354
510
|
|
355
|
-
it "button exists but
|
511
|
+
it "button exists, but not in table row" do
|
512
|
+
# TODO
|
513
|
+
end
|
514
|
+
|
515
|
+
it "button exists, but is disabled" do
|
356
516
|
# TODO
|
357
517
|
end
|
358
518
|
end
|
359
519
|
end
|
360
520
|
|
521
|
+
|
361
522
|
describe "#button_exists" do
|
362
523
|
context "passes when" do
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
524
|
+
context "button with text" do
|
525
|
+
it "exists" do
|
526
|
+
@st.button_exists("Submit person form").should be_true
|
527
|
+
@st.button_exists("Save preferences").should be_true
|
528
|
+
end
|
367
529
|
|
368
|
-
|
369
|
-
|
370
|
-
|
530
|
+
it "exists within scope" do
|
531
|
+
@st.button_exists("Submit person form", :within => "person_form").should be_true
|
532
|
+
@st.button_exists("Submit spouse form", :within => "spouse_form").should be_true
|
533
|
+
end
|
534
|
+
|
535
|
+
it "exists in table row" do
|
536
|
+
# TODO
|
537
|
+
end
|
371
538
|
end
|
372
539
|
end
|
373
540
|
|
@@ -381,6 +548,10 @@ describe Rsel::SeleniumTest do
|
|
381
548
|
@st.button_exists("Submit spouse form", :within => "person_form").should be_false
|
382
549
|
@st.button_exists("Submit person form", :within => "spouse_form").should be_false
|
383
550
|
end
|
551
|
+
|
552
|
+
it "button exists, but not in table row" do
|
553
|
+
# TODO
|
554
|
+
end
|
384
555
|
end
|
385
556
|
end
|
386
557
|
end
|
@@ -393,29 +564,36 @@ describe Rsel::SeleniumTest do
|
|
393
564
|
|
394
565
|
describe "#type_into_field" do
|
395
566
|
context "passes when" do
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
567
|
+
context "text field with label" do
|
568
|
+
it "exists" do
|
569
|
+
@st.type_into_field("Eric", "First name").should be_true
|
570
|
+
@st.fill_in_with("Last name", "Pierce").should be_true
|
571
|
+
end
|
572
|
+
it "exists within scope" do
|
573
|
+
@st.type_into_field("Eric", "First name", :within => 'person_form').should be_true
|
574
|
+
@st.type_into_field("Andrea", "First name", :within => 'spouse_form').should be_true
|
575
|
+
end
|
404
576
|
end
|
405
577
|
|
406
|
-
|
407
|
-
|
408
|
-
|
578
|
+
context "text field with id" do
|
579
|
+
it "exists" do
|
580
|
+
@st.type_into_field("Eric", "first_name").should be_true
|
581
|
+
@st.fill_in_with("last_name", "Pierce").should be_true
|
582
|
+
end
|
409
583
|
end
|
410
584
|
|
411
|
-
|
412
|
-
|
413
|
-
|
585
|
+
context "textarea with label" do
|
586
|
+
it "exists" do
|
587
|
+
@st.type_into_field("Blah blah blah", "Life story").should be_true
|
588
|
+
@st.fill_in_with("Life story", "Jibber jabber").should be_true
|
589
|
+
end
|
414
590
|
end
|
415
591
|
|
416
|
-
|
417
|
-
|
418
|
-
|
592
|
+
context "textarea with id" do
|
593
|
+
it "exists" do
|
594
|
+
@st.type_into_field("Blah blah blah", "biography").should be_true
|
595
|
+
@st.fill_in_with("biography", "Jibber jabber").should be_true
|
596
|
+
end
|
419
597
|
end
|
420
598
|
end
|
421
599
|
|
@@ -433,32 +611,64 @@ describe Rsel::SeleniumTest do
|
|
433
611
|
|
434
612
|
describe "#field_contains" do
|
435
613
|
context "passes when" do
|
436
|
-
|
437
|
-
|
438
|
-
|
614
|
+
context "textarea with label" do
|
615
|
+
it "contains the text" do
|
616
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
617
|
+
@st.field_contains("Life story", "blah").should be_true
|
618
|
+
end
|
439
619
|
end
|
440
620
|
end
|
441
621
|
|
442
622
|
context "fails when" do
|
443
|
-
|
444
|
-
|
445
|
-
|
623
|
+
context "textarea with label" do
|
624
|
+
it "does not contain the text" do
|
625
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
626
|
+
@st.field_contains("Life story", "spam").should be_false
|
627
|
+
end
|
446
628
|
end
|
447
629
|
end
|
448
630
|
end
|
449
631
|
|
450
632
|
describe "#field_equals" do
|
451
633
|
context "passes when" do
|
452
|
-
|
453
|
-
|
454
|
-
|
634
|
+
context "text field with label" do
|
635
|
+
# TODO
|
636
|
+
end
|
637
|
+
|
638
|
+
context "textarea with label" do
|
639
|
+
it "equals the text" do
|
640
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
641
|
+
@st.field_equals("Life story", "Blah dee blah").should be_true
|
642
|
+
end
|
643
|
+
|
644
|
+
it "equals the text, and is within scope" do
|
645
|
+
# TODO
|
646
|
+
end
|
647
|
+
|
648
|
+
it "equals the text, and is in table row" do
|
649
|
+
# TODO
|
650
|
+
end
|
455
651
|
end
|
456
652
|
end
|
457
653
|
|
458
654
|
context "fails when" do
|
459
|
-
|
460
|
-
|
461
|
-
|
655
|
+
context "text field with label" do
|
656
|
+
# TODO
|
657
|
+
end
|
658
|
+
|
659
|
+
context "textarea with label" do
|
660
|
+
it "does not exactly equal the text" do
|
661
|
+
@st.fill_in_with("Life story", "Blah dee blah")
|
662
|
+
@st.field_equals("Life story", "Blah dee").should be_false
|
663
|
+
end
|
664
|
+
|
665
|
+
it "exactly equals the text, but is not within scope" do
|
666
|
+
# TODO
|
667
|
+
end
|
668
|
+
|
669
|
+
it "exactly equals the text, but is not in table row" do
|
670
|
+
# TODO
|
671
|
+
end
|
462
672
|
end
|
463
673
|
end
|
464
674
|
end
|
@@ -522,21 +732,21 @@ describe Rsel::SeleniumTest do
|
|
522
732
|
describe "#row_exists" do
|
523
733
|
context "passes when" do
|
524
734
|
it "full row of headings exists" do
|
525
|
-
@st.row_exists("First name, Last name,
|
735
|
+
@st.row_exists("First name, Last name, Email").should be_true
|
526
736
|
end
|
527
737
|
|
528
738
|
it "partial row of headings exists" do
|
529
739
|
@st.row_exists("First name, Last name").should be_true
|
530
|
-
@st.row_exists("
|
740
|
+
@st.row_exists("Last name, Email").should be_true
|
531
741
|
end
|
532
742
|
|
533
743
|
it "full row of cells exists" do
|
534
|
-
@st.row_exists("Eric, Pierce, epierce
|
744
|
+
@st.row_exists("Eric, Pierce, epierce@example.com").should be_true
|
535
745
|
end
|
536
746
|
|
537
747
|
it "partial row of cells exists" do
|
538
748
|
@st.row_exists("Eric, Pierce").should be_true
|
539
|
-
@st.row_exists("
|
749
|
+
@st.row_exists("Pierce, epierce@example.com").should be_true
|
540
750
|
end
|
541
751
|
end
|
542
752
|
|
@@ -547,10 +757,11 @@ describe Rsel::SeleniumTest do
|
|
547
757
|
|
548
758
|
it "cell values are not consecutive" do
|
549
759
|
@st.row_exists("First name, Email").should be_false
|
550
|
-
@st.row_exists("Eric, epierce").should be_false
|
760
|
+
@st.row_exists("Eric, epierce@example.com").should be_false
|
551
761
|
end
|
552
762
|
end
|
553
763
|
end
|
764
|
+
|
554
765
|
end
|
555
766
|
end
|
556
767
|
|
data/test/app.rb
CHANGED
@@ -13,20 +13,8 @@ class TestApp < Sinatra::Base
|
|
13
13
|
erb :index
|
14
14
|
end
|
15
15
|
|
16
|
-
get '
|
17
|
-
erb
|
18
|
-
end
|
19
|
-
|
20
|
-
get '/form' do
|
21
|
-
erb :form
|
22
|
-
end
|
23
|
-
|
24
|
-
get '/table' do
|
25
|
-
erb :table
|
26
|
-
end
|
27
|
-
|
28
|
-
get '/thanks' do
|
29
|
-
erb :thanks
|
16
|
+
get '/:view' do |view|
|
17
|
+
erb view.to_sym
|
30
18
|
end
|
31
19
|
|
32
20
|
# Allow shutting down the app with a request
|
File without changes
|
data/test/views/form.erb
CHANGED
@@ -80,7 +80,13 @@
|
|
80
80
|
<label for="like_salami">I like salami</label>
|
81
81
|
<input id="like_salami" type="checkbox" />
|
82
82
|
</p>
|
83
|
-
<
|
83
|
+
<p id="clothing">
|
84
|
+
<label for="boxers">Boxers</label>
|
85
|
+
<input id="boxers" type="radio" name="underwear" value="boxers" />
|
86
|
+
<label for="briefs">Briefs</label>
|
87
|
+
<input id="briefs" type="radio" name="underwear" value="briefs" />
|
88
|
+
</p>
|
89
|
+
<table id="food">
|
84
90
|
<tr>
|
85
91
|
<th>Apple</th>
|
86
92
|
<td>
|
data/test/views/table.erb
CHANGED
@@ -8,14 +8,56 @@
|
|
8
8
|
<tr>
|
9
9
|
<th>First name</th>
|
10
10
|
<th>Last name</th>
|
11
|
-
<th>Nickname</th>
|
12
11
|
<th>Email</th>
|
12
|
+
<th>Actions</th>
|
13
13
|
</tr>
|
14
14
|
<tr>
|
15
15
|
<td>Eric</td>
|
16
16
|
<td>Pierce</td>
|
17
|
-
<td>epierce</td>
|
18
17
|
<td>epierce@example.com</td>
|
18
|
+
<td>
|
19
|
+
<a href="/edit_eric">Edit</a>
|
20
|
+
|
21
|
+
<label for="eric_gender">Gender</a>
|
22
|
+
<select id="eric_gender">
|
23
|
+
<option value="male">Male</option>
|
24
|
+
<option value="female">Female</option>
|
25
|
+
</select>
|
26
|
+
</td>
|
27
|
+
</tr>
|
28
|
+
<tr>
|
29
|
+
<td>Marcus</td>
|
30
|
+
<td>French</td>
|
31
|
+
<td>mfrench@example.com</td>
|
32
|
+
<td>
|
33
|
+
<a href="/edit_marcus">Edit</a>
|
34
|
+
|
35
|
+
<label for="like_marcus">Like</label>
|
36
|
+
<input id="like_marcus" type="checkbox"/>
|
37
|
+
|
38
|
+
<label for="marcus_gender">Gender</a>
|
39
|
+
<select id="marcus_gender">
|
40
|
+
<option value="male">Male</option>
|
41
|
+
<option value="female">Female</option>
|
42
|
+
</select>
|
43
|
+
</td>
|
44
|
+
</tr>
|
45
|
+
<tr>
|
46
|
+
<td>Ken</td>
|
47
|
+
<td>Brazier</td>
|
48
|
+
<td>kbrazier@example.com</td>
|
49
|
+
<td>
|
50
|
+
(read-only)
|
51
|
+
|
52
|
+
<label for="like_ken">Like</label>
|
53
|
+
<input id="like_ken" type="checkbox"/>
|
54
|
+
|
55
|
+
<label for="ken_gender">Gender</a>
|
56
|
+
<select id="ken_gender">
|
57
|
+
<option value="male">Male</option>
|
58
|
+
<option value="female">Female</option>
|
59
|
+
</select>
|
60
|
+
</td>
|
19
61
|
</tr>
|
20
62
|
</table>
|
21
63
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Marcus French
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-07-
|
20
|
+
date: 2011-07-25 00:00:00 -06:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -170,6 +170,9 @@ files:
|
|
170
170
|
- test/app.rb
|
171
171
|
- test/config.ru
|
172
172
|
- test/views/about.erb
|
173
|
+
- test/views/edit_eric.erb
|
174
|
+
- test/views/edit_marcus.erb
|
175
|
+
- test/views/favicon.ico.erb
|
173
176
|
- test/views/form.erb
|
174
177
|
- test/views/index.erb
|
175
178
|
- test/views/table.erb
|