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
@@ -377,6 +377,8 @@ describe Watir::Locators::Element::Matcher do
377
377
  it 'not thrown when still matched by text content' do
378
378
  @values_to_match = {text: /some visible/}
379
379
  allow(browser).to receive(:execute_script).and_return('some visible some hidden')
380
+ allow(browser).to receive(:timer).and_return(Watir::Wait::Timer.new)
381
+ allow(browser).to receive(:timer=).and_return(Watir::Wait::Timer.new)
380
382
 
381
383
  expect {
382
384
  expect(matcher.match(elements, values_to_match, filter)).to eq elements[1]
@@ -386,31 +388,31 @@ describe Watir::Locators::Element::Matcher do
386
388
  it 'not thrown with complex regexp matched by text content' do
387
389
  @values_to_match = {text: /some (in|)visible/}
388
390
  allow(browser).to receive(:execute_script).and_return('some visible some hidden')
391
+ allow(browser).to receive(:timer).and_return(Watir::Wait::Timer.new)
392
+ allow(browser).to receive(:timer=).and_return(Watir::Wait::Timer.new)
389
393
 
390
394
  expect {
391
395
  expect(matcher.match(elements, values_to_match, filter)).to eq elements[1]
392
396
  }.not_to have_deprecated_text_regexp
393
397
  end
394
398
 
395
- not_compliant_on :watigiri do
396
- it 'thrown when no longer matched by text content' do
397
- @values_to_match = {text: /some visible$/}
398
- allow(browser).to receive(:execute_script).and_return('some visible some hidden')
399
+ it 'thrown when no longer matched by text content' do
400
+ @values_to_match = {text: /some visible$/}
401
+ allow(browser).to receive(:execute_script).and_return('some visible some hidden')
402
+ allow(browser).to receive(:timer).and_return(Watir::Wait::Timer.new)
403
+ allow(browser).to receive(:timer=).and_return(Watir::Wait::Timer.new)
399
404
 
400
- expect {
401
- expect(matcher.match(elements, values_to_match, filter)).to eq elements[1]
402
- }.to have_deprecated_text_regexp
403
- end
405
+ expect {
406
+ expect(matcher.match(elements, values_to_match, filter)).to eq elements[1]
407
+ }.to have_deprecated_text_regexp
404
408
  end
405
409
 
406
- not_compliant_on :watigiri do
407
- it 'not thrown when element does not exist' do
408
- @values_to_match = {text: /definitely not there/}
410
+ it 'not thrown when element does not exist' do
411
+ @values_to_match = {text: /definitely not there/}
409
412
 
410
- expect {
411
- expect(matcher.match(elements, values_to_match, filter)).to eq elements[1]
412
- }.to_not have_deprecated_text_regexp
413
- end
413
+ expect {
414
+ expect(matcher.match(elements, values_to_match, filter)).to eq elements[1]
415
+ }.to_not have_deprecated_text_regexp
414
416
  end
415
417
 
416
418
  # Note: This will work after:text_regexp deprecation removed
@@ -7,10 +7,10 @@ describe Watir::Locators::Button::SelectorBuilder do
7
7
  let(:uppercase) { 'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ' }
8
8
  let(:lowercase) { 'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ' }
9
9
  let(:default_types) do
10
- "translate(@type,'#{uppercase}','#{lowercase}')='button' or" \
11
- " translate(@type,'#{uppercase}','#{lowercase}')='reset' or"\
12
- " translate(@type,'#{uppercase}','#{lowercase}')='submit' or"\
13
- " translate(@type,'#{uppercase}','#{lowercase}')='image'"
10
+ "translate(@type,'#{uppercase}','#{lowercase}')=translate('button','#{uppercase}','#{lowercase}') or " \
11
+ "translate(@type,'#{uppercase}','#{lowercase}')=translate('reset','#{uppercase}','#{lowercase}') or "\
12
+ "translate(@type,'#{uppercase}','#{lowercase}')=translate('submit','#{uppercase}','#{lowercase}') or "\
13
+ "translate(@type,'#{uppercase}','#{lowercase}')=translate('image','#{uppercase}','#{lowercase}')"
14
14
  end
15
15
 
16
16
  describe '#build' do
@@ -36,9 +36,10 @@ describe Watir::Locators::Button::SelectorBuilder do
36
36
 
37
37
  it 'locates input or button element with specified type' do
38
38
  selector = {type: 'reset'}
39
+ type = "translate('reset','#{uppercase}','#{lowercase}')"
39
40
  built = {xpath: ".//*[(local-name()='button' and " \
40
- "translate(@type,'#{uppercase}','#{lowercase}')='reset') or " \
41
- "(local-name()='input' and (translate(@type,'#{uppercase}','#{lowercase}')='reset'))]"}
41
+ "translate(@type,'#{uppercase}','#{lowercase}')=#{type}) or " \
42
+ "(local-name()='input' and (translate(@type,'#{uppercase}','#{lowercase}')=#{type}))]"}
42
43
  expect(selector_builder.build(selector)).to eq built
