watir 6.15.1 → 6.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -2
  3. data/.travis.yml +2 -0
  4. data/CHANGES.md +13 -0
  5. data/Rakefile +6 -0
  6. data/lib/watir.rb +1 -0
  7. data/lib/watir/browser.rb +4 -1
  8. data/lib/watir/element_collection.rb +27 -17
  9. data/lib/watir/elements/element.rb +41 -14
  10. data/lib/watir/elements/iframe.rb +3 -1
  11. data/lib/watir/elements/radio.rb +7 -2
  12. data/lib/watir/elements/select.rb +1 -0
  13. data/lib/watir/locators.rb +21 -21
  14. data/lib/watir/locators/button/matcher.rb +40 -0
  15. data/lib/watir/locators/cell/selector_builder.rb +3 -0
  16. data/lib/watir/locators/element/locator.rb +29 -172
  17. data/lib/watir/locators/element/matcher.rb +127 -0
  18. data/lib/watir/locators/element/selector_builder.rb +69 -23
  19. data/lib/watir/locators/element/selector_builder/xpath.rb +3 -10
  20. data/lib/watir/locators/row/selector_builder.rb +5 -5
  21. data/lib/watir/locators/text_area/selector_builder.rb +0 -14
  22. data/lib/watir/locators/text_area/selector_builder/xpath.rb +2 -2
  23. data/lib/watir/locators/text_field/matcher.rb +38 -0
  24. data/lib/watir/radio_set.rb +28 -31
  25. data/lib/watir/scroll.rb +69 -0
  26. data/lib/watir/version.rb +1 -1
  27. data/spec/locator_spec_helper.rb +58 -14
  28. data/spec/unit/element_locator_spec.rb +46 -591
  29. data/spec/unit/match_elements/button_spec.rb +80 -0
  30. data/spec/unit/match_elements/element_spec.rb +368 -0
  31. data/spec/unit/match_elements/text_field_spec.rb +79 -0
  32. data/spec/unit/selector_builder/anchor_spec.rb +51 -0
  33. data/spec/unit/selector_builder/button_spec.rb +206 -0
  34. data/spec/unit/selector_builder/cell_spec.rb +63 -0
  35. data/spec/unit/selector_builder/element_spec.rb +744 -0
  36. data/spec/unit/selector_builder/row_spec.rb +111 -0
  37. data/spec/unit/selector_builder/text_field_spec.rb +189 -0
  38. data/spec/unit/selector_builder/textarea_spec.rb +25 -0
  39. data/spec/watirspec/browser_spec.rb +7 -8
  40. data/spec/watirspec/element_hidden_spec.rb +1 -2
  41. data/spec/watirspec/elements/element_spec.rb +52 -16
  42. data/spec/watirspec/elements/iframe_spec.rb +1 -1
  43. data/spec/watirspec/elements/select_list_spec.rb +1 -1
  44. data/spec/watirspec/html/obscured.html +3 -1
  45. data/spec/watirspec/html/scroll.html +32 -0
  46. data/spec/watirspec/relaxed_locate_spec.rb +6 -1
  47. data/spec/watirspec/scroll_spec.rb +106 -0
  48. data/spec/watirspec/support/rspec_matchers.rb +2 -0
  49. data/spec/watirspec/wait_spec.rb +1 -1
  50. data/watir.gemspec +2 -4
  51. metadata +36 -33
  52. data/lib/watir/locators/button/locator.rb +0 -32
  53. data/lib/watir/locators/button/validator.rb +0 -17
  54. data/lib/watir/locators/cell/locator.rb +0 -13
  55. data/lib/watir/locators/element/validator.rb +0 -11
  56. data/lib/watir/locators/row/locator.rb +0 -13
  57. data/lib/watir/locators/text_field/locator.rb +0 -31
  58. data/lib/watir/locators/text_field/validator.rb +0 -13
  59. data/spec/unit/anchor_locator_spec.rb +0 -68
  60. data/spec/watirspec/selector_builder/button_spec.rb +0 -250
  61. data/spec/watirspec/selector_builder/cell_spec.rb +0 -92
  62. data/spec/watirspec/selector_builder/element_spec.rb +0 -628
  63. data/spec/watirspec/selector_builder/row_spec.rb +0 -148
  64. data/spec/watirspec/selector_builder/text_spec.rb +0 -199
