watir 6.16.2 → 6.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +5 -5
  2. data/.github/actions/enable-safari/action.yml +11 -0
  3. data/.github/actions/install-chrome/action.yml +11 -0
  4. data/.github/workflows/linux.yml +61 -0
  5. data/.github/workflows/mac.yml +55 -0
  6. data/.github/workflows/unit.yml +31 -0
  7. data/.github/workflows/windows.yml +39 -0
  8. data/.rubocop.yml +32 -107
  9. data/.rubocop_todo.yml +36 -0
  10. data/CHANGES.md +42 -0
  11. data/Gemfile +3 -1
  12. data/LICENSE +2 -2
  13. data/README.md +9 -10
  14. data/Rakefile +4 -4
  15. data/lib/watir-webdriver.rb +1 -1
  16. data/lib/watir.rb +1 -1
  17. data/lib/watir/adjacent.rb +8 -10
  18. data/lib/watir/after_hooks.rb +4 -4
  19. data/lib/watir/alert.rb +1 -0
  20. data/lib/watir/attribute_helper.rb +2 -0
  21. data/lib/watir/browser.rb +7 -3
  22. data/lib/watir/capabilities.rb +9 -6
  23. data/lib/watir/cookies.rb +3 -1
  24. data/lib/watir/element_collection.rb +21 -6
  25. data/lib/watir/elements/element.rb +66 -53
  26. data/lib/watir/elements/file_field.rb +1 -0
  27. data/lib/watir/elements/html_elements.rb +0 -1
  28. data/lib/watir/elements/iframe.rb +4 -3
  29. data/lib/watir/elements/link.rb +0 -9
  30. data/lib/watir/elements/radio.rb +1 -1
  31. data/lib/watir/elements/select.rb +22 -7
  32. data/lib/watir/generator/base/spec_extractor.rb +4 -4
  33. data/lib/watir/generator/html/generator.rb +1 -1
  34. data/lib/watir/has_window.rb +17 -15
  35. data/lib/watir/js_execution.rb +3 -3
  36. data/lib/watir/js_snippets.rb +2 -2
  37. data/lib/watir/legacy_wait.rb +1 -1
  38. data/lib/watir/locators.rb +1 -3
  39. data/lib/watir/locators/element/locator.rb +22 -12
  40. data/lib/watir/locators/element/selector_builder.rb +12 -13
  41. data/lib/watir/locators/element/selector_builder/xpath.rb +40 -13
  42. data/lib/watir/locators/text_field/matcher.rb +1 -1
  43. data/lib/watir/locators/text_field/selector_builder/xpath.rb +3 -1
  44. data/lib/watir/logger.rb +7 -20
  45. data/lib/watir/radio_set.rb +2 -2
  46. data/lib/watir/user_editable.rb +6 -2
  47. data/lib/watir/version.rb +1 -1
  48. data/lib/watir/wait.rb +2 -0
  49. data/lib/watir/wait/timer.rb +1 -1
  50. data/lib/watir/window.rb +8 -4
  51. data/lib/watir/window_collection.rb +105 -0
  52. data/lib/watirspec.rb +2 -1
  53. data/lib/watirspec/guards.rb +1 -1
  54. data/lib/watirspec/implementation.rb +3 -5
  55. data/lib/watirspec/rake_tasks.rb +2 -0
  56. data/lib/watirspec/runner.rb +5 -1
  57. data/lib/watirspec/server.rb +1 -1
  58. data/spec/spec_helper.rb +2 -7
  59. data/spec/unit/container_spec.rb +1 -1
  60. data/spec/unit/logger_spec.rb +5 -7
  61. data/spec/unit/match_elements/element_spec.rb +17 -15
  62. data/spec/unit/selector_builder/button_spec.rb +16 -15
  63. data/spec/unit/selector_builder/element_spec.rb +58 -9
  64. data/spec/unit/selector_builder/text_field_spec.rb +14 -14
  65. data/spec/unit/unit_helper.rb +2 -4
  66. data/spec/watirspec/after_hooks_spec.rb +58 -68
  67. data/spec/watirspec/alert_spec.rb +69 -79
  68. data/spec/watirspec/browser_spec.rb +51 -48
  69. data/spec/watirspec/cookies_spec.rb +52 -37
  70. data/spec/watirspec/drag_and_drop_spec.rb +14 -38
  71. data/spec/watirspec/elements/button_spec.rb +2 -0
  72. data/spec/watirspec/elements/buttons_spec.rb +1 -1
  73. data/spec/watirspec/elements/checkbox_spec.rb +8 -4
  74. data/spec/watirspec/elements/date_field_spec.rb +18 -9
  75. data/spec/watirspec/elements/date_time_field_spec.rb +3 -4
  76. data/spec/watirspec/elements/div_spec.rb +62 -54
  77. data/spec/watirspec/elements/element_spec.rb +73 -88
  78. data/spec/watirspec/elements/elements_spec.rb +12 -3
  79. data/spec/watirspec/elements/filefield_spec.rb +25 -50
  80. data/spec/watirspec/elements/form_spec.rb +6 -8
  81. data/spec/watirspec/elements/frame_spec.rb +10 -13
  82. data/spec/watirspec/elements/iframe_spec.rb +12 -9
  83. data/spec/watirspec/elements/iframes_spec.rb +2 -2
  84. data/spec/watirspec/elements/link_spec.rb +23 -12
  85. data/spec/watirspec/elements/links_spec.rb +11 -3
  86. data/spec/watirspec/elements/option_spec.rb +15 -17
  87. data/spec/watirspec/elements/select_list_spec.rb +222 -117
  88. data/spec/watirspec/elements/text_field_spec.rb +8 -4
  89. data/spec/watirspec/elements/tr_spec.rb +0 -9
  90. data/spec/watirspec/html/forms_with_input_elements.html +1 -0
  91. data/spec/watirspec/html/iframes.html +3 -0
  92. data/spec/watirspec/html/non_control_elements.html +4 -4
  93. data/spec/watirspec/html/right_click.html +12 -0
  94. data/spec/watirspec/html/wait.html +6 -6
  95. data/spec/watirspec/html/window_switching.html +10 -0
  96. data/spec/watirspec/legacy_wait_spec.rb +216 -0
  97. data/spec/watirspec/support/rspec_matchers.rb +17 -13
  98. data/spec/watirspec/user_editable_spec.rb +1 -1
  99. data/spec/watirspec/wait_spec.rb +257 -305
  100. data/spec/watirspec/window_switching_spec.rb +332 -211
  101. data/spec/watirspec_helper.rb +16 -19
  102. data/support/doctest_helper.rb +0 -2
  103. data/watir.gemspec +6 -7
  104. metadata +36 -26
  105. data/.travis.yml +0 -84
  106. data/appveyor.yml +0 -12
  107. data/lib/watir/elements/area.rb +0 -10
  108. data/spec/watirspec/relaxed_locate_spec.rb +0 -113