43
44
  end
44
45
 
@@ -75,35 +76,35 @@ describe Watir::Locators::Button::SelectorBuilder do
75
76
 
76
77
  it 'locates value of input element with simple Regexp' do
77
78
  selector = {text: /Button/}
78
- built = {xpath: ".//*[(local-name()='button' and contains(text(), 'Button')) or " \
79
+ built = {xpath: ".//*[(local-name()='button' and contains(normalize-space(), 'Button')) or " \
79
80
  "(local-name()='input' and (#{default_types}) and contains(@value, 'Button'))]"}
80
81
  expect(selector_builder.build(selector)).to eq built
81
82
  end
82
83
 
83
84
  it 'locates text of button element with simple Regexp' do
84
85
  selector = {text: /Button 2/}
85
- built = {xpath: ".//*[(local-name()='button' and contains(text(), 'Button 2')) or " \
86
+ built = {xpath: ".//*[(local-name()='button' and contains(normalize-space(), 'Button 2')) or " \
86
87
  "(local-name()='input' and (#{default_types}) and contains(@value, 'Button 2'))]"}
87
88
  expect(selector_builder.build(selector)).to eq built
88
89
  end
89
90
 
90
91
  it 'Simple Regexp for text' do
91
92
  selector = {text: /n 2/}
92
- built = {xpath: ".//*[(local-name()='button' and contains(text(), 'n 2')) or " \
93
+ built = {xpath: ".//*[(local-name()='button' and contains(normalize-space(), 'n 2')) or " \
93
94
  "(local-name()='input' and (#{default_types}) and contains(@value, 'n 2'))]"}
94
95
  expect(selector_builder.build(selector)).to eq built
95
96
  end
96
97
 
97
98
  it 'Simple Regexp for value' do
98
99
  selector = {text: /Prev/}
99
- built = {xpath: ".//*[(local-name()='button' and contains(text(), 'Prev')) or " \
100
+ built = {xpath: ".//*[(local-name()='button' and contains(normalize-space(), 'Prev')) or " \
100
101
  "(local-name()='input' and (#{default_types}) and contains(@value, 'Prev'))]"}
101
102
  expect(selector_builder.build(selector)).to eq built
102
103
  end
103
104
 
104
105
  it 'returns complex Regexp to the locator' do
105
106
  selector = {text: /^foo$/}
106
- built = {xpath: ".//*[(local-name()='button' and contains(text(), 'foo')) or " \
107
+ built = {xpath: ".//*[(local-name()='button' and contains(normalize-space(), 'foo')) or " \
107
108
  "(local-name()='input' and (#{default_types}) and contains(@value, 'foo'))]", text: /^foo$/}
108
109
  expect(selector_builder.build(selector)).to eq built
109
110
  end
@@ -127,14 +128,14 @@ describe Watir::Locators::Button::SelectorBuilder do
127
128
  it 'input element value with simple Regexp' do
128
129
  selector = {value: /Prev/}
129
130
  built = {xpath: ".//*[(local-name()='button') or (local-name()='input' and (#{default_types}))]" \
130
- "[contains(text(), 'Prev') or contains(@value, 'Prev')]"}
131
+ "[contains(normalize-space(), 'Prev') or contains(@value, 'Prev')]"}
131
132
  expect(selector_builder.build(selector)).to eq built
132
133
  end
133
134
 
134
135
  it 'button element value with simple Regexp' do
135
136
  selector = {value: /on_2/}
136
137
  built = {xpath: ".//*[(local-name()='button') or (local-name()='input' and (#{default_types}))]" \
137
- "[contains(text(), 'on_2') or contains(@value, 'on_2')]"}
138
+ "[contains(normalize-space(), 'on_2') or contains(@value, 'on_2')]"}
138
139
  expect(selector_builder.build(selector)).to eq built
139
140
  end
140
141
 
@@ -148,14 +149,14 @@ describe Watir::Locators::Button::SelectorBuilder do
148
149
  it 'button element text with simple Regexp' do
149
150
  selector = {value: /ton 2/}
150
151
  built = {xpath: ".//*[(local-name()='button') or (local-name()='input' and (#{default_types}))]" \
151
- "[contains(text(), 'ton 2') or contains(@value, 'ton 2')]"}
152
+ "[contains(normalize-space(), 'ton 2') or contains(@value, 'ton 2')]"}
152
153
  expect(selector_builder.build(selector)).to eq built
153
154
  end
154
155
 
155
156
  it 'returns complex Regexp to the locator' do
156
157
  selector = {value: /^foo$/}
157
158
  built = {xpath: ".//*[(local-name()='button') or (local-name()='input' and (#{default_types}))]" \
158
- "[contains(text(), 'foo') or contains(@value, 'foo')]", value: /^foo$/}
159
+ "[contains(normalize-space(), 'foo') or contains(@value, 'foo')]", value: /^foo$/}
159
160
  expect(selector_builder.build(selector)).to eq built
160
161
  end
161
162
  end
@@ -51,7 +51,7 @@ describe Watir::Locators::Element::SelectorBuilder do
51
51
 
52
52
  it 'raises exception when not a String' do
53
53
  selector = {xpath: 7}
54
- msg = /expected one of \[String\], got 7:(Fixnum|Integer)/
54
+ msg = /expected one of \[String\], got 7:Integer/
55
55
 
56
56
  expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
57
57
  end
@@ -81,7 +81,7 @@ describe Watir::Locators::Element::SelectorBuilder do
81
81
 
82
82
  it 'raises exception when not a String or Regexp' do
83
83
  selector = {tag_name: 7}
84
- msg = /expected one of \[String, Regexp, Symbol\], got 7:(Fixnum|Integer)/
84
+ msg = /expected one of \[String, Regexp, Symbol\], got 7:Integer/
85
85
 
86
86
  expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
87
87
  end
@@ -186,14 +186,14 @@ describe Watir::Locators::Element::SelectorBuilder do
186
186
 
187
187
  it 'raises exception when not a String or Regexp or Array' do
188
188
  selector = {class: 7}
189
- msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:(Fixnum|Integer)/
189
+ msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
190
190
 
191
191
  expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
192
192
  end
193
193
 
194
194
  it 'raises exception when Array values are not a String or Regexp' do
195
195
  selector = {class: [7]}
196
- msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:(Fixnum|Integer)/
196
+ msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
197
197
 
198
198
  expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
199
199
  end
@@ -244,14 +244,14 @@ describe Watir::Locators::Element::SelectorBuilder do
244
244
 
245
245
  it 'raises exception when attribute value is not a Boolean, String or Regexp' do
246
246
  selector = {foo: 7}
247
- msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:(Fixnum|Integer)/
247
+ msg = /expected one of \[String, Regexp, TrueClass, FalseClass\], got 7:Integer/
248
248
 
249
249
  expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
250
250
  end
251
251
 
252
252
  it 'raises exception when attribute key is not a String or Regexp' do
253
253
  selector = {7 => 'foo'}
254
- msg = /Unable to build XPath using 7:(Fixnum|Integer)/
254
+ msg = /Unable to build XPath using 7:Integer/
255
255
 
256
256
  expect { selector_builder.build(selector) }.to raise_exception Watir::Exception::LocatorException, msg
257
257
  end
@@ -292,7 +292,7 @@ describe Watir::Locators::Element::SelectorBuilder do
292
292
 
293
293
  it 'raises exception when text is not a String or Regexp' do
294
294
  selector = {text: 7}
295
- msg = /expected one of \[String, Regexp\], got 7:(Fixnum|Integer)/
295
+ msg = /expected one of \[String, Regexp\], got 7:Integer/
296
296
 
297
297
  expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
298
298
  end
@@ -574,7 +574,10 @@ describe Watir::Locators::Element::SelectorBuilder do
574
574
  selector = {action: /ME/i}
575
575
  built = {xpath: './/*[contains(translate(@action,' \
576
576
  "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
577
- "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'), 'me')]"}
577
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'), " \
578
+ "translate('me'," \
579
+ "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
580
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'))]"}
578
581
 
579
582
  expect(selector_builder.build(selector)).to eq built
580
583
  end
@@ -662,7 +665,7 @@ describe Watir::Locators::Element::SelectorBuilder do
662
665
 
663
666
  it 'raises exception when visible text is not a String or Regexp' do
664
667
  selector = {visible_text: 7}
665
- msg = /expected one of \[String, Regexp\], got 7:(Fixnum|Integer)/
668
+ msg = /expected one of \[String, Regexp\], got 7:Integer/
666
669
 
667
670
  expect { selector_builder.build(selector) }.to raise_exception TypeError, msg
668
671
  end
@@ -762,5 +765,51 @@ describe Watir::Locators::Element::SelectorBuilder do
762
765
  expect(build_selector).to eq built
763
766
  end
764
767
  end
768
+
769
+ context 'with case-insensitive attributes' do
770
+ it 'respects case when locating uknown element with uknown attribute' do
771
+ expect(selector_builder.build(hreflang: 'en')).to eq(xpath: ".//*[@hreflang='en']")
772
+ expect(selector_builder.build(hreflang: /en/)).to eq(xpath: ".//*[contains(@hreflang, 'en')]")
773
+ end
774
+
775
+ it 'ignores case when locating uknown element with defined attribute' do
776
+ lhs = 'translate(@lang,' \
777
+ "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
778
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ')"
779
+ rhs = "translate('en'," \
780
+ "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
781
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ')"
782
+ expect(selector_builder.build(lang: 'en')).to eq(xpath: ".//*[#{lhs}=#{rhs}]")
783
+ expect(selector_builder.build(lang: /en/)).to eq(xpath: ".//*[contains(#{lhs}, #{rhs})]")
784
+ expect(selector_builder.build(tag_name: /a/, lang: 'en'))
785
+ .to eq(xpath: ".//*[contains(local-name(), 'a')][#{lhs}=#{rhs}]")
786
+ expect(selector_builder.build(tag_name: /a/, lang: /en/))
787
+ .to eq(xpath: ".//*[contains(local-name(), 'a')][contains(#{lhs}, #{rhs})]")
788
+ end
789
+
790
+ it 'ignores case when attribute is defined for element' do
791
+ lhs = 'translate(@hreflang,' \
792
+ "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
793
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ')"
794
+ rhs = "translate('en'," \
795
+ "'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'," \
796
+ "'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ')"
797
+ expect(selector_builder.build(tag_name: 'a', hreflang: 'en'))
798
+ .to eq(xpath: ".//*[local-name()='a'][#{lhs}=#{rhs}]")
799
+ expect(selector_builder.build(tag_name: 'a', hreflang: /en/))
800
+ .to eq(xpath: ".//*[local-name()='a'][contains(#{lhs}, #{rhs})]")
801
+ end
802
+
803
+ it 'respects case when attribute is not defined for element' do
804
+ expect(selector_builder.build(tag_name: 'table', hreflang: 'en'))
805
+ .to eq(xpath: ".//*[local-name()='table'][@hreflang='en']")
806
+ expect(selector_builder.build(tag_name: 'table', hreflang: /en/))
807
+ .to eq(xpath: ".//*[local-name()='table'][contains(@hreflang, 'en')]")
808
+ expect(selector_builder.build(tag_name: /a/, hreflang: 'en'))
809
+ .to eq(xpath: ".//*[contains(local-name(), 'a')][@hreflang='en']")
810
+ expect(selector_builder.build(tag_name: /a/, hreflang: /en/))
811
+ .to eq(xpath: ".//*[contains(local-name(), 'a')][contains(@hreflang, 'en')]")
812
+ end
813
+ end
765
814
  end
766
815
  end
@@ -7,18 +7,18 @@ describe Watir::Locators::TextField::SelectorBuilder do
7
7
  let(:uppercase) { 'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ' }
8
8
  let(:lowercase) { 'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ' }
9
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'"
10
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('file','#{uppercase}','#{lowercase}') and "\
11
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('radio','#{uppercase}','#{lowercase}') and " \
12
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('checkbox','#{uppercase}','#{lowercase}') and " \
13
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('submit','#{uppercase}','#{lowercase}') and " \
14
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('reset','#{uppercase}','#{lowercase}') and " \
15
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('image','#{uppercase}','#{lowercase}') and " \
16
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('button','#{uppercase}','#{lowercase}') and " \
17
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('hidden','#{uppercase}','#{lowercase}') and " \
18
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('range','#{uppercase}','#{lowercase}') and " \
19
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('color','#{uppercase}','#{lowercase}') and " \
20
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('date','#{uppercase}','#{lowercase}') and " \
21
+ "translate(@type,'#{uppercase}','#{lowercase}')!=translate('datetime-local','#{uppercase}','#{lowercase}')"
22
22
  end
23
23
 
24
24
  describe '#build' do
@@ -33,7 +33,7 @@ describe Watir::Locators::TextField::SelectorBuilder do
33
33
  it 'specified text field type that is text' do
34
34
  selector = {type: 'text'}
35
35
  built = {xpath: ".//*[local-name()='input']" \
36
- "[translate(@type,'#{uppercase}','#{lowercase}')='text']"}
36
+ "[translate(@type,'#{uppercase}','#{lowercase}')=translate('text','#{uppercase}','#{lowercase}')]"}
37
37
 
