watir 6.14.0 → 6.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +24 -6
  3. data/CHANGES.md +10 -0
  4. data/Gemfile +0 -2
  5. data/README.md +1 -1
  6. data/Rakefile +2 -2
  7. data/lib/watir.rb +2 -3
  8. data/lib/watir/adjacent.rb +2 -2
  9. data/lib/watir/alert.rb +5 -9
  10. data/lib/watir/attribute_helper.rb +2 -3
  11. data/lib/watir/browser.rb +5 -17
  12. data/lib/watir/capabilities.rb +11 -0
  13. data/lib/watir/cell_container.rb +2 -2
  14. data/lib/watir/container.rb +7 -8
  15. data/lib/watir/cookies.rb +2 -12
  16. data/lib/watir/element_collection.rb +2 -2
  17. data/lib/watir/elements/button.rb +2 -11
  18. data/lib/watir/elements/element.rb +43 -25
  19. data/lib/watir/elements/hidden.rb +1 -1
  20. data/lib/watir/elements/iframe.rb +7 -5
  21. data/lib/watir/elements/option.rb +2 -13
  22. data/lib/watir/elements/select.rb +6 -22
  23. data/lib/watir/elements/table.rb +2 -2
  24. data/lib/watir/exception.rb +1 -2
  25. data/lib/watir/generator/base/idl_sorter.rb +1 -1
  26. data/lib/watir/generator/base/spec_extractor.rb +2 -2
  27. data/lib/watir/generator/base/visitor.rb +1 -1
  28. data/lib/watir/generator/html/generator.rb +0 -1
  29. data/lib/watir/generator/html/spec_extractor.rb +1 -1
  30. data/lib/watir/generator/html/visitor.rb +1 -1
  31. data/lib/watir/generator/svg/spec_extractor.rb +1 -1
  32. data/lib/watir/generator/svg/visitor.rb +1 -1
  33. data/lib/watir/js_execution.rb +11 -0
  34. data/lib/watir/js_snippets.rb +1 -1
  35. data/lib/watir/js_snippets/elementObscured.js +14 -0
  36. data/lib/watir/js_snippets/selectedText.js +17 -0
  37. data/lib/watir/legacy_wait.rb +5 -5
  38. data/lib/watir/locators.rb +16 -5
  39. data/lib/watir/locators/anchor/selector_builder.rb +38 -0
  40. data/lib/watir/locators/button/locator.rb +14 -12
  41. data/lib/watir/locators/button/selector_builder.rb +0 -22
  42. data/lib/watir/locators/button/selector_builder/xpath.rb +67 -12
  43. data/lib/watir/locators/button/validator.rb +2 -1
  44. data/lib/watir/locators/cell/selector_builder.rb +0 -14
  45. data/lib/watir/locators/cell/selector_builder/xpath.rb +21 -0
  46. data/lib/watir/locators/element/locator.rb +60 -153
  47. data/lib/watir/locators/element/selector_builder.rb +103 -84
  48. data/lib/watir/locators/element/selector_builder/regexp_disassembler.rb +66 -0
  49. data/lib/watir/locators/element/selector_builder/xpath.rb +195 -82
  50. data/lib/watir/locators/element/selector_builder/xpath_support.rb +27 -0
  51. data/lib/watir/locators/element/validator.rb +2 -9
  52. data/lib/watir/locators/row/selector_builder.rb +5 -22
  53. data/lib/watir/locators/row/selector_builder/xpath.rb +53 -0
  54. data/lib/watir/locators/text_area/selector_builder.rb +1 -1
  55. data/lib/watir/locators/text_area/selector_builder/xpath.rb +19 -0
  56. data/lib/watir/locators/text_field/locator.rb +11 -8
  57. data/lib/watir/locators/text_field/selector_builder.rb +0 -23
  58. data/lib/watir/locators/text_field/selector_builder/xpath.rb +33 -4
  59. data/lib/watir/locators/text_field/validator.rb +4 -4
  60. data/lib/watir/radio_set.rb +5 -5
  61. data/lib/watir/row_container.rb +2 -2
  62. data/lib/watir/user_editable.rb +2 -2
  63. data/lib/watir/version.rb +1 -1
  64. data/lib/watir/wait.rb +24 -37
  65. data/lib/watir/window.rb +11 -8
  66. data/lib/watirspec/remote_server.rb +3 -1
  67. data/spec/locator_spec_helper.rb +1 -1
  68. data/spec/spec_helper.rb +25 -1
  69. data/spec/unit/anchor_locator_spec.rb +68 -0
  70. data/spec/unit/capabilities_spec.rb +27 -0
  71. data/spec/unit/element_locator_spec.rb +184 -101
  72. data/spec/unit/logger_spec.rb +5 -0
  73. data/spec/watirspec/adjacent_spec.rb +34 -34
  74. data/spec/watirspec/after_hooks_spec.rb +78 -35
  75. data/spec/watirspec/alert_spec.rb +10 -0
  76. data/spec/watirspec/browser_spec.rb +27 -1
  77. data/spec/watirspec/element_hidden_spec.rb +6 -0
  78. data/spec/watirspec/elements/button_spec.rb +5 -11
  79. data/spec/watirspec/elements/buttons_spec.rb +1 -1
  80. data/spec/watirspec/elements/checkbox_spec.rb +2 -15
  81. data/spec/watirspec/elements/date_time_field_spec.rb +6 -1
  82. data/spec/watirspec/elements/dd_spec.rb +0 -17
  83. data/spec/watirspec/elements/del_spec.rb +0 -14
  84. data/spec/watirspec/elements/div_spec.rb +0 -18
  85. data/spec/watirspec/elements/dl_spec.rb +0 -17
  86. data/spec/watirspec/elements/dt_spec.rb +0 -17
  87. data/spec/watirspec/elements/element_spec.rb +177 -17
  88. data/spec/watirspec/elements/elements_spec.rb +7 -6
  89. data/spec/watirspec/elements/em_spec.rb +0 -13
  90. data/spec/watirspec/elements/filefield_spec.rb +0 -11
  91. data/spec/watirspec/elements/form_spec.rb +6 -0
  92. data/spec/watirspec/elements/hn_spec.rb +0 -14
  93. data/spec/watirspec/elements/iframe_spec.rb +15 -0
  94. data/spec/watirspec/elements/ins_spec.rb +0 -14
  95. data/spec/watirspec/elements/labels_spec.rb +1 -1
  96. data/spec/watirspec/elements/li_spec.rb +0 -14
  97. data/spec/watirspec/elements/link_spec.rb +22 -14
  98. data/spec/watirspec/elements/links_spec.rb +13 -0
  99. data/spec/watirspec/elements/list_spec.rb +15 -0
  100. data/spec/watirspec/elements/ol_spec.rb +0 -14
  101. data/spec/watirspec/elements/option_spec.rb +0 -10
  102. data/spec/watirspec/elements/p_spec.rb +0 -14
  103. data/spec/watirspec/elements/pre_spec.rb +0 -14
  104. data/spec/watirspec/elements/radio_spec.rb +0 -14
  105. data/spec/watirspec/elements/select_list_spec.rb +0 -10
  106. data/spec/watirspec/elements/span_spec.rb +4 -15
  107. data/spec/watirspec/elements/strong_spec.rb +4 -15
  108. data/spec/watirspec/elements/table_nesting_spec.rb +1 -1
  109. data/spec/watirspec/elements/table_spec.rb +7 -0
  110. data/spec/watirspec/elements/text_field_spec.rb +10 -2
  111. data/spec/watirspec/elements/text_fields_spec.rb +1 -1
  112. data/spec/watirspec/elements/tr_spec.rb +1 -1
  113. data/spec/watirspec/elements/ul_spec.rb +0 -14
  114. data/spec/watirspec/html/closeable.html +8 -0
  115. data/spec/watirspec/html/forms_with_input_elements.html +28 -23
  116. data/spec/watirspec/html/nested_elements.html +9 -9
  117. data/spec/watirspec/html/obscured.html +34 -0
  118. data/spec/watirspec/html/tables.html +13 -13
  119. data/spec/watirspec/radio_set_spec.rb +5 -0
  120. data/spec/watirspec/selector_builder/button_spec.rb +254 -0
  121. data/spec/watirspec/selector_builder/cell_spec.rb +93 -0
  122. data/spec/watirspec/selector_builder/element_spec.rb +639 -0
  123. data/spec/watirspec/selector_builder/row_spec.rb +150 -0
  124. data/spec/watirspec/selector_builder/text_spec.rb +170 -0
  125. data/spec/watirspec/support/rspec_matchers.rb +6 -1
  126. data/spec/watirspec/user_editable_spec.rb +4 -0
  127. data/spec/watirspec/wait_spec.rb +65 -14
  128. data/spec/watirspec/window_switching_spec.rb +54 -1
  129. data/spec/watirspec_helper.rb +2 -0
  130. data/watir.gemspec +7 -1
  131. metadata +86 -8
  132. data/lib/watir/locators/text_area/locator.rb +0 -13
  133. data/lib/watir/xpath_support.rb +0 -18