@@ -5,7 +5,7 @@ describe Watir::UserEditable do
5
5
  browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
6
6
  end
7
7
 
8
- not_compliant_on :safari do
8
+ bug 'incorrectly clears first', :safari do
9
9
  describe '#append' do
10
10
  it 'appends the text to the text field' do
11
11
  browser.text_field(name: 'new_user_occupation').append(' Append This')
@@ -1,400 +1,352 @@
1
1
  require 'watirspec_helper'
2
2
 
3
- describe Watir::Element do
4
- before do
5
- browser.goto WatirSpec.url_for('wait.html')
6
- end
7
-
8
- # TODO: This is deprecated; remove in future version
9
- not_compliant_on :relaxed_locate do
10
- describe '#when_present' do
11
- it 'invokes subsequent method calls when the element becomes present' do
12
- browser.a(id: 'show_bar').click
13
-
14
- bar = browser.div(id: 'bar')
15
- bar.when_present(2).click
16
- expect(bar.text).to eq 'changed'
17
- end
18
-
19
- it 'times out when given a block' do
20
- expect { browser.div(id: 'bar').when_present(1) {} }.to raise_error(Watir::Wait::TimeoutError)
21
- end
22
-
23
- it 'times out when not given a block' do
24
- locator = '(\{:id=>"bar", :tag_name=>"div"\}|\{:tag_name=>"div", :id=>"bar"\})'
25
- msg = /^timed out after 1 seconds, waiting for #{locator} to become present$/
26
- expect { browser.div(id: 'bar').when_present(1).click }.to raise_error(Watir::Wait::TimeoutError, msg)
27
- end
28
-
29
- it 'responds to Element methods' do
30
- decorator = browser.div.when_present
3
+ compliant_on :relaxed_locate do
4
+ describe Watir do
5
+ before do
6
+ browser.goto WatirSpec.url_for('wait.html')
7
+ end
31
8
 
32
- expect(decorator).to respond_to(:exist?)
33
- expect(decorator).to respond_to(:present?)
34
- expect(decorator).to respond_to(:click)
35
- end
9
+ describe '#default_timeout' do
10
+ context 'when no timeout is specified' do
11
+ it 'is used by Wait#until' do
12
+ expect { Watir::Wait.until { false } }.to wait_and_raise_timeout_exception(timeout: 1)
13
+ end
36
14
 