38
38
  expect(selector_builder.build(selector)).to eq built
39
39
  end
@@ -41,7 +41,7 @@ describe Watir::Locators::TextField::SelectorBuilder do
41
41
  it 'specified text field type that is not text' do
42
42
  selector = {type: 'number'}
43
43
  built = {xpath: ".//*[local-name()='input']" \
44
- "[translate(@type,'#{uppercase}','#{lowercase}')='number']"}
44
+ "[translate(@type,'#{uppercase}','#{lowercase}')=translate('number','#{uppercase}','#{lowercase}')]"}
45
45
 
46
46
  expect(selector_builder.build(selector)).to eq built
47
47
  end
@@ -1,4 +1,2 @@
1
- require 'watirspec'
2
- WatirSpec::Runner.execute = false
3
-
4
- require_relative '../watirspec_helper'
1
+ require 'spec_helper'
2
+ require 'watirspec/support/rspec_matchers'
@@ -50,6 +50,8 @@ describe 'Browser::AfterHooks' do
50
50
  end
51
51
 
52
52
  describe '#run' do
53
+ before { @yield = nil }
54
+
53
55
  after(:each) do
54
56
  browser.original_window.use
55
57
  browser.after_hooks.delete @page_after_hook
@@ -83,7 +85,7 @@ describe 'Browser::AfterHooks' do
83
85
  expect(@yield).to be true