@@ -0,0 +1,150 @@
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
+ built = selector_builder.build(@selector)
14
+ expect(built).to eq [@wd_locator, (@remaining || {})]
15
+
16
+ next unless @data_locator || @tag_name
17
+
18
+ expect { @located = @query_scope.wd.first(@wd_locator) }.not_to raise_exception
19
+
20
+ if @data_locator
21
+ expect(@located.attribute('data-locator')).to eq(@data_locator)
22
+ else
23
+ expect {
24
+ expect(@located.tag_name).to eq @tag_name
25
+ }.not_to raise_exception
26
+ end
27
+ end
28
+
29
+ context 'with query scopes' do
30
+ before(:each) do
31
+ browser.goto(WatirSpec.url_for('tables.html'))
32
+ end
33
+
34
+ it 'with only table query scope' do
35
+ @query_scope = browser.element(id: 'outer').locate
36
+ @selector = {}
37
+ @wd_locator = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
38
+ "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr']"}
39
+ @data_locator = 'first row'
40
+ end
41
+
42
+ it 'with tbody query scope' do
43
+ @query_scope = browser.element(id: 'first').locate
44
+ @selector = {}
45
+ @wd_locator = {xpath: "./*[local-name()='tr']"}
46
+ @data_locator = 'tbody row'
47
+ end
48
+
49
+ it 'with thead query scope' do
50
+ @query_scope = browser.element(id: 'tax_headers').locate
51
+ @selector = {}
52
+ @wd_locator = {xpath: "./*[local-name()='tr']"}
53
+ @data_locator = 'thead row'
54
+ end
55
+
56
+ it 'with tfoot query scope' do
57
+ @query_scope = browser.element(id: 'tax_totals').locate
58
+ @selector = {}
59
+ @wd_locator = {xpath: "./*[local-name()='tr']"}
60
+ @data_locator = 'tfoot row'
61
+ end
62
+ end
63
+
64
+ context 'with index' do
65
+ before(:each) do
66
+ browser.goto(WatirSpec.url_for('tables.html'))
67
+ end
68
+
69
+ it 'positive' do
70
+ @query_scope = browser.element(id: 'outer').locate
71
+ @selector = {index: 1}
72
+ @wd_locator = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
73
+ "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr'])[2]"}
74
+ @data_locator = 'middle row'
75
+ end
76
+
77
+ it 'negative' do
78
+ @query_scope = browser.element(id: 'outer').locate
79
+ @selector = {index: -3}
80
+ @wd_locator = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
81
+ "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr'])[last()-2]"}
82
+ @data_locator = 'first row'
83
+ end
84
+
85
+ it 'last' do
86
+ @query_scope = browser.element(id: 'outer').locate
87
+ @selector = {index: -1}
88
+ @wd_locator = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
89
+ "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr'])[last()]"}
90
+ @data_locator = 'last row'
91
+ end
92
+
93
+ it 'does not return index if it is zero' do
94
+ @query_scope = browser.element(id: 'outer').locate
95
+ @selector = {index: 0}
96
+ @wd_locator = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
97
+ "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr']"}
98
+ @data_locator = 'first row'
99
+ end
100
+
101
+ it 'raises exception when index is not an Integer', skip_after: true do
102
+ @query_scope = browser.element(id: 'outer').locate
103
+ selector = {index: 'foo'}
104
+ msg = 'expected Integer, got "foo":String'
105
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
106
+ end
107
+ end
108
+
109
+ context 'with multiple locators' do
110
+ before(:each) do
111
+ browser.goto(WatirSpec.url_for('tables.html'))
112
+ @query_scope = browser.table.locate
113
+ end
114
+
115
+ it 'attribute and class' do
116
+ @selector = {id: 'gregory', class: /brick/}
117
+ @wd_locator = {xpath: "./*[local-name()='tr'][contains(@class, 'brick')][@id='gregory'] | " \
118
+ "./*[local-name()='tbody']/*[local-name()='tr'][contains(@class, 'brick')][@id='gregory'] | " \
119
+ "./*[local-name()='thead']/*[local-name()='tr'][contains(@class, 'brick')][@id='gregory'] | " \
120
+ "./*[local-name()='tfoot']/*[local-name()='tr'][contains(@class, 'brick')][@id='gregory']"}
121
+ @data_locator = 'House row'
122
+ end
123
+ end
124
+
125
+ context 'returns locators that can not be directly translated' do
126
+ before(:each) do
127
+ browser.goto(WatirSpec.url_for('tables.html'))
128
+ @query_scope = browser.table(id: 'outer').locate
129
+ end
130
+
131
+ it 'any text value' do
132
+ @selector = {text: 'Gregory'}
133
+ @wd_locator = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
134
+ "./*[local-name()='thead']/*[local-name()='tr'] | ./*[local-name()='tfoot']/*[local-name()='tr']"}
135
+ @remaining = {text: 'Gregory'}
136
+ end
137
+ end
138
+
139
+ it 'delegates adjacent to Element SelectorBuilder' do
140
+ browser.goto(WatirSpec.url_for('tables.html'))
141
+
142
+ @scope_tag_name = 'table'
143
+ @query_scope = browser.element(id: 'gregory').locate
144
+
145
+ @selector = {adjacent: :ancestor, index: 1}
146
+ @wd_locator = {xpath: './ancestor::*[2]'}
147
+ @data_locator = 'top table'
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,170 @@
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
+ built = selector_builder.build(@selector)
31
+ expect(built).to eq [@wd_locator, (@remaining || {})]
32
+
33
+ next unless @data_locator || @tag_name
34
+
35
+ expect { @located = @query_scope.wd.first(@wd_locator) }.not_to raise_exception
36
+
37
+ if @data_locator
38
+ expect(@located.attribute('data-locator')).to eq(@data_locator)
39
+ else
40
+ expect {
41
+ expect(@located.tag_name).to eq @tag_name
42
+ }.not_to raise_exception
43
+ end
44
+ end
45
+
46
+ it 'without any arguments' do
47
+ browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
48
+ @selector = {}
49
+ @wd_locator = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]"}
50
+ @data_locator = 'input name'
51
+ end
52
+
53
+ context 'with type' do
54
+ before(:each) { browser.goto(WatirSpec.url_for('forms_with_input_elements.html')) }
55
+
56
+ it 'specified text field type that is text' do
57
+ @selector = {type: 'text'}
58
+ @wd_locator = {xpath: ".//*[local-name()='input']" \
59
+ "[translate(@type,'#{uppercase}','#{lowercase}')='text']"}
60
+ @data_locator = 'first text'
61
+ end
62
+
63
+ it 'specified text field type that is not text' do
64
+ @selector = {type: 'number'}
65
+ @wd_locator = {xpath: ".//*[local-name()='input']" \
66
+ "[translate(@type,'#{uppercase}','#{lowercase}')='number']"}
67
+ @data_locator = '42'
68
+ end
69
+
70
+ it 'true locates text field with a type specified' do
71
+ @selector = {type: true}
72
+ @wd_locator = {xpath: ".//*[local-name()='input'][#{negative_types}]"}
73
+ @data_locator = 'input name'
74
+ end
75
+
76
+ it 'false locates text field without type specified' do
77
+ @selector = {type: false}
78
+ @wd_locator = {xpath: ".//*[local-name()='input'][not(@type)]"}
79
+ @data_locator = 'input name'
80
+ end
81
+
82
+ it 'raises exception when a non-text field type input is specified', skip_after: true do
83
+ selector = {type: 'checkbox'}
84
+ msg = 'TextField Elements can not be located by type: checkbox'
85
+ expect { selector_builder.build(selector) }
86
+ .to raise_exception Watir::Exception::LocatorException, msg
87
+ end
88
+ end
89
+
90
+ context 'with index' do
91
+ before(:each) do
92
+ browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
93
+ end
94
+
95
+ it 'positive' do
96
+ @selector = {index: 4}
97
+ @wd_locator = {xpath: "(.//*[local-name()='input'][not(@type) or (#{negative_types})])[5]"}
98
+ @data_locator = 'dev'
99
+ end
100
+
101
+ it 'negative' do
102
+ @selector = {index: -3}
103
+ @wd_locator = {xpath: "(.//*[local-name()='input'][not(@type) or (#{negative_types})])[last()-2]"}
104
+ @data_locator = '42'
105
+ end
106
+
107
+ it 'last' do
108
+ @selector = {index: -1}
109
+ @wd_locator = {xpath: "(.//*[local-name()='input'][not(@type) or (#{negative_types})])[last()]"}
110
+ @data_locator = 'last text'
111
+ end
112
+
113
+ it 'does not return index if it is zero' do
114
+ @selector = {index: 0}
115
+ @wd_locator = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]"}
116
+ @data_locator = 'input name'
117
+ end
118
+
119
+ it 'raises exception when index is not an Integer', skip_after: true do
120
+ selector = {index: 'foo'}
121
+ msg = 'expected Integer, got "foo":String'
122
+ expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
123
+ end
124
+ end
125
+
126
+ context 'with text' do
127
+ before(:each) { browser.goto(WatirSpec.url_for('forms_with_input_elements.html')) }
128
+
129
+ it 'String for value' do
130
+ @selector = {text: 'Developer'}
131
+ @wd_locator = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]"}
132
+ @remaining = {text: 'Developer'}
133
+ end
134
+
135
+ it 'Simple Regexp for value' do
136
+ @selector = {text: /Dev/}
137
+ @wd_locator = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]"}
138
+ @remaining = {text: /Dev/}
139
+ end
140
+
141
+ it 'returns complicated Regexp to the locator as a value' do
142
+ @selector = {text: /^foo$/}
143
+ @wd_locator = {xpath: ".//*[local-name()='input'][not(@type) or (#{negative_types})]"}
144
+ @remaining = {text: /^foo$/}
145
+ end
146
+ end
147
+
148
+ context 'with multiple locators' do
149
+ before(:each) do
150
+ browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
151
+ end
152
+
153
+ it 'locates using tag name, class, attributes and text' do
154
+ @selector = {text: 'Developer', class: /c/, id: true}
155
+ @wd_locator = {xpath: ".//*[local-name()='input'][contains(@class, 'c')]" \
156
+ "[not(@type) or (#{negative_types})][@id]"}
157
+ @remaining = {text: 'Developer'}
158
+ end
159
+
160
+ it 'delegates adjacent to Element SelectorBuilder' do
161
+ browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
162
+ @query_scope = browser.element(id: 'new_user_email').locate
163
+
164
+ @selector = {adjacent: :ancestor, index: 1}
165
+ @wd_locator = {xpath: './ancestor::*[2]'}
166
+ @data_locator = 'form'
167
+ end
168
+ end
169
+ end
170
+ end
@@ -1,12 +1,17 @@
1
1
  if defined?(RSpec)