37
- it 'delegates present? to element' do
38
- Object.class_eval do
39
- def present?
40
- false
41
- end
15
+ it 'is used by Wait#while' do
16
+ expect { Watir::Wait.while { true } }.to wait_and_raise_timeout_exception(timeout: 1)
42
17
  end
43
- element = browser.a(id: 'show_bar').when_present(1)
44
- expect(element).to be_present
45
- end
46
18
 
47
- it 'processes before calling present?' do
48
- browser.a(id: 'show_bar').click
49
- expect(browser.div(id: 'bar').when_present.present?).to be true
19
+ it 'ensures all checks happen once even if time has expired' do
20
+ Watir.default_timeout = -1
21
+ expect { browser.link.click }.to_not raise_exception
22
+ ensure
23
+ Watir.default_timeout = 30
24
+ end
50
25
  end
51
26
  end
52
27
  end
53
28
 
54
- compliant_on :relaxed_locate do
55
- it 'clicking automatically waits until the element appears' do
56
- browser.a(id: 'show_bar').click
57
- expect { browser.div(id: 'bar').click }.to_not raise_exception
58
- expect(browser.div(id: 'bar').text).to eq 'changed'
59
- end
60
-
61
- it "raises exception if the element doesn't appear" do
62
- expect { browser.div(id: 'bar').click }.to raise_unknown_object_exception
63
- end
64
-
65
- it "raises exception if the element doesn't become enabled" do
66
- expect { browser.button(id: 'btn').click }.to raise_object_disabled_exception
29
+ describe Watir::Element do
30
+ before do
31
+ browser.goto WatirSpec.url_for('wait.html')
67
32
  end
68
- end
69
-
70
- not_compliant_on :relaxed_locate do
71
- describe '#wait_until &:enabled?' do
72
- it 'invokes subsequent method calls when the element becomes enabled' do
73
- browser.a(id: 'enable_btn').click
74
33
 
75
- btn = browser.button(id: 'btn')
76
- btn.wait_until(timeout: 2, &:enabled?).click
77
- Watir::Wait.while { btn.enabled? }
78
- expect(btn.disabled?).to be true
34
+ describe '#wait_until' do
35
+ it 'returns element for additional actions' do
36
+ element = browser.div(id: 'foo')
37
+ expect(element.wait_until(&:exist?)).to eq element
79
38
  end
80
39
 
81
- it 'times out' do
82
- error = Watir::Wait::TimeoutError
83
- inspected = '#<Watir::Button: located: true; {:id=>"btn", :tag_name=>"button"}>'
84
- message = "timed out after 1 seconds, waiting for true condition on #{inspected}"
85
- element = browser.button(id: 'btn')
86
- expect { element.wait_until(timeout: 1, &:enabled?).click }.to raise_error(error, message)
40
+ it 'accepts self in block' do
41
+ element = browser.div(id: 'bar')
42
+ browser.a(id: 'show_bar').click
43
+ expect { element.wait_until { |el| el.text == 'bar' } }.to_not raise_exception
87
44
  end
88
45
 
89
- it 'responds to Element methods' do
90
- element = browser.button.wait_until { true }
91
-
92
- expect(element).to respond_to(:exist?)
93
- expect(element).to respond_to(:present?)
94
- expect(element).to respond_to(:click)
46
+ it 'accepts any values in block' do
47
+ element = browser.div(id: 'bar')
48
+ expect { element.wait_until { true } }.to_not raise_exception
95
49
  end
96
50
 
97
- it 'can be chained with #wait_until &:present?' do
98
- browser.a(id: 'show_and_enable_btn').click
99
- browser.button(id: 'btn2').wait_until(&:present?).wait_until(&:enabled?).click
100
-
101
- expect(browser.button(id: 'btn2')).to exist
102
- expect(browser.button(id: 'btn2')).to be_enabled
51
+ it 'accepts just a timeout parameter' do
52
+ element = browser.div(id: 'bar')
53
+ expect { element.wait_until(timeout: 0) { true } }.to_not raise_exception
103
54
  end
104
- end
105
- end
106
55
 
107
- describe '#wait_until_present' do
108
- it 'waits until the element appears' do
109
- browser.a(id: 'show_bar').click
110
- expect {
111
- expect { browser.div(id: 'bar').wait_until_present(timeout: 5) }.to_not raise_exception
112
- }.to have_deprecated_wait_until_present
113
- end
56
+ it 'accepts just a message parameter' do
57
+ element = browser.div(id: 'bar')
58
+ expect { element.wait_until(message: 'no') { true } }.to_not raise_exception
59
+ end
114
60
 