84
86
  end
85
87
 
86
- not_compliant_on :safari do
88
+ bug 'https://gist.github.com/titusfortner/bd32f27ec2458b3a733d83374d156940', :safari do
87
89
  it 'runs after_hooks after Element#submit' do
88
90
  browser.goto(WatirSpec.url_for('forms_with_input_elements.html'))
89
91
  @page_after_hook = proc { @yield = browser.div(id: 'messages').text == 'submit' }
@@ -93,24 +95,24 @@ describe 'Browser::AfterHooks' do
93
95
  end
94
96
  end
95
97
 
96
- bug 'MoveTargetOutOfBoundsError', :firefox do
97
- it 'runs after_hooks after Element#double_click' do
98
- browser.goto(WatirSpec.url_for('non_control_elements.html'))
99
- @page_after_hook = proc { @yield = browser.title == 'Non-control elements' }
100
- browser.after_hooks.add @page_after_hook
101
- browser.div(id: 'html_test').double_click
102
- expect(@yield).to be true
103
- end
98
+ it 'runs after_hooks after Element#double_click' do
99
+ browser.goto(WatirSpec.url_for('non_control_elements.html'))
100
+ @page_after_hook = proc { @yield = browser.title == 'Non-control elements' }
101
+ browser.after_hooks.add @page_after_hook
102
+ div = browser.div(id: 'html_test')
103
+ div.scroll.to
104
+ div.double_click
105
+ expect(@yield).to be true
104
106
  end