@@ -1,148 +0,0 @@
1
- require 'watirspec_helper'
2
-
3
- describe Watir::Locators::Row::SelectorBuilder do
4
- let(:attributes) { Watir::HTMLElement.attribute_list }
5
- let(:selector_builder) { described_class.new(attributes, @scope_tag_name) }
6
-
7
- describe '#build' do
8
- after(:each) do |example|
9
- next if example.metadata[:skip_after]
10
-
11
- @scope_tag_name ||= @query_scope.tag_name
12
-
13
- expect(selector_builder.build(@selector)).to eq @built
14
-
15
- next unless @data_locator || @tag_name
16
-
17
- expect { @located = @query_scope.wd.first(@built) }.not_to raise_exception
18
-
19
- if @data_locator
20
- expect(@located.attribute('data-locator')).to eq(@data_locator)
21
- else
22
- expect {
23
- expect(@located.tag_name).to eq @tag_name
24
- }.not_to raise_exception
25
- end
26
- end
27
-
28
- context 'with query scopes' do
29
- before(:each) do
30
- browser.goto(WatirSpec.url_for('tables.html'))
31
- end
32
-
33
- it 'with only table query scope' do
34
- @query_scope = browser.element(id: 'outer').locate
35
- @selector = {}
36
- @built = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
37
- "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr']"}
38
- @data_locator = 'first row'
39
- end
40
-
41
- it 'with tbody query scope' do
42
- @query_scope = browser.element(id: 'first').locate
43
- @selector = {}
44
- @built = {xpath: "./*[local-name()='tr']"}
45
- @data_locator = 'tbody row'
46
- end
47
-
48
- it 'with thead query scope' do
49
- @query_scope = browser.element(id: 'tax_headers').locate
50
- @selector = {}
51
- @built = {xpath: "./*[local-name()='tr']"}
52
- @data_locator = 'thead row'
53
- end
54
-
55
- it 'with tfoot query scope' do
56
- @query_scope = browser.element(id: 'tax_totals').locate
57
- @selector = {}
58
- @built = {xpath: "./*[local-name()='tr']"}
59
- @data_locator = 'tfoot row'
60
- end
61
- end
62
-
63
- context 'with index' do
64
- before(:each) do
65
- browser.goto(WatirSpec.url_for('tables.html'))
66
- end
67
-
68
- it 'positive' do
69
- @query_scope = browser.element(id: 'outer').locate
70
- @selector = {index: 1}
71
- @built = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
72
- "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr'])[2]"}
73
- @data_locator = 'middle row'
74
- end
75
-
76
- it 'negative' do
77
- @query_scope = browser.element(id: 'outer').locate
78
- @selector = {index: -3}
79
- @built = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
80
- "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr'])[last()-2]"}
81
- @data_locator = 'first row'
82
- end
83
-
84
- it 'last' do
85
- @query_scope = browser.element(id: 'outer').locate
86
- @selector = {index: -1}
87
- @built = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
88
- "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr'])[last()]"}
89
- @data_locator = 'last row'
90
- end
91
-
92
- it 'does not return index if it is zero' do
93
- @query_scope = browser.element(id: 'outer').locate
94
- @selector = {index: 0}
95
- @built = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
96
- "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr']"}
97
- @data_locator = 'first row'
98
- end
99
-
100
- it 'raises exception when index is not an Integer', skip_after: true do
101
- @query_scope = browser.element(id: 'outer').locate
102
- selector = {index: 'foo'}
103
- msg = /expected one of \[(Integer|Fixnum)\], got "foo":String/
104
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
105
- end
106
- end
107
-
108
- context 'with multiple locators' do
109
- before(:each) do
110
- browser.goto(WatirSpec.url_for('tables.html'))
111
- @query_scope = browser.table.locate
112
- end
113
-
114
- it 'attribute and class' do
115
- @selector = {id: 'gregory', class: /brick/}
116
- @built = {xpath: "./*[local-name()='tr'][contains(@class, 'brick')][@id='gregory'] | " \
117
- "./*[local-name()='tbody']/*[local-name()='tr'][contains(@class, 'brick')][@id='gregory'] | " \
118
- "./*[local-name()='thead']/*[local-name()='tr'][contains(@class, 'brick')][@id='gregory'] | " \
119
- "./*[local-name()='tfoot']/*[local-name()='tr'][contains(@class, 'brick')][@id='gregory']"}
120
- @data_locator = 'House row'
121
- end
122
- end
123
-
124
- context 'returns locators that can not be directly translated' do
125
- before(:each) do
126
- browser.goto(WatirSpec.url_for('tables.html'))
127
- @query_scope = browser.table(id: 'outer').locate
128
- end
129
-
130
- it 'any text value' do
131
- @selector = {text: 'Gregory'}
132
- @built = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
133
- "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr']", text: 'Gregory'}
134
- end
135
- end
136
-
137
- it 'delegates adjacent to Element SelectorBuilder' do
138
- browser.goto(WatirSpec.url_for('tables.html'))
139
-
140
- @scope_tag_name = 'table'
141
- @query_scope = browser.element(id: 'gregory').locate
142
-
143
- @selector = {adjacent: :ancestor, index: 1}
144
- @built = {xpath: './ancestor::*[2]'}
145
- @data_locator = 'top table'
146
- end
147
- end
148
- end
@@ -1,199 +0,0 @@
1
- require 'watirspec_helper'
2
-
3
- describe Watir::Locators::TextField::SelectorBuilder do
4
- let(:attributes) { Watir::HTMLElement.attribute_list }
5
- let(:scope_tag_name) { nil }
6
- let(:selector_builder) { described_class.new(attributes) }
7
- let(:uppercase) { 'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ' }
8
- let(:lowercase) { 'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ' }
9
- let(:negative_types) do
10
- "translate(@type,'#{uppercase}','#{lowercase}')!='file' and "\
11
- "translate(@type,'#{uppercase}','#{lowercase}')!='radio' and " \
12
- "translate(@type,'#{uppercase}','#{lowercase}')!='checkbox' and " \
13
- "translate(@type,'#{uppercase}','#{lowercase}')!='submit' and " \
14
- "translate(@type,'#{uppercase}','#{lowercase}')!='reset' and " \
15
- "translate(@type,'#{uppercase}','#{lowercase}')!='image' and " \
16
- "translate(@type,'#{uppercase}','#{lowercase}')!='button' and " \
17
- "translate(@type,'#{uppercase}','#{lowercase}')!='hidden' and " \
18
- "translate(@type,'#{uppercase}','#{lowercase}')!='range' and " \
19
- "translate(@type,'#{uppercase}','#{lowercase}')!='color' and " \
20
- "translate(@type,'#{uppercase}','#{lowercase}')!='date' and " \
21
- "translate(@type,'#{uppercase}','#{lowercase}')!='datetime-local'"
22
- end
23
-
24
- describe '#build' do
25
- after(:each) do |example|
26
- next if example.metadata[:skip_after]
27
-
28
- @query_scope ||= browser
29
-
30
- expect(selector_builder.build(@selector)).to eq @built
31
-
32
- next unless @data_locator || @tag_name
33
-
34
- expect { @located = @query_scope.wd.first(@built) }.not_to raise_exception
35
-
36
- if @data_locator
37
- expect(@located.attribute('data-locator')).to eq(@data_locator)
38
- else
39
- expect {
40
- expect(@located.tag_name).to eq @tag_name
41
- }.not_to raise_exception
42
- end
43
- end
44
-
45
- it 'without any arguments' do
46
- browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
47
- @selector = {}
48
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]"}
49
- @data_locator = 'input name'
50
- end
51
-
52
- context 'with type' do
53
- before(:each) { browser.goto(WatirSpec.url_for('forms_with_input_elements.html')) }
54
-
55
- it 'specified text field type that is text' do
56
- @selector = {type: 'text'}
57
- @built = {xpath: ".//*[local-name()='input']" \
58
- "[translate(@type,'#{uppercase}','#{lowercase}')='text']"}
59
- @data_locator = 'first text'
60
- end
61
-
62
- it 'specified text field type that is not text' do
63
- @selector = {type: 'number'}
64
- @built = {xpath: ".//*[local-name()='input']" \
65
- "[translate(@type,'#{uppercase}','#{lowercase}')='number']"}
66
- @data_locator = '42'
67
- end
68
-
69
- it 'true locates text field with a type specified' do
70
- @selector = {type: true}
71
- @built = {xpath: ".//*[local-name()='input'][#{negative_types}]"}
72
- @data_locator = 'input name'
73
- end
74
-
75
- it 'false locates text field without type specified' do
76
- @selector = {type: false}
77
- @built = {xpath: ".//*[local-name()='input'][not(@type)]"}
78
- @data_locator = 'input name'
79
- end
80
-
81
- it 'raises exception when a non-text field type input is specified', skip_after: true do
82
- selector = {type: 'checkbox'}
83
- msg = 'TextField Elements can not be located by type: checkbox'
84
- expect { selector_builder.build(selector) }
85
- .to raise_exception Watir::Exception::LocatorException, msg
86
- end
87
- end
88
-
89
- context 'with index' do
90
- before(:each) do
91
- browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
92
- end
93
-
94
- it 'positive' do
95
- @selector = {index: 4}
96
- @built = {xpath: "(.//*[local-name()='input'][not(@type) or (#{negative_types})])[5]"}
97
- @data_locator = 'dev'
98
- end
99
-
100
- it 'negative' do
101
- @selector = {index: -3}
102
- @built = {xpath: "(.//*[local-name()='input'][not(@type) or (#{negative_types})])[last()-2]"}
103
- @data_locator = '42'
104
- end
105
-
106
- it 'last' do
107
- @selector = {index: -1}
108
- @built = {xpath: "(.//*[local-name()='input'][not(@type) or (#{negative_types})])[last()]"}
109
- @data_locator = 'last text'
110
- end
111
-
112
- it 'does not return index if it is zero' do
113
- @selector = {index: 0}
114
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]"}
115
- @data_locator = 'input name'
116
- end
117
-
118
- it 'raises exception when index is not an Integer', skip_after: true do
119
- selector = {index: 'foo'}
120
- msg = /expected one of \[(Integer|Fixnum)\], got "foo":String/
121
- expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
122
- end
123
- end
124
-
125
- context 'with text' do
126
- before(:each) { browser.goto(WatirSpec.url_for('forms_with_input_elements.html')) }
127
-
128
- it 'String for value' do
129
- @selector = {text: 'Developer'}
130
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]", text: 'Developer'}
131
- end
132
-
133
- it 'Simple Regexp for value' do
134
- @selector = {text: /Dev/}
135
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]", text: /Dev/}
136
- end
137
-
138
- it 'returns complicated Regexp to the locator as a value' do
139
- @selector = {text: /^foo$/}
140
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]", text: /^foo$/}
141
- end
142
- end
143
-
144
- context 'with label' do
145
- before(:each) { browser.goto(WatirSpec.url_for('forms_with_input_elements.html')) }
146
-
147
- it 'using String' do
148
- @selector = {label: 'First name'}
149
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]" \
150
- "[@id=//label[normalize-space()='First name']/@for or parent::label[normalize-space()='First name']]"}
151
- @data_locator = 'input name'
152
- end
153
-
154
- it 'uses String with hidden text' do
155
- @selector = {label: 'With hidden text'}
156
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]" \
157
- "[@id=//label[normalize-space()='With hidden text']/@for or parent::label[normalize-space()='With hidden text']]"}
158
- @data_locator = 'hidden'
159
- end
160
-
161
- # Desired Behavior
162
- xit 'using simple Regexp' do
163
- @selector = {label: /First/}
164
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]" \
165
- "[@id=//label[contains(text(), 'First')]/@for or parent::label[contains(text(), 'First')]]"}
166
- @data_locator = 'input name'
167
- end
168
-
169
- # Desired Behavior
170
- xit 'using complex Regexp' do
171
- @selector = {label: /([qa])st? name/}
172
- @built = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]" \
173
- "[@id=//label[contains(text(), 's') and contains(text(), ' name')]/@for or " \
174
- "parent::label[contains(text(), 's') and contains(text(), ' name')]]", label_element: /([qa])st? name/}
175
- end
176
- end
177
-
178
- context 'with multiple locators' do
179
- before(:each) do
180
- browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
181
- end
182
-
183
- it 'locates using tag name, class, attributes and text' do
184
- @selector = {text: 'Developer', class: /c/, id: true}
185
- @built = {xpath: ".//*[local-name()='input'][contains(@class, 'c')]" \
186
- "[not(@type) or (#{negative_types})][@id]", text: 'Developer'}
187
- end
188
-
189
- it 'delegates adjacent to Element SelectorBuilder' do
190
- browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
191
- @query_scope = browser.element(id: 'new_user_email').locate
192
-
193
- @selector = {adjacent: :ancestor, index: 1}
194
- @built = {xpath: './ancestor::*[2]'}
195
- @data_locator = 'form'
196
- end
197
- end
198
- end
199
- end