115
- it 'waits until the element re-appears' do
116
- browser.link(id: 'readd_bar').click
117
- expect {
118
- expect { browser.div(id: 'bar').wait_until_present }.to_not raise_exception
119
- }.to have_deprecated_wait_until_present
120
- end
61
+ it 'accepts just an interval parameter' do
62
+ element = browser.div(id: 'bar')
63
+ expect { element.wait_until(interval: 0.1) { true } }.to_not raise_exception
64
+ end
121
65
 
122
- it "times out if the element doesn't appear" do
123
- inspected = '#<Watir::Div: located: true; {:id=>"bar", :tag_name=>"div"}>'
124
- error = Watir::Wait::TimeoutError
125
- message = "timed out after 1 seconds, waiting for #{inspected} to become present"
66
+ context 'accepts keywords instead of block' do
67
+ before { browser.refresh }
126
68
 
127
- expect {
128
- expect { browser.div(id: 'bar').wait_until_present(timeout: 1) }.to raise_error(error, message)
129
- }.to have_deprecated_wait_until_present
130
- end
69
+ it 'accepts text keyword' do
70
+ element = browser.div(id: 'bar')
71
+ browser.a(id: 'show_bar').click
72
+ expect { element.wait_until(text: 'bar') }.to_not raise_exception
73
+ end
131
74
 
132
- it 'uses provided interval' do
133
- element = browser.div(id: 'bar')
134
- expect(element).to receive(:present?).twice
75
+ it 'accepts regular expression value' do
76
+ element = browser.div(id: 'bar')
77
+ browser.a(id: 'show_bar').click
78
+ expect { element.wait_until(style: /block/) }.to_not raise_exception
79
+ end
135
80
 
136
- expect {
137
- expect { element.wait_until_present(timeout: 0.4, interval: 0.2) }.to raise_timeout_exception
138
- }.to have_deprecated_wait_until_present
139
- end
140
- end
81
+ it 'accepts multiple keywords' do
82
+ element = browser.div(id: 'bar')
83
+ browser.a(id: 'show_bar').click
84
+ expect { element.wait_until(text: 'bar', style: /block/) }.to_not raise_exception
85
+ end
141
86
 
142
- describe '#wait_while_present' do
143
- it 'waits until the element disappears' do
144
- browser.a(id: 'hide_foo').click
145
- expect {
146
- expect { browser.div(id: 'foo').wait_while_present(timeout: 2) }.to_not raise_exception
147
- }.to have_deprecated_wait_while_present
148
- end
87
+ it 'accepts custom keyword' do
88
+ element = browser.div(id: 'bar')
89
+ browser.a(id: 'show_bar').click
90
+ expect { element.wait_until(custom: 'bar') }.to_not raise_exception
91
+ end
149
92
 
150
- it "times out if the element doesn't disappear" do
151
- error = Watir::Wait::TimeoutError
152
- inspected = '#<Watir::Div: located: true; {:id=>"foo", :tag_name=>"div"}>'
153
- message = "timed out after 1 seconds, waiting for #{inspected} not to be present"
154
- expect {
155
- expect { browser.div(id: 'foo').wait_while_present(timeout: 1) }.to raise_error(error, message)
156
- }.to have_deprecated_wait_while_present
157
- end
93
+ it 'times out when single keyword not met' do
94
+ element = browser.div(id: 'bar')
95
+ expect { element.wait_until(id: 'foo') }.to raise_timeout_exception
96
+ end
158
97
 
159
- it 'uses provided interval' do
160
- error = Watir::Wait::TimeoutError
161
- element = browser.div(id: 'foo')
162
- expect(element).to receive(:present?).and_return(true).twice
98
+ it 'times out when one of multiple keywords not met' do
99
+ element = browser.div(id: 'bar')
100
+ expect { element.wait_until(id: 'bar', text: 'foo') }.to raise_timeout_exception
101
+ end
163
102
 
164
- expect {
165
- expect { element.wait_while_present(timeout: 0.4, interval: 0.2) }.to raise_error(error)
166
- }.to have_deprecated_wait_while_present
103
+ it 'times out when a custom keywords not met' do
104
+ element = browser.div(id: 'bar')
105
+ expect { element.wait_until(custom: 'foo') }.to raise_timeout_exception
106
+ end
107
+ end
167
108
  end
168
109
 