2
2
  DEPRECATION_WARNINGS = %i[selector_parameters
3
+ ready_state
3
4
  class_array
4
5
  use_capabilities
5
6
  visible_text
7
+ link_text
6
8
  text_regexp
9
+ stale_exists
7
10
  stale_visible
8
11
  stale_present
9
- select_by].freeze
12
+ select_by
13
+ wait_until_present
14
+ wait_while_present].freeze
10
15
 
11
16
  DEPRECATION_WARNINGS.each do |deprecation|
12
17
  RSpec::Matchers.define "have_deprecated_#{deprecation}" do
@@ -128,6 +128,10 @@ describe Watir::UserEditable do
128
128
  it "raises UnknownObjectException if the text field doesn't exist" do
129
129
  expect { browser.text_field(id: 'no_such_id').set('secret') }.to raise_unknown_object_exception
130
130
  end
131
+
132
+ it 'raises ObjectReadOnlyException if the object is read only' do
133
+ expect { browser.text_field(id: 'new_user_code').set('Foo') }.to raise_object_read_only_exception
134
+ end
131
135
  end
132
136
 
133
137
  describe '#set!' do
@@ -107,48 +107,63 @@ describe Watir::Element do
107
107
  describe '#wait_until_present' do
108
108
  it 'waits until the element appears' do
