watir 6.14.0 → 6.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -13,7 +13,7 @@ describe 'Buttons' do
13
13
 
14
14
  describe '#length' do
15
15
  it 'returns the number of buttons' do
16
- expect(browser.buttons.length).to eq 9
16
+ expect(browser.buttons.length).to eq 10
17
17
  end
18
18
  end
19
19
 
@@ -11,6 +11,8 @@ describe 'CheckBox' do
11
11
  it 'returns true if the checkbox button exists' do
12
12
  expect(browser.checkbox(id: 'new_user_interests_books')).to exist
13
13
  expect(browser.checkbox(id: /new_user_interests_books/)).to exist
14
+ expect(browser.checkbox(label: 'Cars')).to exist
15
+ expect(browser.checkbox(label: /Cars/)).to exist
14
16
  expect(browser.checkbox(name: 'new_user_interests')).to exist
15
17
  expect(browser.checkbox(name: /new_user_interests/)).to exist
16
18
  expect(browser.checkbox(value: 'books')).to exist
@@ -70,21 +72,6 @@ describe 'CheckBox' do
70
72
  end
71
73
 
72
74
  # Attribute methods
73
-
74
- describe '#class_name' do
75
- it 'returns the class name if the checkbox exists and has an attribute' do
76
- expect(browser.checkbox(id: 'new_user_interests_dancing').class_name).to eq 'fun'
77
- end
78
-
79
- it "returns an empty string if the checkbox exists and the attribute doesn't" do
80
- expect(browser.checkbox(id: 'new_user_interests_books').class_name).to eq ''
81
- end
82
-
83
- it "raises UnknownObjectException if the checkbox doesn't exist" do
84
- expect { browser.checkbox(id: 'no_such_id').class_name }.to raise_unknown_object_exception
85
- end
86
- end
87
-
88
75
  describe '#id' do
89
76
  it 'returns the id attribute if the checkbox exists and has an attribute' do
90
77
  expect(browser.checkbox(index: 0).id).to eq 'new_user_interests_books'
@@ -15,7 +15,12 @@ describe 'DateTimeField' do
15
15
  expect(browser.date_time_field(text: '')).to exist