169
- it 'does not error when element goes stale' do
170
- element = browser.div(id: 'foo').locate
171
-
172
- allow(element).to receive(:stale?).and_return(false, true)
110
+ describe '#wait_while' do
111
+ it 'returns element for additional actions' do
112
+ element = browser.div(id: 'foo')
113
+ browser.a(id: 'hide_foo').click
114
+ expect(element.wait_while(&:present?)).to eq element
115
+ end
173
116
 
174
- browser.a(id: 'hide_foo').click
175
- expect {
176
- expect { element.wait_while_present(timeout: 1) }.to_not raise_exception
177
- }.to have_deprecated_wait_while_present
178
- end
117
+ it 'accepts any values in block' do
118
+ element = browser.div(id: 'foo')
119
+ expect { element.wait_while { false } }.to_not raise_exception
120
+ end
179
121
 
180
- it 'waits until the selector no longer matches' do
181
- element = browser.link(name: 'add_select').wait_until(&:exists?)
182
- browser.link(id: 'change_select').click
183
- expect {
184
- expect { element.wait_while_present }.not_to raise_error
185
- }.to have_deprecated_wait_while_present
186
- end
187
- end
122
+ it 'accepts just a timeout parameter' do
123
+ element = browser.div(id: 'foo')
124
+ expect { element.wait_while(timeout: 0) { false } }.to_not raise_exception
125
+ end
188
126
 
189
- describe '#wait_until' do
190
- it 'returns element for additional actions' do
191
- element = browser.div(id: 'foo')
192
- expect(element.wait_until(&:exist?)).to eq element
193
- end
127
+ it 'accepts just a message parameter' do
128
+ element = browser.div(id: 'foo')
129
+ expect { element.wait_while(message: 'no') { false } }.to_not raise_exception
130
+ end
194
131
 
195
- it 'accepts self in block' do
196
- element = browser.div(id: 'bar')
197
- browser.a(id: 'show_bar').click
198
- expect { element.wait_until { |el| el.text == 'bar' } }.to_not raise_exception
199
- end
132
+ it 'accepts just an interval parameter' do
133
+ element = browser.div(id: 'foo')
134
+ expect { element.wait_while(interval: 0.1) { false } }.to_not raise_exception
135
+ end
200
136
 
201
- it 'accepts any values in block' do
202
- element = browser.div(id: 'bar')
203
- expect { element.wait_until { true } }.to_not raise_exception
204
- end
137
+ context 'accepts keywords instead of block' do
138
+ bug 'Safari does not recognize date type', :safari do
139
+ it 'accepts text keyword' do
140
+ element = browser.div(id: 'foo')
141
+ browser.a(id: 'hide_foo').click
142
+ expect { element.wait_while(text: 'foo') }.to_not raise_exception
143
+ end
144
+ end
205
145
 
206
- it 'accepts just a timeout parameter' do
207
- element = browser.div(id: 'bar')
208
- expect { element.wait_until(timeout: 0) { true } }.to_not raise_exception
209
- end
146
+ it 'accepts regular expression value' do
147
+ element = browser.div(id: 'foo')
148
+ browser.a(id: 'hide_foo').click
149
+ expect { element.wait_while(style: /block/) }.to_not raise_exception
150
+ end
210
151
 
211
- it 'accepts just a message parameter' do
212
- element = browser.div(id: 'bar')
213
- expect { element.wait_until(message: 'no') { true } }.to_not raise_exception
214
- end
152
+ it 'accepts multiple keywords' do
153
+ element = browser.div(id: 'foo')
154
+ browser.a(id: 'hide_foo').click
155
+ expect { element.wait_while(text: 'foo', style: /block/) }.to_not raise_exception
156
+ end
215
157
 
216
- it 'accepts just an interval parameter' do
217
- element = browser.div(id: 'bar')
218
- expect { element.wait_until(interval: 0.1) { true } }.to_not raise_exception
219
- end
158
+ it 'accepts custom attributes' do
159
+ element = browser.div(id: 'foo')
160
+ browser.a(id: 'hide_foo').click
161
+ expect { element.wait_while(custom: '') }.to_not raise_exception
162
+ end
220
163
 
221
- context 'accepts keywords instead of block' do
222
- before { browser.refresh }
164
+ it 'accepts keywords and block' do
165
+ element = browser.div(id: 'foo')
166
+ browser.a(id: 'hide_foo').click
167
+ expect { element.wait_while(custom: '', &:present?) }.to_not raise_exception
168
+ end
223
169
 