105
107
 
106
- not_compliant_on %i[remote firefox] do
107
- it 'runs after_hooks after Element#right_click' do
108
- browser.goto(WatirSpec.url_for('right_click.html'))
109
- @page_after_hook = proc { @yield = browser.title == 'Right Click Test' }
110
- browser.after_hooks.add @page_after_hook
111
- browser.div(id: 'click').right_click
112
- expect(@yield).to be true
113
- end
108
+ it 'runs after_hooks after Element#right_click' do
109
+ browser.goto(WatirSpec.url_for('right_click.html'))
110
+ @page_after_hook = proc { @yield = browser.title == 'Right Click Test' }
111
+ browser.after_hooks.add @page_after_hook
112
+ div = browser.div(id: 'click')
113
+ div.scroll.to
114
+ div.right_click
115
+ expect(@yield).to be true
114
116
  end
115
117
 
116
118
  it 'runs after_hooks after FramedDriver#switch!' do
@@ -135,70 +137,58 @@ describe 'Browser::AfterHooks' do
135
137
  expect(@yield).to be true
136
138
  end
137
139
 
138
- not_compliant_on :headless do
139
- it 'runs after_hooks after Alert#ok' do
140
- browser.goto(WatirSpec.url_for('alerts.html'))
141
- @page_after_hook = proc { @yield = browser.title == 'Alerts' }
142
- browser.after_hooks.add @page_after_hook
143
- browser.after_hooks.without { browser.button(id: 'alert').click }
144
- browser.alert.ok
145
- expect(@yield).to be true
146
- end
140
+ it 'runs after_hooks after Alert#ok' do
141
+ browser.goto(WatirSpec.url_for('alerts.html'))
142
+ @page_after_hook = proc { @yield = browser.title == 'Alerts' }
143
+ browser.after_hooks.add @page_after_hook
144
+ browser.after_hooks.without { browser.button(id: 'alert').click }
145
+ browser.alert.ok
146
+ expect(@yield).to be true
147
147
  end