16
16
  expect(browser.date_time_field(text: //)).to exist
17
17
  expect(browser.date_time_field(index: 0)).to exist
18
- expect(browser.date_time_field(xpath: "//input[@id='html5_datetime-local']")).to exist
18
+
19
+ # Firefox validates attribute "type" as "text" not "datetime-local"
20
+ not_compliant_on :firefox do
21
+ expect(browser.date_time_field(xpath: "//input[@id='html5_datetime-local']")).to exist
22
+ end
23
+
19
24
  expect(browser.date_time_field(label: 'HTML5 Datetime Local')).to exist
20
25
  expect(browser.date_time_field(label: /Local$/)).to exist
21
26
  end
@@ -28,23 +28,6 @@ describe 'Dd' do
28
28
  end
29
29
 
30
30
  # Attribute methods
31
- describe '#class_name' do
32
- it 'returns the class attribute if the element exists' do
33
- expect(browser.dd(id: 'someone').class_name).to eq 'name'
34
- end
35
-
36
- it "returns an empty string if the element exists but the attribute doesn't" do
37
- expect(browser.dd(id: 'city').class_name).to eq ''
38
- end
39
-
40
- it 'raises UnknownObjectException if the element does not exist' do
41
- expect { browser.dd(id: 'no_such_id').class_name }.to raise_unknown_object_exception
42
- expect { browser.dd(title: 'no_such_title').class_name }.to raise_unknown_object_exception
43
- expect { browser.dd(index: 1337).class_name }.to raise_unknown_object_exception
44
- expect { browser.dd(xpath: "//dd[@id='no_such_id']").class_name }.to raise_unknown_object_exception
45
- end
46
- end
47
-
48
31
  describe '#id' do
49
32
  it 'returns the id attribute if the element exists' do
50
33
  expect(browser.dd(class: 'name').id).to eq 'someone'
@@ -39,20 +39,6 @@ describe 'Del' do
39
39
  end
40
40
 
41
41
  # Attribute methods
42
- describe '#class_name' do
43
- it 'returns the class attribute' do
44
- expect(browser.del(index: 0).class_name).to eq 'lead'
45
- end
46
-
47
- it "returns an empty string if the element exists and the attribute doesn't" do
48
- expect(browser.del(index: 2).class_name).to eq ''
49
- end
50
-
51
- it "raises UnknownObjectException if the del doesn't exist" do
52
- expect { browser.del(id: 'no_such_id').class_name }.to raise_unknown_object_exception
53
- end
54
- end
55
-
56
42
  describe '#id' do
57
43
  it 'returns the id attribute' do
58
44
  expect(browser.del(index: 0).id).to eq 'lead'
@@ -5,7 +5,6 @@ describe 'Div' do
5
5
  browser.goto(WatirSpec.url_for('non_control_elements.html'))
6
6
  end
7
7
 
8
- # Exists method
9
8
  describe '#exists?' do
10
9
  it 'returns true if the element exists' do
11
10
  expect(browser.div(id: 'header')).to exist
@@ -45,23 +44,6 @@ describe 'Div' do
45
44
  end
46
45
 
47
46
  # Attribute methods
48
- describe '#class_name' do
49
- it 'returns the class attribute if the element exists' do
50
- expect(browser.div(id: 'footer').class_name).to eq 'profile'
51
- end
52
-
53
- it "returns an empty string if the element exists but the attribute doesn't" do
54
- expect(browser.div(id: 'content').class_name).to eq ''
55
- end
56
-
57
- it 'raises UnknownObjectException if the element does not exist' do
58
- expect { browser.div(id: 'no_such_id').class_name }.to raise_unknown_object_exception
59
- expect { browser.div(title: 'no_such_title').class_name }.to raise_unknown_object_exception
60
- expect { browser.div(index: 1337).class_name }.to raise_unknown_object_exception
61
- expect { browser.div(xpath: "//div[@id='no_such_id']").class_name }.to raise_unknown_object_exception
62
- end
63
- end
64
-
65
47
  describe '#id' do
66
48
  it 'returns the id attribute if the element exists' do
67
49
  expect(browser.div(index: 1).id).to eq 'outer_container'
@@ -28,23 +28,6 @@ describe 'Dl' do
28
28
  end
29
29
 
30
30
  # Attribute methods
31
- describe '#class_name' do
32
- it 'returns the class attribute if the element exists' do
33
- expect(browser.dl(id: 'experience-list').class_name).to eq 'list'
34
- end
35
-
36
- it "returns an empty string if the element exists but the attribute doesn't" do
37
- expect(browser.dl(id: 'noop').class_name).to eq ''
38
- end
39
-
40
- it 'raises UnknownObjectException if the element does not exist' do
41
- expect { browser.dl(id: 'no_such_id').class_name }.to raise_unknown_object_exception
42
- expect { browser.dl(title: 'no_such_title').class_name }.to raise_unknown_object_exception
43
- expect { browser.dl(index: 1337).class_name }.to raise_unknown_object_exception
44
- expect { browser.dl(xpath: "//dl[@id='no_such_id']").class_name }.to raise_unknown_object_exception
45
- end
46
- end
47
-
48
31
  describe '#id' do
49
32
  it 'returns the id attribute if the element exists' do
50
33
  expect(browser.dl(class: 'list').id).to eq 'experience-list'
@@ -28,23 +28,6 @@ describe 'Dt' do
28
28
  end
29
29
 
30
30
  # Attribute methods
31
- describe '#class_name' do
32
- it 'returns the class attribute if the element exists' do
33
- expect(browser.dt(id: 'experience').class_name).to eq 'industry'
34
- end
35
-
36
- it "returns an empty string if the element exists but the attribute doesn't" do
37
- expect(browser.dt(id: 'education').class_name).to eq ''
38
- end
39
-
40
- it 'raises UnknownObjectException if the element does not exist' do
41
- expect { browser.dt(id: 'no_such_id').class_name }.to raise_unknown_object_exception
42
- expect { browser.dt(title: 'no_such_title').class_name }.to raise_unknown_object_exception
43
- expect { browser.dt(index: 1337).class_name }.to raise_unknown_object_exception
44
- expect { browser.dt(xpath: "//dt[@id='no_such_id']").class_name }.to raise_unknown_object_exception
45
- end
46
- end
47
-
48
31
  describe '#id' do
49
32
  it 'returns the id attribute if the element exists' do
50
33
  expect(browser.dt(class: 'industry').id).to eq 'experience'
@@ -87,20 +87,27 @@ describe 'Element' do
87
87
  it 'finds elements by visible text' do
88
88
  browser.goto WatirSpec.url_for('non_control_elements.html')
89
89
 
90
- expect(browser.link(visible_text: 'all visible')).to exist
91
- expect(browser.link(visible_text: /all visible/)).to exist
92
- expect(browser.link(visible_text: 'some visible')).to exist
93
- expect(browser.link(visible_text: /some visible/)).to exist
94
- expect(browser.link(visible_text: 'none visible')).not_to exist
95
- expect(browser.link(visible_text: /none visible/)).not_to exist
96
-
97
- expect(browser.link(visible_text: 'Link 2', class: 'external')).to exist
98
- expect(browser.link(visible_text: /Link 2/, class: 'external')).to exist
99
-
100
90
  expect(browser.element(visible_text: 'all visible')).to exist
101
91
  expect(browser.element(visible_text: /all visible/)).to exist
102
92
  expect(browser.element(visible_text: 'some visible')).to exist
103
93
  expect(browser.element(visible_text: /some visible/)).to exist
94
+ expect(browser.element(visible_text: 'none visible')).not_to exist
95
+ expect(browser.element(visible_text: /none visible/)).not_to exist
96
+
97
+ expect(browser.element(visible_text: 'Link 2', class: 'external')).to exist
98
+ expect(browser.element(visible_text: /Link 2/, class: 'external')).to exist
99
+ end
100
+
101
+ it 'raises exception unless value is a String or a RegExp' do
102
+ browser.goto WatirSpec.url_for('non_control_elements.html')
103
+ msg = /expected string_or_regexp, got 7\:(Fixnum|Integer)/
104
+ expect { browser.element(visible_text: 7).exists? }.to raise_exception(TypeError, msg)
105
+ end
106
+
107
+ it 'raises exception unless key is valid' do
108
+ browser.goto WatirSpec.url_for('non_control_elements.html')
109
+ msg = /Unable to build XPath using 7:(Fixnum|Integer)/
110
+ expect { browser.element(7 => /foo/).exists? }.to raise_exception(Watir::Exception::Error, msg)
104
111
  end
105
112
  end
106
113
 
@@ -131,7 +138,7 @@ describe 'Element' do
131
138
  end
132
139
 
133
140
  it "finds several elements from an element's subtree" do
134
- expect(browser.fieldset.elements(xpath: './/label').length).to eq 22
141
+ expect(browser.fieldset.elements(xpath: './/label').length).to eq 23
135
142
  end
136
143
  end
137
144
 
@@ -265,7 +272,9 @@ describe 'Element' do
265
272
  browser.refresh
266
273
 
267
274
  expect(element).to be_stale
268
- expect(element).to_not exist
275
+ expect {
276
+ expect(element).to_not exist
277
+ }.to have_deprecated_stale_exists
269
278
  end
270
279
 
271
280
  it 'returns false when tag name does not match id' do
@@ -447,23 +456,29 @@ describe 'Element' do
447
456
  end
448
457
 
449
458
  it 'raises if both :xpath and :css are given' do
450
- expect { browser.div(xpath: '//div', css: 'div').exists? }.to raise_error(ArgumentError)
459
+ msg = ':xpath and :css cannot be combined ({:xpath=>"//div", :css=>"div"})'
460
+ expect { browser.div(xpath: '//div', css: 'div').exists? }
461
+ .to raise_exception Watir::Exception::LocatorException, msg
451
462
  end
452
463
 
453
464
  it "doesn't raise when selector has with :xpath has :index" do
454
465
  expect(browser.div(xpath: '//div', index: 1)).to exist
455
466
  end
456
467
 
457
- it 'raises ArgumentError error if selector hash with :xpath has multiple entries' do
458
- expect { browser.div(xpath: '//div', class: 'foo').exists? }.to raise_error(ArgumentError)
468
+ it 'raises LocatorException error if selector hash with :xpath has multiple entries' do
469
+ msg = 'xpath cannot be combined with all of these locators ({:class=>"foo", :tag_name=>"div"})'
470
+ expect { browser.div(xpath: '//div', class: 'foo').exists? }
471
+ .to raise_exception Watir::Exception::LocatorException, msg
459
472
  end
460
473
 
461
474
  it "doesn't raise when selector has with :css has :index" do
462
475
  expect(browser.div(css: 'div', index: 1)).to exist
463
476
  end
464
477
 
465
- it 'raises ArgumentError error if selector hash with :css has multiple entries' do
466
- expect { browser.div(css: 'div', class: 'foo').exists? }.to raise_error(ArgumentError)
478
+ it 'raises LocatorException error if selector hash with :css has multiple entries' do
479
+ msg = 'css cannot be combined with all of these locators ({:class=>"foo", :tag_name=>"div"})'
480
+ expect { browser.div(css: 'div', class: 'foo').exists? }
481
+ .to raise_exception Watir::Exception::LocatorException, msg
467
482
  end
468
483
 
469
484
  it 'finds element by Selenium name locator' do
@@ -524,6 +539,20 @@ describe 'Element' do
524
539
  end
525
540
  end
526
541
 
542
+ describe '#click' do
543
+ bug 'https://github.com/mozilla/geckodriver/issues/1375', :firefox do
544
+ it 'accepts modifiers' do
545
+ begin
546
+ browser.a.click(:shift)
547
+ expect(browser.windows.size).to eq 2
548
+ ensure
549
+ browser.windows.reject(&:current?).each(&:close)
550
+ expect(browser.windows.size).to eq 1
551
+ end
552
+ end
553
+ end
554
+ end
555
+
527
556
  describe '#flash' do
528
557
  let(:h2) { browser.h2(text: 'Add user') }
529
558
  let(:h1) { browser.h1(text: 'User administration') }
@@ -643,6 +672,15 @@ describe 'Element' do
643
672
  end
644
673
  end
645
674
 
675
+ describe '#select_text and #selected_text' do
676
+ it 'selects text and returns selected text' do
677
+ browser.goto WatirSpec.url_for('non_control_elements.html')
678
+ element = browser.element(visible_text: 'all visible')
679
+ element.select_text('all visible')
680
+ expect(element.selected_text).to eq 'all visible'
681
+ end
682
+ end
683
+
646
684
  not_compliant_on %i[remote firefox] do
647
685
  describe '#scroll_into_view' do
648
686
  it 'scrolls element into view' do
@@ -771,4 +809,126 @@ describe 'Element' do
771
809
  expect(element.wd).to be_a(Selenium::WebDriver::Element)
772
810
  end
773
811
  end
812
+
813
+ describe '#hash' do
814
+ it 'returns a hash' do
815
+ element = browser.text_field(id: 'new_user_email')
816
+ hash1 = element.hash
817
+ hash2 = element.locate.hash
818
+ expect(hash1).to be_a Integer
819
+ expect(hash2).to be_a Integer
820
+ expect(hash1).to_not eq hash2
821
+ end
822
+ end
823
+
824
+ describe 'Float Attribute' do
825
+ it 'returns Float value of applicable element' do
826
+ element = browser.text_field(id: 'number')
827
+ expect(element.valueasnumber).to be_a Float
828
+ end
829
+
830
+ it 'returns nil value for an inapplicable Element' do
831
+ element = browser.input
832
+ expect(element.valueasnumber).to be_nil
833
+ end
834
+ end
835
+
836
+ describe 'Integer Attribute' do
837
+ it 'returns Float value of applicable element' do
838
+ element = browser.form
839
+ expect(element.length).to be_a Integer
840
+ end
841
+
842
+ it 'returns -1 for an inapplicable Element' do
843
+ element = browser.input
844
+ expect(element.maxlength).to eq(-1)
845
+ end
846
+ end
847
+
848
+ describe '#class_name' do
849
+ it 'returns single class name' do
850
+ expect(browser.form(id: 'new_user').class_name).to eq 'user'
851
+ end
852
+
853
+ it 'returns multiple class names in a String' do
854
+ expect(browser.div(id: 'messages').class_name).to eq 'multiple classes here'
855
+ end
856
+
857
+ it 'returns an empty string if the element exists but there is no class attribute' do
858
+ expect(browser.div(id: 'changed_language').class_name).to eq ''
859
+ end
860
+
861
+ it 'raises UnknownObjectException if the element does not exist' do
862
+ expect { browser.div(id: 'no_such_id').class_name }.to raise_unknown_object_exception
863
+ end
864
+ end
865
+
866
+ describe '#classes' do
867
+ it 'returns the class attribute if the element exists' do
868
+ expect(browser.div(id: 'messages').classes).to eq %w[multiple classes here]
869
+ end
870
+
871
+ it 'returns an empty array if the element exists but there is no class attribute' do
872
+ expect(browser.div(id: 'changed_language').classes).to eq []
873
+ end
874
+
875
+ it 'raises UnknownObjectException if the element does not exist' do
876
+ expect { browser.div(id: 'no_such_id').classes }.to raise_unknown_object_exception
877
+ end
878
+ end
879
+
880
+ describe '#obscured?' do
881
+ before { browser.goto WatirSpec.url_for('obscured.html') }
882
+
883
+ it 'returns false if element\'s center is not covered' do
884
+ btn = browser.button(id: 'not_obscured')
885
+ expect(btn).not_to be_obscured
886
+ expect { btn.click }.not_to raise_exception
887
+ end
888
+
889
+ it 'returns false if element\'s center is covered by its descendant' do
890
+ btn = browser.button(id: 'has_descendant')
891
+ expect(btn).not_to be_obscured
892
+ expect { btn.click }.not_to raise_exception
893
+ end
894
+
895
+ it 'returns true if element\'s center is covered by a non-descendant' do
896
+ btn = browser.button(id: 'obscured')
897
+ expect(btn).to be_obscured
898
+ not_compliant_on :chrome do
899
+ expect { btn.click }.to raise_exception(Selenium::WebDriver::Error::ElementClickInterceptedError)
900
+ end
901
+ compliant_on :chrome do
902
+ expect { btn.click }.to raise_exception(Selenium::WebDriver::Error::UnknownError)
903
+ end
904
+ end
905
+
906
+ it 'returns false if element\'s center is surrounded by non-descendants' do
907
+ btn = browser.button(id: 'surrounded')
908
+ expect(btn).not_to be_obscured
909
+ expect { btn.click }.not_to raise_exception
910
+ end
911
+
912
+ it 'scrolls element into view before checking if obscured' do
913
+ btn = browser.button(id: 'requires_scrolling')
914
+ expect(btn).not_to be_obscured
915
+ expect { btn.click }.not_to raise_exception
916
+ end
917
+
918
+ it 'returns true if element cannot be scrolled into view' do
919
+ btn = browser.button(id: 'off_screen')
920
+ expect(btn).to be_obscured
921
+ expect { btn.click }.to raise_unknown_object_exception
922
+ end
923
+
924
+ it 'returns true if element is hidden' do
925
+ btn = browser.button(id: 'hidden')
926
+ expect(btn).to be_obscured
927
+ expect { btn.click }.to raise_unknown_object_exception
928
+ end
929
+
930
+ it 'raises UnknownObjectException if element does not exist' do
931
+ expect { browser.button(id: 'does_not_exist').obscured? }.to raise_unknown_object_exception
932
+ end
933
+ end
774
934
  end
@@ -36,12 +36,13 @@ describe 'Elements' do
36
36
  describe 'visible text' do
37
37
  it 'finds elements by visible text' do
38
38
  browser.goto WatirSpec.url_for('non_control_elements.html')
39
- expect(browser.links(visible_text: 'all visible').count).to eq(1)
40
- expect(browser.links(visible_text: /all visible/).count).to eq(1)
41
- expect(browser.links(visible_text: 'some visible').count).to eq(1)
42
- expect(browser.links(visible_text: /some visible/).count).to eq(1)
43
- expect(browser.links(visible_text: 'none visible').count).to eq(0)
44
- expect(browser.links(visible_text: /none visible/).count).to eq(0)
39
+ container = browser.div(id: 'visible_text')
40
+ expect(container.elements(visible_text: 'all visible').count).to eq(1)
41
+ expect(container.elements(visible_text: /all visible/).count).to eq(1)
42
+ expect(container.elements(visible_text: 'some visible').count).to eq(1)
43
+ expect(container.elements(visible_text: /some visible/).count).to eq(1)
44
+ expect(container.elements(visible_text: 'none visible').count).to eq(0)
45
+ expect(container.elements(visible_text: /none visible/).count).to eq(0)
45
46
  end
46
47
  end
47
48
  end