224
- it 'accepts text keyword' do
225
- element = browser.div(id: 'bar')
226
- browser.a(id: 'show_bar').click
227
- expect { element.wait_until(text: 'bar') }.to_not raise_exception
228
- end
170
+ it 'browser accepts keywords' do
171
+ expect { browser.wait_until(title: 'wait test') }.to_not raise_exception
172
+ expect { browser.wait_until(title: 'wrong') }.to raise_timeout_exception
173
+ end
229
174
 
230
- it 'accepts regular expression value' do
231
- element = browser.div(id: 'bar')
232
- browser.a(id: 'show_bar').click
233
- expect { element.wait_until(style: /block/) }.to_not raise_exception
234
- end
175
+ it 'alert accepts keywords' do
176
+ browser.goto WatirSpec.url_for('alerts.html')
235
177
 
236
- it 'accepts multiple keywords' do
237
- element = browser.div(id: 'bar')
238
- browser.a(id: 'show_bar').click
239
- expect { element.wait_until(text: 'bar', style: /block/) }.to_not raise_exception
240
- end
178
+ begin
179
+ browser.button(id: 'alert').click
180
+ expect { browser.alert.wait_until(text: 'ok') }.to_not raise_exception
181
+ expect { browser.alert.wait_until(text: 'not ok') }.to raise_timeout_exception
182
+ ensure
183
+ browser.alert.ok
184
+ end
185
+ end
241
186
 
242
- it 'accepts custom keyword' do
243
- element = browser.div(id: 'bar')
244
- browser.a(id: 'show_bar').click
245
- expect { element.wait_until(custom: 'bar') }.to_not raise_exception
246
- end
187
+ it 'window accepts keywords' do
188
+ expect { browser.window.wait_until(title: 'wait test') }.to_not raise_exception
189
+ expect { browser.window.wait_until(title: 'wrong') }.to raise_timeout_exception
190
+ end
247
191
 
248
- it 'times out when single keyword not met' do
249
- element = browser.div(id: 'bar')
250
- expect { element.wait_until(id: 'foo') }.to raise_timeout_exception
251
- end
192
+ it 'times out when single keyword not met' do
193
+ element = browser.div(id: 'foo')
194
+ expect { element.wait_while(id: 'foo') }.to raise_timeout_exception
195
+ end
252
196
 
253
- it 'times out when one of multiple keywords not met' do
254
- element = browser.div(id: 'bar')
255
- expect { element.wait_until(id: 'bar', text: 'foo') }.to raise_timeout_exception
256
- end
197
+ it 'times out when one of multiple keywords not met' do
198
+ element = browser.div(id: 'foo')
199
+ browser.a(id: 'hide_foo').click
200
+ expect { element.wait_while(id: 'foo', style: /block/) }.to raise_timeout_exception
201
+ end
257
202
 
258
- it 'times out when a custom keywords not met' do
259
- element = browser.div(id: 'bar')
260
- expect { element.wait_until(custom: 'foo') }.to raise_timeout_exception
203
+ it 'times out when one of custom keywords not met' do
204
+ element = browser.div(id: 'foo')
205
+ expect { element.wait_while(custom: '') }.to raise_timeout_exception
206
+ end
261
207
  end
262
208
  end
263
- end
264
-
265
- describe '#wait_while' do
266
- it 'returns element for additional actions' do
267
- element = browser.div(id: 'foo')
268
- browser.a(id: 'hide_foo').click
269
- expect(element.wait_while(&:present?)).to eq element
270
- end
271
209
 
272
- not_compliant_on :safari do
273
- it 'accepts self in block' do
274
- element = browser.div(id: 'foo')
275
- browser.a(id: 'hide_foo').click
276
- expect { element.wait_while { |el| el.text == 'foo' } }.to_not raise_exception
210
+ context 'when acting on an element that is never present' do
211
+ it 'raises exception after timing out' do
212
+ element = browser.link(id: 'not_there')
213
+ expect { element.click }.to wait_and_raise_unknown_object_exception
277
214
  end
278
215
  end
279
216
 
280
- it 'accepts any values in block' do
281
- element = browser.div(id: 'foo')
282
- expect { element.wait_while { false } }.to_not raise_exception
217
+ context 'when acting on an element that is already present' do
218
+ it 'does not wait' do
219
+ expect { browser.link.click }.to execute_when_satisfied(max: 1)
220
+ end
283
221
  end
284
222
 