148
148
 
149
- not_compliant_on :headless do
150
- bug 'https://code.google.com/p/chromedriver/issues/detail?id=26', [:chrome, :macosx] do
151
- it 'runs after_hooks after Alert#close' do
152
- browser.goto(WatirSpec.url_for('alerts.html'))
153
- @page_after_hook = proc { @yield = browser.title == 'Alerts' }
154
- browser.after_hooks.add @page_after_hook
155
- browser.after_hooks.without { browser.button(id: 'alert').click }
156
- browser.alert.close
157
- expect(@yield).to be true
158
- end
159
- end
149
+ it 'runs after_hooks after Alert#close' do
150
+ browser.goto(WatirSpec.url_for('alerts.html'))
151
+ @page_after_hook = proc { @yield = browser.title == 'Alerts' }
152
+ browser.after_hooks.add @page_after_hook
153
+ browser.after_hooks.without { browser.button(id: 'alert').click }
154
+ browser.alert.close
155
+ expect(@yield).to be true
160
156
  end
161
157
 
162
- not_compliant_on :safari, :headless do
163
- it 'does not run error checks with alert present' do
164
- browser.goto WatirSpec.url_for('alerts.html')
158
+ it 'does not run error checks with alert present' do
159
+ browser.goto WatirSpec.url_for('alerts.html')
165
160
 