109
109
  browser.a(id: 'show_bar').click
110
- expect { browser.div(id: 'bar').wait_until_present(timeout: 5) }.to_not raise_exception
110
+ expect {
111
+ expect { browser.div(id: 'bar').wait_until_present(timeout: 5) }.to_not raise_exception
112
+ }.to have_deprecated_wait_until_present
111
113
  end
112
114
 
113
115
  it 'waits until the element re-appears' do
114
116
  browser.link(id: 'readd_bar').click
115
- expect { browser.div(id: 'bar').wait_until_present }.to_not raise_exception
117
+ expect {
118
+ expect { browser.div(id: 'bar').wait_until_present }.to_not raise_exception
119
+ }.to have_deprecated_wait_until_present
116
120
  end
117
121
 
118
122
  it "times out if the element doesn't appear" do
119
123
  inspected = '#<Watir::Div: located: true; {:id=>"bar", :tag_name=>"div"}>'
120
124
  error = Watir::Wait::TimeoutError
121
- message = "timed out after 1 seconds, waiting for element #{inspected} to become present"
125
+ message = "timed out after 1 seconds, waiting for #{inspected} to become present"
122
126
 
123
- expect { browser.div(id: 'bar').wait_until_present(timeout: 1) }.to raise_error(error, message)
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
124
130
  end