285
- it 'accepts just a timeout parameter' do
286
- element = browser.div(id: 'foo')
287
- expect { element.wait_while(timeout: 0) { false } }.to_not raise_exception
288
- end
223
+ context 'when acting on an element that eventually becomes present' do
224
+ it 'waits until element is present and then takes action' do
225
+ expect {
226
+ browser.a(id: 'show_bar').click
227
+ browser.div(id: 'bar').click
228
+ }.to execute_when_satisfied(min: 1)
229
+ expect(browser.div(id: 'bar').text).to eq 'changed'
230
+ end
289
231
 
290
- it 'accepts just a message parameter' do
291
- element = browser.div(id: 'foo')
292
- expect { element.wait_while(message: 'no') { false } }.to_not raise_exception
232
+ it 'waits until text field present and then takes action' do
233
+ expect {
234
+ browser.a(id: 'show_textfield').click
235
+ browser.text_field(id: 'textfield').set 'Foo'
236
+ }.to execute_when_satisfied(min: 1)
237
+ end
293
238
  end
294
239
 
295
- it 'accepts just an interval parameter' do
296
- element = browser.div(id: 'foo')
297
- expect { element.wait_while(interval: 0.1) { false } }.to_not raise_exception
298
- end
240
+ context 'when acting on a read only text field' do
241
+ it 'waits and raises read only exception if never becomes writable' do
242
+ expect { browser.text_field(id: 'writable').set 'foo' }.to wait_and_raise_object_read_only_exception
243
+ end
299
244
 
300
- context 'accepts keywords instead of block' do
301
- it 'accepts text keyword' do
302
- element = browser.div(id: 'foo')
303
- browser.a(id: 'hide_foo').click
304
- expect { element.wait_while(text: 'foo') }.to_not raise_exception
245
+ it 'waits until writable' do
246
+ expect {
247
+ browser.a(id: 'make-writable').click
248
+ browser.text_field(id: 'writable').set 'foo'
249
+ }.to execute_when_satisfied(min: 1)
305
250
  end
251
+ end
306
252
 
307
- it 'accepts regular expression value' do
308
- element = browser.div(id: 'foo')
309
- browser.a(id: 'hide_foo').click
310
- expect { element.wait_while(style: /block/) }.to_not raise_exception
253
+ context 'when acting on a disabled button' do
254
+ it 'waits and raises exception if it never becomes enabled' do
255
+ expect { browser.button(id: 'btn').click }.to wait_and_raise_object_disabled_exception
311
256
  end
312
257
 
313
- it 'accepts multiple keywords' do
314
- element = browser.div(id: 'foo')
315
- browser.a(id: 'hide_foo').click
316
- expect { element.wait_while(text: 'foo', style: /block/) }.to_not raise_exception
258
+ it 'waits until enabled' do
259
+ expect {
260
+ browser.a(id: 'enable_btn').click
261
+ browser.button(id: 'btn').click
262
+ }.to execute_when_satisfied(min: 1)
317
263
  end
264
+ end
318
265
 
319
- it 'accepts custom attributes' do
320
- element = browser.div(id: 'foo')
321
- browser.a(id: 'hide_foo').click
322
- expect { element.wait_while(custom: '') }.to_not raise_exception
266
+ context 'when acting on an element with a parent' do
267
+ it 'raises exception after timing out if parent never present' do
268
+ element = browser.link(id: 'not_there')
269
+ expect { element.element.click }.to wait_and_raise_unknown_object_exception
323
270
  end
324
271
 
325
- it 'accepts keywords and block' do
326
- element = browser.div(id: 'foo')
327
- browser.a(id: 'hide_foo').click
328
- expect { element.wait_while(custom: '', &:present?) }.to_not raise_exception
272
+ it 'raises exception after timing out when element from a collection whose parent is never present' do
273
+ element = browser.link(id: 'not_there')
274
+ expect { element.elements[2].click }.to wait_and_raise_unknown_object_exception
329
275
  end
330
276
 
331
- it 'browser accepts keywords' do
332
- expect { browser.wait_until(title: 'wait test') }.to_not raise_exception
333
- expect { browser.wait_until(title: 'wrong') }.to raise_timeout_exception
277
+ it 'does not wait for parent element to be present when querying child element' do
278
+ el = browser.element(id: 'not_there').element(id: 'doesnt_matter')
279
+ expect { el.present? }.to execute_when_satisfied(max: 1)
334
280
  end
281
+ end
282
+ end
335
283
 
336
- it 'alert accepts keywords' do
337
- browser.goto WatirSpec.url_for('alerts.html')
284
+ describe Watir::ElementCollection do
285
+ before do
286
+ browser.goto WatirSpec.url_for('wait.html')
287
+ end
338
288
 
