watir 6.0.0.beta4 → 6.0.0.beta5
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.
- checksums.yaml +4 -4
- data/CHANGES.md +6 -0
- data/lib/watir/browser.rb +0 -5
- data/lib/watir/element_collection.rb +3 -1
- data/lib/watir/elements/element.rb +24 -27
- data/lib/watir/elements/iframe.rb +6 -22
- data/lib/watir/elements/image.rb +0 -26
- data/lib/watir/elements/row.rb +2 -2
- data/lib/watir/elements/text_field.rb +7 -2
- data/lib/watir/locators/element/locator.rb +20 -13
- data/lib/watir/locators/element/selector_builder.rb +5 -1
- data/lib/watir/window.rb +2 -2
- data/spec/element_spec.rb +36 -16
- data/watir.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 935a787298648718688deca84d844924d69dc5b0
|
4
|
+
data.tar.gz: d6e4f016435c83c21ab6045eac35365c2fb0b370
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e215494da9556e98fe9542a042ff80a64bedbef8071bc920a9653806b629e4876a0708f0b06cb318f69b8cdbc16855dc0704b630df0de83fac3b36225f406a5
|
7
|
+
data.tar.gz: 4b77b7a781336fc2534b5a91051e1b66e590eabdc85162dd8ee6aebf4ba1cecb79d29a766d284d0bc849b42b82e025c51e627b543d59981a0756f5e0c31d8065
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
### 6.0.0.beta5 (2016-09-25)
|
2
|
+
|
3
|
+
* Elements in collections can now be relocated after going stale
|
4
|
+
* Added visible locator to filter out matching elements that are hidden
|
5
|
+
* Element not found error messages now include selector information from parent elements
|
6
|
+
|
1
7
|
### 6.0.0.beta4 (2016-09-12)
|
2
8
|
|
3
9
|
* Deprecate Watir#prefer_css setting
|
data/lib/watir/browser.rb
CHANGED
@@ -81,7 +81,9 @@ module Watir
|
|
81
81
|
|
82
82
|
def to_a
|
83
83
|
# TODO: optimize - lazy element_class instance?
|
84
|
-
@to_a ||= elements.map
|
84
|
+
@to_a ||= elements.map.with_index do |e, idx|
|
85
|
+
element_class.new(@query_scope, @selector.merge(element: e, index: idx))
|
86
|
+
end
|
85
87
|
end
|
86
88
|
|
87
89
|
private
|
@@ -24,12 +24,13 @@ module Watir
|
|
24
24
|
|
25
25
|
def initialize(query_scope, selector)
|
26
26
|
@query_scope = query_scope
|
27
|
-
@selector = selector
|
28
|
-
@element = nil
|
29
27
|
|
30
|
-
unless
|
28
|
+
unless selector.kind_of? Hash
|
31
29
|
raise ArgumentError, "invalid argument: #{selector.inspect}"
|
32
30
|
end
|
31
|
+
|
32
|
+
@element = selector.delete(:element)
|
33
|
+
@selector = selector
|
33
34
|
end
|
34
35
|
|
35
36
|
#
|
@@ -47,7 +48,7 @@ module Watir
|
|
47
48
|
alias_method :exist?, :exists?
|
48
49
|
|
49
50
|
def inspect
|
50
|
-
if @selector.
|
51
|
+
if @selector.empty?
|
51
52
|
'#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, '{element: (selenium element)}']
|
52
53
|
else
|
53
54
|
'#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, selector_string]
|
@@ -513,10 +514,11 @@ module Watir
|
|
513
514
|
|
514
515
|
# Ensure that the element exists, making sure that it is not stale and located if necessary
|
515
516
|
def assert_exists
|
516
|
-
@element
|
517
|
-
|
518
|
-
|
519
|
-
|
517
|
+
if @element && @selector.empty?
|
518
|
+
ensure_context
|
519
|
+
@element = nil if stale?
|
520
|
+
elsif @element && !stale?
|
521
|
+
return
|
520
522
|
else
|
521
523
|
@element = locate
|
522
524
|
end
|
@@ -524,27 +526,14 @@ module Watir
|
|
524
526
|
assert_element_found
|
525
527
|
end
|
526
528
|
|
527
|
-
# Ensure that the element isn't stale, by relocating if it is
|
528
|
-
def ensure_not_stale
|
529
|
-
ensure_context
|
530
|
-
|
531
|
-
# Performance shortcut; only need recursive call to ensure context if stale in current context
|
532
|
-
return unless stale?
|
533
|
-
@element = @selector.key?(:element) ? nil : locate
|
534
|
-
assert_element_found
|
535
|
-
end
|
536
|
-
|
537
529
|
def assert_element_found
|
538
530
|
unless @element
|
539
531
|
raise UnknownObjectException, "unable to locate element, using #{selector_string}"
|
540
532
|
end
|
541
533
|
end
|
542
534
|
|
543
|
-
def reset!
|
544
|
-
@element = nil
|
545
|
-
end
|
546
|
-
|
547
535
|
def locate
|
536
|
+
return if @selector.empty?
|
548
537
|
ensure_context
|
549
538
|
|
550
539
|
element_validator = element_validator_class.new
|
@@ -554,6 +543,18 @@ module Watir
|
|
554
543
|
locator.locate
|
555
544
|
end
|
556
545
|
|
546
|
+
protected
|
547
|
+
|
548
|
+
def selector_string
|
549
|
+
return @selector.inspect if @query_scope.is_a?(Browser)
|
550
|
+
query_scope = if @query_scope.is_a?(IFrame)
|
551
|
+
@query_scope.element.instance_variable_get("@query_scope")
|
552
|
+
else
|
553
|
+
@query_scope
|
554
|
+
end
|
555
|
+
"#{query_scope.selector_string} --> #{@selector.inspect}"
|
556
|
+
end
|
557
|
+
|
557
558
|
private
|
558
559
|
|
559
560
|
def locator_class
|
@@ -578,10 +579,6 @@ module Watir
|
|
578
579
|
self.class.name.split('::').last
|
579
580
|
end
|
580
581
|
|
581
|
-
def selector_string
|
582
|
-
@selector.inspect
|
583
|
-
end
|
584
|
-
|
585
582
|
# Ensure the driver is in the desired browser context
|
586
583
|
def ensure_context
|
587
584
|
@query_scope.is_a?(IFrame) ? @query_scope.switch_to! : @query_scope.assert_exists
|
@@ -620,7 +617,7 @@ module Watir
|
|
620
617
|
def element_call
|
621
618
|
yield
|
622
619
|
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
623
|
-
@element =
|
620
|
+
@element = locate
|
624
621
|
assert_element_found
|
625
622
|
retry
|
626
623
|
end
|
@@ -2,6 +2,7 @@ module Watir
|
|
2
2
|
class IFrame < HTMLElement
|
3
3
|
|
4
4
|
def locate
|
5
|
+
return if @selector.empty?
|
5
6
|
@query_scope.assert_exists
|
6
7
|
|
7
8
|
selector = @selector.merge(tag_name: frame_tag)
|
@@ -15,6 +16,11 @@ module Watir
|
|
15
16
|
FramedDriver.new(element, driver)
|
16
17
|
end
|
17
18
|
|
19
|
+
def ==(other)
|
20
|
+
return false unless other.is_a?(self.class)
|
21
|
+
wd == other.wd.is_a?(FramedDriver) ? other.wd.send(:wd) : other.wd
|
22
|
+
end
|
23
|
+
|
18
24
|
def switch_to!
|
19
25
|
locate.send :switch!
|
20
26
|
end
|
@@ -62,28 +68,6 @@ module Watir
|
|
62
68
|
|
63
69
|
|
64
70
|
class IFrameCollection < ElementCollection
|
65
|
-
|
66
|
-
def to_a
|
67
|
-
# In case `#all_elements` returns empty array, but `#elements`
|
68
|
-
# returns non-empty array (i.e. any frame has loaded between these two calls),
|
69
|
-
# index will return nil. That's why `#all_elements` should always
|
70
|
-
# be called after `#elements.`
|
71
|
-
element_indexes = elements.map { |el| all_elements.index(el) }
|
72
|
-
element_indexes.map { |idx| element_class.new(@query_scope, tag_name: @selector[:tag_name], index: idx) }
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
76
|
-
|
77
|
-
def all_elements
|
78
|
-
selector = { tag_name: @selector[:tag_name] }
|
79
|
-
|
80
|
-
element_validator = element_validator_class.new
|
81
|
-
selector_builder = selector_builder_class.new(@query_scope, selector, element_class.attribute_list)
|
82
|
-
locator = locator_class.new(@query_scope, selector, selector_builder, element_validator)
|
83
|
-
|
84
|
-
locator.locate_all
|
85
|
-
end
|
86
|
-
|
87
71
|
end # IFrameCollection
|
88
72
|
|
89
73
|
|
data/lib/watir/elements/image.rb
CHANGED
@@ -27,32 +27,6 @@ module Watir
|
|
27
27
|
driver.execute_script "return arguments[0].width", @element
|
28
28
|
end
|
29
29
|
|
30
|
-
#
|
31
|
-
# Returns the image's height in pixels.
|
32
|
-
#
|
33
|
-
# @return [Fixnum] width
|
34
|
-
#
|
35
|
-
|
36
|
-
def height
|
37
|
-
assert_exists
|
38
|
-
driver.execute_script "return arguments[0].height", @element
|
39
|
-
end
|
40
|
-
|
41
|
-
def file_created_date
|
42
|
-
assert_exists
|
43
|
-
raise NotImplementedError, "not currently supported by Selenium"
|
44
|
-
end
|
45
|
-
|
46
|
-
def file_size
|
47
|
-
assert_exists
|
48
|
-
raise NotImplementedError, "not currently supported by Selenium"
|
49
|
-
end
|
50
|
-
|
51
|
-
def save(path)
|
52
|
-
assert_exists
|
53
|
-
raise NotImplementedError, "not currently supported by Selenium"
|
54
|
-
end
|
55
|
-
|
56
30
|
end # Image
|
57
31
|
|
58
32
|
module Container
|
data/lib/watir/elements/row.rb
CHANGED
@@ -8,10 +8,10 @@ module Watir
|
|
8
8
|
end # Row
|
9
9
|
|
10
10
|
class RowCollection < TableRowCollection
|
11
|
-
def
|
11
|
+
def to_a
|
12
12
|
# we do this craziness since the xpath used will find direct child rows
|
13
13
|
# before any rows inside thead/tbody/tfoot...
|
14
|
-
super.sort_by { |e| e.
|
14
|
+
super.sort_by { |e| e.attribute_value(:rowIndex).to_i }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end # Watir
|
@@ -7,13 +7,18 @@ module Watir
|
|
7
7
|
inherit_attributes_from Watir::TextArea
|
8
8
|
remove_method :type # we want Input#type here, which was overriden by TextArea's attributes
|
9
9
|
|
10
|
-
|
10
|
+
protected
|
11
11
|
|
12
12
|
def selector_string
|
13
13
|
selector = @selector.dup
|
14
14
|
selector[:type] = '(any text type)'
|
15
15
|
selector[:tag_name] = "input or textarea"
|
16
|
-
|
16
|
+
|
17
|
+
if @query_scope.is_a?(Browser) || @query_scope.is_a?(IFrame)
|
18
|
+
super
|
19
|
+
else
|
20
|
+
"#{@query_scope.selector_string} --> #{selector.inspect}"
|
21
|
+
end
|
17
22
|
end
|
18
23
|
end # TextField
|
19
24
|
|
@@ -38,11 +38,11 @@ module Watir
|
|
38
38
|
def locate
|
39
39
|
e = by_id and return e # short-circuit if :id is given
|
40
40
|
|
41
|
-
if @selector.size == 1
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
element = if @selector.size == 1
|
42
|
+
find_first_by_one
|
43
|
+
else
|
44
|
+
find_first_by_multiple
|
45
|
+
end
|
46
46
|
|
47
47
|
# This actually only applies when finding by xpath/css - browser.text_field(:xpath, "//input[@type='radio']")
|
48
48
|
# We don't need to validate the element if we built the xpath ourselves.
|
@@ -64,16 +64,15 @@ module Watir
|
|
64
64
|
private
|
65
65
|
|
66
66
|
def by_id
|
67
|
-
return unless id = @selector[:id] and id.is_a? String
|
68
|
-
|
69
67
|
selector = @selector.dup
|
70
|
-
selector.delete(:id)
|
68
|
+
id = selector.delete(:id)
|
69
|
+
return unless id.is_a? String
|
71
70
|
|
72
71
|
tag_name = selector.delete(:tag_name)
|
73
72
|
return unless selector.empty? # multiple attributes
|
74
73
|
|
75
74
|
element = @query_scope.wd.find_element(:id, id)
|
76
|
-
return if tag_name && !element_validator.validate(element,
|
75
|
+
return if tag_name && !element_validator.validate(element, {tag_name: tag_name})
|
77
76
|
|
78
77
|
element
|
79
78
|
end
|
@@ -93,19 +92,27 @@ module Watir
|
|
93
92
|
selector = selector_builder.normalized_selector
|
94
93
|
|
95
94
|
idx = selector.delete(:index)
|
95
|
+
visible = selector.delete(:visible)
|
96
|
+
|
96
97
|
how, what = selector_builder.build(selector)
|
97
98
|
|
98
99
|
if how
|
99
100
|
# could build xpath/css for selector
|
100
|
-
if idx
|
101
|
-
|
101
|
+
if idx || !visible.nil?
|
102
|
+
idx ||= 0
|
103
|
+
elements = @query_scope.wd.find_elements(how, what)
|
104
|
+
elements = elements.select { |el| visible == el.displayed? } unless visible.nil?
|
105
|
+
elements[idx] unless elements.nil?
|
102
106
|
else
|
103
107
|
@query_scope.wd.find_element(how, what)
|
104
108
|
end
|
105
109
|
else
|
106
110
|
# can't use xpath, probably a regexp in there
|
107
|
-
if idx
|
108
|
-
|
111
|
+
if idx || !visible.nil?
|
112
|
+
idx ||= 0
|
113
|
+
elements = wd_find_by_regexp_selector(selector, :select)
|
114
|
+
elements = elements.select { |el| visible == el.displayed? } unless visible.nil?
|
115
|
+
elements[idx] unless elements.nil?
|
109
116
|
else
|
110
117
|
wd_find_by_regexp_selector(selector, :find)
|
111
118
|
end
|
@@ -30,6 +30,10 @@ module Watir
|
|
30
30
|
unless what.is_a?(Fixnum)
|
31
31
|
raise TypeError, "expected Fixnum, got #{what.inspect}:#{what.class}"
|
32
32
|
end
|
33
|
+
when :visible
|
34
|
+
unless what.is_a?(TrueClass) || what.is_a?(FalseClass)
|
35
|
+
raise TypeError, "expected TrueClass or FalseClass, got #{what.inspect}:#{what.class}"
|
36
|
+
end
|
33
37
|
else
|
34
38
|
unless VALID_WHATS.any? { |t| what.is_a? t }
|
35
39
|
raise TypeError, "expected one of #{VALID_WHATS.inspect}, got #{what.inspect}:#{what.class}"
|
@@ -53,7 +57,7 @@ module Watir
|
|
53
57
|
|
54
58
|
def normalize_selector(how, what)
|
55
59
|
case how
|
56
|
-
when :tag_name, :text, :xpath, :index, :class, :label, :css
|
60
|
+
when :tag_name, :text, :xpath, :index, :class, :label, :css, :visible
|
57
61
|
# include :class since the valid attribute is 'class_name'
|
58
62
|
# include :for since the valid attribute is 'html_for'
|
59
63
|
[how, what]
|
data/lib/watir/window.rb
CHANGED
data/spec/element_spec.rb
CHANGED
@@ -49,34 +49,24 @@ describe Watir::Element do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
describe "#reset!" do
|
53
|
-
it "successfully relocates collection elements after a reset!" do
|
54
|
-
browser.goto(WatirSpec.url_for("wait.html"))
|
55
|
-
element = browser.div(id: 'foo')
|
56
|
-
expect(element).to exist
|
57
|
-
browser.refresh
|
58
|
-
browser.div(id: 'foo').wait_until_present
|
59
|
-
|
60
|
-
expect(element.exist?).to be false unless Watir.always_locate?
|
61
|
-
element.send :reset!
|
62
|
-
expect(element).to exist
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
52
|
describe "#exists?" do
|
67
53
|
before do
|
68
54
|
browser.goto WatirSpec.url_for('removed_element.html')
|
69
55
|
end
|
70
56
|
|
71
|
-
it "
|
57
|
+
it "relocates element from a collection when it becomes stale" do
|
72
58
|
watir_element = browser.divs(id: "text").first
|
73
59
|
expect(watir_element).to exist
|
74
60
|
|
75
61
|
browser.refresh
|
76
62
|
|
77
|
-
expect(watir_element).
|
63
|
+
expect(watir_element).to exist
|
78
64
|
end
|
79
65
|
|
66
|
+
it "returns false when tag name does not match id" do
|
67
|
+
watir_element = browser.span(id: "text")
|
68
|
+
expect(watir_element).to_not exist
|
69
|
+
end
|
80
70
|
end
|
81
71
|
|
82
72
|
describe "#element_call" do
|
@@ -129,4 +119,34 @@ describe Watir::Element do
|
|
129
119
|
end.to output.to_stderr
|
130
120
|
end
|
131
121
|
end
|
122
|
+
|
123
|
+
describe "#selector_string" do
|
124
|
+
it "displays selector string for regular element" do
|
125
|
+
browser.goto(WatirSpec.url_for("wait.html"))
|
126
|
+
delegator = browser.div(:id, 'foo').when_present
|
127
|
+
message = delegator.instance_variable_get('@message')
|
128
|
+
expect(message).to eq 'waiting for {:id=>"foo", :tag_name=>"div"} to become present'
|
129
|
+
end
|
130
|
+
|
131
|
+
it "displays selector string for element from colection" do
|
132
|
+
browser.goto(WatirSpec.url_for("wait.html"))
|
133
|
+
delegator = browser.divs.last.when_present
|
134
|
+
message = delegator.instance_variable_get('@message')
|
135
|
+
expect(message).to match /waiting for {:tag_name=>\"div\", :index=>3} to become present/
|
136
|
+
end
|
137
|
+
|
138
|
+
it "displays selector string for nested element" do
|
139
|
+
browser.goto(WatirSpec.url_for("wait.html"))
|
140
|
+
delegator = browser.div(index: -1).div(:id, 'foo').when_present
|
141
|
+
message = delegator.instance_variable_get('@message')
|
142
|
+
expect(message).to eq 'waiting for {:index=>-1, :tag_name=>"div"} --> {:id=>"foo", :tag_name=>"div"} to become present'
|
143
|
+
end
|
144
|
+
|
145
|
+
it "displays selector string for nested element under frame" do
|
146
|
+
browser.goto(WatirSpec.url_for("nested_iframes.html"))
|
147
|
+
delegator = browser.iframe(id: 'one').iframe(:id, 'three').when_present
|
148
|
+
message = delegator.instance_variable_get('@message')
|
149
|
+
expect(message).to eq 'waiting for {:id=>"one", :tag_name=>"iframe"} --> {:id=>"three", :tag_name=>"iframe"} to become present'
|
150
|
+
end
|
151
|
+
end
|
132
152
|
end
|
data/watir.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: watir
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.0.
|
4
|
+
version: 6.0.0.beta5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Rodionov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-09-
|
12
|
+
date: 2016-09-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: selenium-webdriver
|