125
131
 
126
132
  it 'uses provided interval' do
127
133
  element = browser.div(id: 'bar')
128
134
  expect(element).to receive(:present?).twice
129
135
 
130
- expect { element.wait_until_present(timeout: 0.4, interval: 0.2) }.to raise_timeout_exception
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
131
139
  end
132
140
  end
133
141
 
134
142
  describe '#wait_while_present' do
135
143
  it 'waits until the element disappears' do
136
144
  browser.a(id: 'hide_foo').click
137
- expect { browser.div(id: 'foo').wait_while_present(timeout: 2) }.to_not raise_exception
145
+ expect {
146
+ expect { browser.div(id: 'foo').wait_while_present(timeout: 2) }.to_not raise_exception
147
+ }.to have_deprecated_wait_while_present
138
148
  end
139
149
 
140
150
  it "times out if the element doesn't disappear" do
141
151
  error = Watir::Wait::TimeoutError
142
152
  inspected = '#<Watir::Div: located: true; {:id=>"foo", :tag_name=>"div"}>'
143
- message = "timed out after 1 seconds, waiting for element #{inspected} not to be present"
144
- expect { browser.div(id: 'foo').wait_while_present(timeout: 1) }.to raise_error(error, message)
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
145
157
  end
146
158
 
147
159
  it 'uses provided interval' do
