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
@@ -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