166
- @page_after_hook = proc { @yield = browser.title == 'Alerts' }
167
- browser.after_hooks.add @page_after_hook
161
+ @page_after_hook = proc { @yield = browser.title == 'Alerts' }
162
+ browser.after_hooks.add @page_after_hook
168
163
 
169
- browser.button(id: 'alert').click
170
- expect(@yield).to be_nil
164
+ browser.button(id: 'alert').click
165
+ expect(@yield).to be_nil
171
166
 
172
- browser.alert.ok
173
- expect(@yield).to eq true
174
- end
167
+ browser.alert.ok
168
+ expect(@yield).to eq true
175
169
  end
176
170
 
177
- not_compliant_on :headless do
178
- it 'does not raise error when running error checks using #after_hooks#without with alert present' do
179
- url = WatirSpec.url_for('alerts.html')
180
- @page_after_hook = proc { browser.url }
181
- browser.after_hooks.add @page_after_hook
182
- browser.goto url
183
- expect { browser.after_hooks.without { browser.button(id: 'alert').click } }.to_not raise_error
184
- browser.alert.ok
185
- end
171
+ it 'does not raise error when running error checks using #after_hooks#without with alert present' do
172
+ url = WatirSpec.url_for('alerts.html')
173
+ @page_after_hook = proc { browser.url }
174
+ browser.after_hooks.add @page_after_hook
175
+ browser.goto url
176
+ expect { browser.after_hooks.without { browser.button(id: 'alert').click } }.to_not raise_error
177
+ browser.alert.ok
186
178
  end
187
179
 
188
- not_compliant_on :headless do
189
- it 'does not raise error if no error checks are defined with alert present' do
190
- url = WatirSpec.url_for('alerts.html')
191
- @page_after_hook = proc { browser.url }
192
- browser.after_hooks.add @page_after_hook
193
- browser.goto url
194
- browser.after_hooks.delete @page_after_hook
195
- expect { browser.button(id: 'alert').click }.to_not raise_error
196
- browser.alert.ok
197
- end
180
+ it 'does not raise error if no error checks are defined with alert present' do
181
+ url = WatirSpec.url_for('alerts.html')
182
+ @page_after_hook = proc { browser.url }
183
+ browser.after_hooks.add @page_after_hook
184
+ browser.goto url
185
+ browser.after_hooks.delete @page_after_hook
186
+ expect { browser.button(id: 'alert').click }.to_not raise_error
187
+ browser.alert.ok
198
188
  end
199
189
 
200
- bug 'https://bugzilla.mozilla.org/show_bug.cgi?id=1223277', :firefox do
201
- not_compliant_on :headless do
190
+ bug 'Clicking an Element that Closes a Window is returning NoMatchingWindowFoundException', :safari do
191
+ bug 'https://github.com/mozilla/geckodriver/issues/1847', :firefox do
202
192
  it 'does not raise error when running error checks on closed window' do
203
193
  url = WatirSpec.url_for('window_switching.html')
204
194
  @page_after_hook = proc { browser.url }