160
+ error = Watir::Wait::TimeoutError
148
161
  element = browser.div(id: 'foo')
149
- expect(element).to receive(:present?).twice
162
+ expect(element).to receive(:present?).and_return(true).twice
150
163
 
151
- expect { element.wait_until_present(timeout: 0.4, interval: 0.2) }.to raise_timeout_exception
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
152
167
  end
153
168
 
154
169
  it 'does not error when element goes stale' do
@@ -157,13 +172,17 @@ describe Watir::Element do
157
172
  allow(element).to receive(:stale?).and_return(false, true)
158
173
 
159
174
  browser.a(id: 'hide_foo').click
160
- expect { element.wait_while_present(timeout: 1) }.to_not raise_exception
175
+ expect {
176
+ expect { element.wait_while_present(timeout: 1) }.to_not raise_exception
177
+ }.to have_deprecated_wait_while_present
161
178
  end
162
179
 
163
180
  it 'waits until the selector no longer matches' do
164
181
  element = browser.link(name: 'add_select').wait_until(&:exists?)
165
182
  browser.link(id: 'change_select').click
166
- expect { element.wait_while_present }.not_to raise_error
183
+ expect {
184
+ expect { element.wait_while_present }.not_to raise_error
185
+ }.to have_deprecated_wait_while_present
167
186
  end
168
187
  end
169
188
 
@@ -303,6 +322,34 @@ describe Watir::Element do
303
322
  expect { element.wait_while(custom: '') }.to_not raise_exception
304
323
  end
305
324
 
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
329
+ end
330
+
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
334
+ end
335
+
336
+ it 'alert accepts keywords' do
337
+ browser.goto WatirSpec.url_for('alerts.html')
338
+
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
346
+ end
347
+
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
351
+ end
352
+
306
353
  it 'times out when single keyword not met' do
307
354
  element = browser.div(id: 'foo')
308
355
  expect { element.wait_while(id: 'foo') }.to raise_timeout_exception
@@ -338,11 +385,15 @@ describe Watir do
338
385
  end
339
386
 
340
387
  it 'is used by Element#wait_until_present' do
341
- expect { browser.div(id: 'bar').wait_until_present }.to wait_and_raise_timeout_exception(timeout: 1)
388
+ 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
342
391
  end
343
392
 
344
393
  it 'is used by Element#wait_while_present' do
345
- expect { browser.div(id: 'foo').wait_while_present }.to wait_and_raise_timeout_exception(timeout: 1)
394
+ 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
346
397
  end
347
398
  end
348
399
  end