339
- begin
340
- browser.button(id: 'alert').click
341
- expect { browser.alert.wait_until(text: 'ok') }.to_not raise_exception
342
- expect { browser.alert.wait_until(text: 'not ok') }.to raise_timeout_exception
343
- ensure
344
- browser.alert.ok
345
- end
289
+ describe '#wait_until' do
290
+ it 'returns collection' do
291
+ elements = browser.divs
292
+ expect(elements.wait_until(&:exist?)).to eq elements
346
293
  end
347
294
 
348
- it 'window accepts keywords' do
349
- expect { browser.window.wait_until(title: 'wait test') }.to_not raise_exception
350
- expect { browser.window.wait_until(title: 'wrong') }.to raise_timeout_exception
295
+ it 'times out when waiting for non-empty collection' do
296
+ expect { browser.divs.wait_until(&:empty?) }.to raise_timeout_exception
351
297
  end
352
298
 
353
- it 'times out when single keyword not met' do
354
- element = browser.div(id: 'foo')
355
- expect { element.wait_while(id: 'foo') }.to raise_timeout_exception
299
+ it 'provides matching collection when exists' do
300
+ expect {
301
+ browser.a(id: 'add_foobar').click
302
+ browser.divs(id: 'foobar').wait_until(&:exists?)
303
+ }.to execute_when_satisfied(min: 1)
356
304
  end
357
305
 
358
- it 'times out when one of multiple keywords not met' do
359
- element = browser.div(id: 'foo')
360
- browser.a(id: 'hide_foo').click
361
- expect { element.wait_while(id: 'foo', style: /block/) }.to raise_timeout_exception
306
+ it 'accepts self in block' do
307
+ expect {
308
+ browser.a(id: 'add_foobar').click
309
+ browser.divs.wait_until { |els| els.size == 7 }
310
+ }.to execute_when_satisfied(min: 1)
362
311
  end
363
312
 
364
- it 'times out when one of custom keywords not met' do
365
- element = browser.div(id: 'foo')
366
- expect { element.wait_while(custom: '') }.to raise_timeout_exception
313
+ it 'accepts attributes to evaluate' do
314
+ expect {
315
+ browser.a(id: 'add_foobar').click
316
+ browser.divs.wait_until(size: 7)
317
+ }.to execute_when_satisfied(min: 1)
367
318
  end
368
319
  end
369
- end
370
- end
371
-
372
- describe Watir do
373
- describe '#default_timeout' do
374
- before do
375
- browser.goto WatirSpec.url_for('wait.html')
376
- end
377
320
 
378
- context 'when no timeout is specified' do
379
- it 'is used by Wait#until' do
380
- expect { Watir::Wait.until { false } }.to wait_and_raise_timeout_exception(timeout: 1)
321
+ describe '#wait_while' do
322
+ it 'returns collection' do
323
+ elements = browser.divs
324
+ expect(elements.wait_while(&:empty?)).to eq elements
381
325
  end
382
326
 
383
- it 'is used by Wait#while' do
384
- expect { Watir::Wait.while { true } }.to wait_and_raise_timeout_exception(timeout: 1)
327
+ it 'times out when waiting for non-empty collection' do
328
+ elements = browser.divs
329
+ expect { elements.wait_while(&:exists?) }.to raise_timeout_exception
385
330
  end
386
331
 
387
- it 'is used by Element#wait_until_present' do
332
+ it 'provides matching collection when exists' do
388
333
  expect {
389
- expect { browser.div(id: 'bar').wait_until_present }.to wait_and_raise_timeout_exception(timeout: 1)
390
- }.to have_deprecated_wait_until_present
334
+ browser.a(id: 'remove_foo').click
335
+ browser.divs(id: 'foo').wait_while(&:exists?)
336
+ }.to execute_when_satisfied(min: 1)
391
337
  end
392
338
 
393
- it 'is used by Element#wait_while_present' do
339
+ it 'accepts self in block' do
394
340
  expect {
395
- expect { browser.div(id: 'foo').wait_while_present }.to wait_and_raise_timeout_exception(timeout: 1)
396
- }.to have_deprecated_wait_while_present
341
+ browser.a(id: 'add_foobar').click
342
+ browser.divs.wait_while { |els| els.size == 6 }
343
+ }.to execute_when_satisfied(min: 1)
397
344
  end
398
345
  end
346
+
347
+ it 'waits for parent element to be present before locating' do
348
+ els = browser.element(id: /not|there/).elements(id: 'doesnt_matter')
349
+ expect { els.to_a }.to wait_and_raise_unknown_object_exception
350
+ end
399
351
  end
400
352
  end