watir 6.7.3 → 6.8.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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGES.md +11 -0
- data/lib/watir.rb +4 -1
- data/lib/watir/adjacent.rb +1 -1
- data/lib/watir/browser.rb +5 -3
- data/lib/watir/capabilities.rb +1 -0
- data/lib/watir/container.rb +1 -1
- data/lib/watir/elements/element.rb +31 -98
- data/lib/watir/elements/file_field.rb +1 -1
- data/lib/watir/elements/iframe.rb +1 -1
- data/lib/watir/elements/image.rb +1 -5
- data/lib/watir/elements/input.rb +15 -0
- data/lib/watir/elements/radio.rb +17 -0
- data/lib/watir/elements/select.rb +67 -20
- data/lib/watir/js_execution.rb +141 -0
- data/lib/watir/js_snippets.rb +16 -0
- data/lib/watir/js_snippets/backgroundColor.js +7 -0
- data/lib/watir/{atoms → js_snippets}/fireEvent.js +2 -0
- data/lib/watir/js_snippets/focus.js +3 -0
- data/lib/watir/{atoms → js_snippets}/getInnerHtml.js +1 -0
- data/lib/watir/js_snippets/getInnerText.js +19 -0
- data/lib/watir/{atoms → js_snippets}/getOuterHtml.js +2 -0
- data/lib/watir/js_snippets/getTextContent.js +19 -0
- data/lib/watir/js_snippets/isImageLoaded.js +3 -0
- data/lib/watir/js_snippets/selectOptionsLabel.js +10 -0
- data/lib/watir/js_snippets/selectOptionsText.js +10 -0
- data/lib/watir/js_snippets/selectOptionsValue.js +10 -0
- data/lib/watir/{atoms → js_snippets}/selectText.js +3 -0
- data/lib/watir/js_snippets/selectedOptions.js +11 -0
- data/lib/watir/js_snippets/setValue.js +3 -0
- data/lib/watir/locators/element/locator.rb +24 -10
- data/lib/watir/radio_set.rb +231 -0
- data/lib/watir/user_editable.rb +16 -2
- data/lib/watirspec/remote_server.rb +2 -1
- data/spec/browser_spec.rb +8 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/watirspec/elements/div_spec.rb +22 -0
- data/spec/watirspec/elements/divs_spec.rb +1 -1
- data/spec/watirspec/elements/element_spec.rb +24 -7
- data/spec/watirspec/elements/labels_spec.rb +1 -1
- data/spec/watirspec/elements/radio_spec.rb +17 -3
- data/spec/watirspec/elements/radios_spec.rb +1 -1
- data/spec/watirspec/elements/select_list_spec.rb +167 -65
- data/spec/watirspec/elements/text_field_spec.rb +36 -0
- data/spec/watirspec/html/forms_with_input_elements.html +4 -2
- data/spec/watirspec/html/non_control_elements.html +1 -1
- data/spec/watirspec/radio_set_spec.rb +340 -0
- data/spec/watirspec_helper.rb +14 -1
- data/support/doctest_helper.rb +11 -8
- data/watir.gemspec +2 -2
- metadata +30 -11
- data/lib/watir/atoms.rb +0 -22
- data/lib/watir/atoms/README +0 -3
- data/lib/watir/extensions/select_text.rb +0 -11
@@ -0,0 +1,141 @@
|
|
1
|
+
module Watir
|
2
|
+
module JSExecution
|
3
|
+
|
4
|
+
#
|
5
|
+
# Delegates script execution to Browser or IFrame.
|
6
|
+
#
|
7
|
+
def execute_script(script, *args)
|
8
|
+
@query_scope.execute_script(script, *args)
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Simulates JavaScript events on element.
|
13
|
+
# Note that you may omit "on" from event name.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# browser.button(name: "new_user_button").fire_event :click
|
17
|
+
# browser.button(name: "new_user_button").fire_event "mousemove"
|
18
|
+
# browser.button(name: "new_user_button").fire_event "onmouseover"
|
19
|
+
#
|
20
|
+
# @param [String, Symbol] event_name
|
21
|
+
#
|
22
|
+
|
23
|
+
def fire_event(event_name)
|
24
|
+
event_name = event_name.to_s.sub(/^on/, '').downcase
|
25
|
+
|
26
|
+
element_call { execute_js :fireEvent, @element, event_name }
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Flashes (change background color to a new color and back a few times) element.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# browser.li(id: 'non_link_1').flash
|
34
|
+
# browser.li(id: 'non_link_1').flash(color: "green", flashes: 3, delay: 0.05)
|
35
|
+
# browser.li(id: 'non_link_1').flash(color: "yellow")
|
36
|
+
# browser.li(id: 'non_link_1').flash(flashes: 4)
|
37
|
+
# browser.li(id: 'non_link_1').flash(delay: 0.1)
|
38
|
+
#
|
39
|
+
# @param [String] color what color to flash with
|
40
|
+
# @param [Integer] flashes number of times element should be flashed
|
41
|
+
# @param [Integer, Float] delay how long to wait between flashes
|
42
|
+
#
|
43
|
+
# @return [Watir::Element]
|
44
|
+
#
|
45
|
+
|
46
|
+
def flash(color: 'red', flashes: 10, delay: 0)
|
47
|
+
background_color = style("backgroundColor")
|
48
|
+
element_color = element_call { execute_js(:backgroundColor, @element) }.strip
|
49
|
+
|
50
|
+
flashes.times do |n|
|
51
|
+
nextcolor = n.even? ? color : background_color
|
52
|
+
element_call { execute_js(:backgroundColor, @element, nextcolor) }
|
53
|
+
sleep(delay)
|
54
|
+
end
|
55
|
+
|
56
|
+
element_call { execute_js(:backgroundColor, @element, element_color) }
|
57
|
+
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Focuses element.
|
63
|
+
# Note that Firefox queues focus events until the window actually has focus.
|
64
|
+
#
|
65
|
+
# @see http://code.google.com/p/selenium/issues/detail?id=157
|
66
|
+
#
|
67
|
+
|
68
|
+
def focus
|
69
|
+
element_call { execute_js(:focus, @element) }
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Returns inner HTML code of element.
|
74
|
+
#
|
75
|
+
# @example
|
76
|
+
# browser.div(id: 'shown').inner_html
|
77
|
+
# #=> "<div id=\"hidden\" style=\"display: none;\">Not shown</div><div>Not hidden</div>"
|
78
|
+
#
|
79
|
+
# @return [String]
|
80
|
+
#
|
81
|
+
|
82
|
+
def inner_html
|
83
|
+
element_call { execute_js(:getInnerHtml, @element) }.strip
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Returns inner Text code of element.
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# browser.div(id: 'shown').inner_text
|
91
|
+
# #=> "Not hidden"
|
92
|
+
#
|
93
|
+
# @return [String]
|
94
|
+
#
|
95
|
+
|
96
|
+
def inner_text
|
97
|
+
element_call { execute_js(:getInnerText, @element) }.strip
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Returns outer (inner + element itself) HTML code of element.
|
102
|
+
#
|
103
|
+
# @example
|
104
|
+
# browser.div(id: 'shown').outer_html
|
105
|
+
# #=> "<div id=\"shown\"><div id=\"hidden\" style=\"display: none;\">Not shown</div><div>Not hidden</div></div>"
|
106
|
+
#
|
107
|
+
# @return [String]
|
108
|
+
#
|
109
|
+
|
110
|
+
def outer_html
|
111
|
+
element_call { execute_js(:getOuterHtml, @element) }.strip
|
112
|
+
end
|
113
|
+
alias_method :html, :outer_html
|
114
|
+
|
115
|
+
#
|
116
|
+
# Returns text content of element.
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
# browser.div(id: 'shown').text_content
|
120
|
+
# #=> "Not shownNot hidden"
|
121
|
+
#
|
122
|
+
# @return [String]
|
123
|
+
#
|
124
|
+
|
125
|
+
def text_content
|
126
|
+
element_call { execute_js(:getTextContent, @element) }.strip
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# Selects text on page (as if dragging clicked mouse across provided text).
|
131
|
+
#
|
132
|
+
# @example
|
133
|
+
# browser.li(id: 'non_link_1').select_text('Non-link')
|
134
|
+
#
|
135
|
+
|
136
|
+
def select_text(str)
|
137
|
+
element_call { execute_js :selectText, @element, str }
|
138
|
+
end
|
139
|
+
|
140
|
+
end # JSExecution
|
141
|
+
end # Watir
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Watir
|
2
|
+
module JSSnippets
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def execute_js(function_name, *arguments)
|
7
|
+
file = File.expand_path("../js_snippets/#{function_name}.js", __FILE__)
|
8
|
+
raise Watir::Error, "Can not excute script as #{function_name}.js does not exist" unless File.exist?(file)
|
9
|
+
|
10
|
+
js = File.read(file)
|
11
|
+
script = "return (#{js}).apply(null, arguments)"
|
12
|
+
@query_scope.execute_script(script, *arguments)
|
13
|
+
end
|
14
|
+
|
15
|
+
end # JSSnippets
|
16
|
+
end # Watir
|
@@ -11,6 +11,8 @@
|
|
11
11
|
// See the License for the specific language governing permissions and
|
12
12
|
// limitations under the License.
|
13
13
|
|
14
|
+
// This code was built by the Selenium code base
|
15
|
+
// See https://github.com/SeleniumHQ/selenium/tree/master/javascript/watir-atoms
|
14
16
|
|
15
17
|
function(){return function(){var l=this;
|
16
18
|
function m(a){var c=typeof a;if(c=="object")if(a){if(a instanceof Array)return"array";else if(a instanceof Object)return c;var b=Object.prototype.toString.call(a);if(b=="[object Window]")return"object";if(b=="[object Array]"||typeof a.length=="number"&&typeof a.splice!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("splice"))return"array";if(b=="[object Function]"||typeof a.call!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if(c==
|
@@ -11,6 +11,7 @@
|
|
11
11
|
// See the License for the specific language governing permissions and
|
12
12
|
// limitations under the License.
|
13
13
|
|
14
|
+
// This code is a modification getOuterHtml.js which was built by the Selenium code base
|
14
15
|
|
15
16
|
function(){return function(){var d=this;function e(a,b){function c(){}c.prototype=b.prototype;a.b=b.prototype;a.prototype=new c};function f(a){this.stack=Error().stack||"";if(a)this.message=String(a)}e(f,Error);function i(a){for(var b=1;b<arguments.length;b++){var c=String(arguments[b]).replace(/\$/g,"$$$$");a=a.replace(/\%s/,c)}return a}
|
16
17
|
function j(a,b){var c=0,A=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),B=String(b).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),H=Math.max(A.length,B.length);for(var l=0;c==0&&l<H;l++){var I=A[l]||"",J=B[l]||"",K=RegExp("(\\d*)(\\D*)","g"),L=RegExp("(\\d*)(\\D*)","g");do{var g=K.exec(I)||["","",""],h=L.exec(J)||["","",""];if(g[0].length==0&&h[0].length==0)break;c=k(g[1].length==0?0:parseInt(g[1],10),h[1].length==0?0:parseInt(h[1],10))||k(g[2].length==0,h[2].length==0)||k(g[2],h[2])}while(c==
|
@@ -0,0 +1,19 @@
|
|
1
|
+
// Copyright 2011 Software Freedom Conservatory
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
3
|
+
// you may not use this file except in compliance with the License.
|
4
|
+
// You may obtain a copy of the License at
|
5
|
+
//
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
//
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
11
|
+
// See the License for the specific language governing permissions and
|
12
|
+
// limitations under the License.
|
13
|
+
|
14
|
+
// This code is a modification getOuterHtml.js which was built by the Selenium code base
|
15
|
+
|
16
|
+
function(){return function(){var d=this;function e(a,b){function c(){}c.prototype=b.prototype;a.b=b.prototype;a.prototype=new c};function f(a){this.stack=Error().stack||"";if(a)this.message=String(a)}e(f,Error);function i(a){for(var b=1;b<arguments.length;b++){var c=String(arguments[b]).replace(/\$/g,"$$$$");a=a.replace(/\%s/,c)}return a}
|
17
|
+
function j(a,b){var c=0,A=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),B=String(b).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),H=Math.max(A.length,B.length);for(var l=0;c==0&&l<H;l++){var I=A[l]||"",J=B[l]||"",K=RegExp("(\\d*)(\\D*)","g"),L=RegExp("(\\d*)(\\D*)","g");do{var g=K.exec(I)||["","",""],h=L.exec(J)||["","",""];if(g[0].length==0&&h[0].length==0)break;c=k(g[1].length==0?0:parseInt(g[1],10),h[1].length==0?0:parseInt(h[1],10))||k(g[2].length==0,h[2].length==0)||k(g[2],h[2])}while(c==
|
18
|
+
0)}return c}function k(a,b){if(a<b)return-1;else if(a>b)return 1;return 0};e(function(a,b){b.unshift(a);f.call(this,i.apply(null,b));b.shift();this.a=a},f);var m,n,o,p;function q(){return d.navigator?d.navigator.userAgent:null}p=o=n=m=false;var r;if(r=q()){var s=d.navigator;m=r.indexOf("Opera")==0;n=!m&&r.indexOf("MSIE")!=-1;o=!m&&r.indexOf("WebKit")!=-1;p=!m&&!o&&s.product=="Gecko"}var t=n,u=p,v=o,w;
|
19
|
+
a:{var x="",y;if(m&&d.opera){var z=d.opera.version;x=typeof z=="function"?z():z}else{if(u)y=/rv\:([^\);]+)(\)|;)/;else if(t)y=/MSIE\s+([^\);]+)(\)|;)/;else if(v)y=/WebKit\/(\S+)/;if(y){var C=y.exec(q());x=C?C[1]:""}}if(t){var D,E=d.document;D=E?E.documentMode:undefined;if(D>parseFloat(x)){w=String(D);break a}}w=x}var F={};!t||F["9"]||(F["9"]=j(w,"9")>=0);t&&(F["9"]||(F["9"]=j(w,"9")>=0));function G(a){if("innerText"in a)return a.innerText;else{var b=(a.nodeType==9?a:a.ownerDocument||a.document).createElement("div");b.appendChild(a.cloneNode(true));return b.innerText}}var M="_".split("."),N=d;!(M[0]in N)&&N.execScript&&N.execScript("var "+M[0]);for(var O;M.length&&(O=M.shift());)if(!M.length&&G!==undefined)N[O]=G;else N=N[O]?N[O]:N[O]={};; return this._.apply(null,arguments);}.apply({navigator:typeof window!='undefined'?window.navigator:null}, arguments);}
|
@@ -11,6 +11,8 @@
|
|
11
11
|
// See the License for the specific language governing permissions and
|
12
12
|
// limitations under the License.
|
13
13
|
|
14
|
+
// This code was built by the Selenium code base
|
15
|
+
// See https://github.com/SeleniumHQ/selenium/tree/master/javascript/watir-atoms
|
14
16
|
|
15
17
|
function(){return function(){var d=this;function e(a,b){function c(){}c.prototype=b.prototype;a.b=b.prototype;a.prototype=new c};function f(a){this.stack=Error().stack||"";if(a)this.message=String(a)}e(f,Error);function i(a){for(var b=1;b<arguments.length;b++){var c=String(arguments[b]).replace(/\$/g,"$$$$");a=a.replace(/\%s/,c)}return a}
|
16
18
|
function j(a,b){var c=0,A=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),B=String(b).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),H=Math.max(A.length,B.length);for(var l=0;c==0&&l<H;l++){var I=A[l]||"",J=B[l]||"",K=RegExp("(\\d*)(\\D*)","g"),L=RegExp("(\\d*)(\\D*)","g");do{var g=K.exec(I)||["","",""],h=L.exec(J)||["","",""];if(g[0].length==0&&h[0].length==0)break;c=k(g[1].length==0?0:parseInt(g[1],10),h[1].length==0?0:parseInt(h[1],10))||k(g[2].length==0,h[2].length==0)||k(g[2],h[2])}while(c==
|
@@ -0,0 +1,19 @@
|
|
1
|
+
// Copyright 2011 Software Freedom Conservatory
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
3
|
+
// you may not use this file except in compliance with the License.
|
4
|
+
// You may obtain a copy of the License at
|
5
|
+
//
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
//
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
11
|
+
// See the License for the specific language governing permissions and
|
12
|
+
// limitations under the License.
|
13
|
+
|
14
|
+
// This code is a modification getOuterHtml.js which was built by the Selenium code base
|
15
|
+
|
16
|
+
function(){return function(){var d=this;function e(a,b){function c(){}c.prototype=b.prototype;a.b=b.prototype;a.prototype=new c};function f(a){this.stack=Error().stack||"";if(a)this.message=String(a)}e(f,Error);function i(a){for(var b=1;b<arguments.length;b++){var c=String(arguments[b]).replace(/\$/g,"$$$$");a=a.replace(/\%s/,c)}return a}
|
17
|
+
function j(a,b){var c=0,A=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),B=String(b).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),H=Math.max(A.length,B.length);for(var l=0;c==0&&l<H;l++){var I=A[l]||"",J=B[l]||"",K=RegExp("(\\d*)(\\D*)","g"),L=RegExp("(\\d*)(\\D*)","g");do{var g=K.exec(I)||["","",""],h=L.exec(J)||["","",""];if(g[0].length==0&&h[0].length==0)break;c=k(g[1].length==0?0:parseInt(g[1],10),h[1].length==0?0:parseInt(h[1],10))||k(g[2].length==0,h[2].length==0)||k(g[2],h[2])}while(c==
|
18
|
+
0)}return c}function k(a,b){if(a<b)return-1;else if(a>b)return 1;return 0};e(function(a,b){b.unshift(a);f.call(this,i.apply(null,b));b.shift();this.a=a},f);var m,n,o,p;function q(){return d.navigator?d.navigator.userAgent:null}p=o=n=m=false;var r;if(r=q()){var s=d.navigator;m=r.indexOf("Opera")==0;n=!m&&r.indexOf("MSIE")!=-1;o=!m&&r.indexOf("WebKit")!=-1;p=!m&&!o&&s.product=="Gecko"}var t=n,u=p,v=o,w;
|
19
|
+
a:{var x="",y;if(m&&d.opera){var z=d.opera.version;x=typeof z=="function"?z():z}else{if(u)y=/rv\:([^\);]+)(\)|;)/;else if(t)y=/MSIE\s+([^\);]+)(\)|;)/;else if(v)y=/WebKit\/(\S+)/;if(y){var C=y.exec(q());x=C?C[1]:""}}if(t){var D,E=d.document;D=E?E.documentMode:undefined;if(D>parseFloat(x)){w=String(D);break a}}w=x}var F={};!t||F["9"]||(F["9"]=j(w,"9")>=0);t&&(F["9"]||(F["9"]=j(w,"9")>=0));function G(a){if("textcontent"in a)return a.textContent;else{var b=(a.nodeType==9?a:a.ownerDocument||a.document).createElement("div");b.appendChild(a.cloneNode(true));return b.textContent}}var M="_".split("."),N=d;!(M[0]in N)&&N.execScript&&N.execScript("var "+M[0]);for(var O;M.length&&(O=M.shift());)if(!M.length&&G!==undefined)N[O]=G;else N=N[O]?N[O]:N[O]={};; return this._.apply(null,arguments);}.apply({navigator:typeof window!='undefined'?window.navigator:null}, arguments);}
|
@@ -11,6 +11,9 @@
|
|
11
11
|
// See the License for the specific language governing permissions and
|
12
12
|
// limitations under the License.
|
13
13
|
|
14
|
+
// This code was built by the Selenium code base
|
15
|
+
// See https://github.com/SeleniumHQ/selenium/tree/master/javascript/watir-atoms
|
16
|
+
|
14
17
|
function(){return function(){function f(a){throw a;}var h=void 0,l=null;function m(a){return function(){return this[a]}}function o(a){return function(){return a}}var p,r=this;
|
15
18
|
function s(a){var b=typeof a;if(b=="object")if(a){if(a instanceof Array)return"array";else if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(c=="[object Window]")return"object";if(c=="[object Array]"||typeof a.length=="number"&&typeof a.splice!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("splice"))return"array";if(c=="[object Function]"||typeof a.call!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("call"))return"function"}else return"null";
|
16
19
|
else if(b=="function"&&typeof a.call=="undefined")return"object";return b}function t(a){var b=s(a);return b=="array"||b=="object"&&typeof a.length=="number"}function u(a){return typeof a=="string"}function aa(a){a=s(a);return a=="object"||a=="array"||a=="function"}var ba="closure_uid_"+Math.floor(Math.random()*2147483648).toString(36),ca=0,da=Date.now||function(){return+new Date};function v(a,b){function c(){}c.prototype=b.prototype;a.Q=b.prototype;a.prototype=new c};function ea(a){this.stack=Error().stack||"";if(a)this.message=String(a)}v(ea,Error);ea.prototype.name="CustomError";function fa(a){for(var b=1;b<arguments.length;b++)var c=String(arguments[b]).replace(/\$/g,"$$$$"),a=a.replace(/\%s/,c);return a}function w(a){if(!ga.test(a))return a;a.indexOf("&")!=-1&&(a=a.replace(ha,"&"));a.indexOf("<")!=-1&&(a=a.replace(ia,"<"));a.indexOf(">")!=-1&&(a=a.replace(ja,">"));a.indexOf('"')!=-1&&(a=a.replace(ka,"""));return a}var ha=/&/g,ia=/</g,ja=/>/g,ka=/\"/g,ga=/[&<>\"]/;function la(a,b){if(a<b)return-1;else if(a>b)return 1;return 0}
|
@@ -69,7 +69,7 @@ module Watir
|
|
69
69
|
tag_name = selector.delete(:tag_name)
|
70
70
|
return unless selector.empty? # multiple attributes
|
71
71
|
|
72
|
-
element =
|
72
|
+
element = locate_element(:id, id)
|
73
73
|
return if tag_name && !element_validator.validate(element, {tag_name: tag_name})
|
74
74
|
|
75
75
|
element
|
@@ -98,11 +98,11 @@ module Watir
|
|
98
98
|
# could build xpath/css for selector
|
99
99
|
if idx || !visible.nil?
|
100
100
|
idx ||= 0
|
101
|
-
elements =
|
101
|
+
elements = locate_elements(how, what)
|
102
102
|
elements = elements.select { |el| visible == el.displayed? } unless visible.nil?
|
103
103
|
elements[idx] unless elements.nil?
|
104
104
|
else
|
105
|
-
|
105
|
+
locate_element(how, what)
|
106
106
|
end
|
107
107
|
else
|
108
108
|
# can't use xpath, probably a regexp in there
|
@@ -119,6 +119,7 @@ module Watir
|
|
119
119
|
|
120
120
|
def find_all_by_one
|
121
121
|
how, what = @selector.to_a.first
|
122
|
+
return [what] if how == :element
|
122
123
|
selector_builder.check_type how, what
|
123
124
|
|
124
125
|
if WD_FINDERS.include?(how)
|
@@ -138,7 +139,7 @@ module Watir
|
|
138
139
|
|
139
140
|
how, what = selector_builder.build(selector)
|
140
141
|
found = if how
|
141
|
-
|
142
|
+
locate_elements(how, what)
|
142
143
|
else
|
143
144
|
wd_find_by_regexp_selector(selector, :select)
|
144
145
|
end
|
@@ -148,7 +149,7 @@ module Watir
|
|
148
149
|
|
149
150
|
def wd_find_all_by(how, what)
|
150
151
|
if what.is_a? String
|
151
|
-
|
152
|
+
locate_elements(how, what)
|
152
153
|
else
|
153
154
|
all_elements.select { |element| fetch_value(element, how) =~ what }
|
154
155
|
end
|
@@ -168,19 +169,19 @@ module Watir
|
|
168
169
|
end
|
169
170
|
|
170
171
|
def all_elements
|
171
|
-
|
172
|
+
locate_elements(:xpath, ".//*")
|
172
173
|
end
|
173
174
|
|
174
175
|
def wd_find_first_by(how, what)
|
175
176
|
if what.is_a? String
|
176
|
-
|
177
|
+
locate_element(how, what)
|
177
178
|
else
|
178
179
|
all_elements.find { |element| fetch_value(element, how) =~ what }
|
179
180
|
end
|
180
181
|
end
|
181
182
|
|
182
183
|
def wd_find_by_regexp_selector(selector, method = :find)
|
183
|
-
query_scope =
|
184
|
+
query_scope = ensure_scope_context
|
184
185
|
rx_selector = delete_regexps_from(selector)
|
185
186
|
|
186
187
|
if rx_selector.key?(:label) && selector_builder.should_use_label_element?
|
@@ -207,7 +208,7 @@ module Watir
|
|
207
208
|
end
|
208
209
|
end
|
209
210
|
|
210
|
-
elements =
|
211
|
+
elements = locate_elements(how, what, query_scope)
|
211
212
|
elements.__send__(method) { |el| matches_selector?(el, rx_selector) }
|
212
213
|
end
|
213
214
|
|
@@ -225,7 +226,7 @@ module Watir
|
|
225
226
|
|
226
227
|
def label_from_text(label_exp)
|
227
228
|
# TODO: this won't work correctly if @wd is a sub-element
|
228
|
-
|
229
|
+
locate_elements(:tag_name, 'label').find do |el|
|
229
230
|
matches_selector?(el, text: label_exp)
|
230
231
|
end
|
231
232
|
end
|
@@ -251,6 +252,19 @@ module Watir
|
|
251
252
|
"contains(#{lhs}, #{XpathSupport.escape(literals)})"
|
252
253
|
end
|
253
254
|
end
|
255
|
+
|
256
|
+
def ensure_scope_context
|
257
|
+
@query_scope.wd
|
258
|
+
end
|
259
|
+
|
260
|
+
def locate_element(how, what)
|
261
|
+
@query_scope.wd.find_element(how, what)
|
262
|
+
end
|
263
|
+
|
264
|
+
def locate_elements(how, what, scope = @query_scope.wd)
|
265
|
+
scope.find_elements(how, what)
|
266
|
+
end
|
267
|
+
|
254
268
|
end
|
255
269
|
end
|
256
270
|
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
module Watir
|
2
|
+
class RadioSet
|
3
|
+
extend Forwardable
|
4
|
+
include Watir::Exception
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
delegate [:exists?, :present?, :visible?, :browser] => :source
|
8
|
+
|
9
|
+
attr_reader :source, :frame
|
10
|
+
|
11
|
+
def initialize(query_scope, selector)
|
12
|
+
unless selector.kind_of? Hash
|
13
|
+
raise ArgumentError, "invalid argument: #{selector.inspect}"
|
14
|
+
end
|
15
|
+
|
16
|
+
@source = Radio.new(query_scope, selector)
|
17
|
+
@frame = @source.parent(tag_name: :form)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Yields each Radio associated with this set.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# radio_set = browser.radio_set
|
25
|
+
# radio_set.each do |radio|
|
26
|
+
# puts radio.text
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @yieldparam [Watir::RadioSet] element iterate through the radio buttons.
|
30
|
+
#
|
31
|
+
|
32
|
+
def each(&block)
|
33
|
+
radios.each(&block)
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Get the n'th radio button in this set
|
38
|
+
#
|
39
|
+
# @return Watir::Radio
|
40
|
+
#
|
41
|
+
|
42
|
+
def [](idx)
|
43
|
+
radios[idx]
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# @return Watir::Radio
|
48
|
+
#
|
49
|
+
|
50
|
+
def radio(opt = {})
|
51
|
+
n = name
|
52
|
+
if !n.empty? && (!opt[:name] || opt[:name] == n)
|
53
|
+
frame.radio(opt.merge name: n)
|
54
|
+
elsif n.empty?
|
55
|
+
return source
|
56
|
+
else
|
57
|
+
raise Watir::Exception::UnknownObjectException, "#{opt[:name]} does not match name of RadioSet: #{n}"
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# @return Watir::RadioCollection
|
64
|
+
#
|
65
|
+
|
66
|
+
def radios(opt = {})
|
67
|
+
n = name
|
68
|
+
if !n.empty? && (!opt[:name] || opt[:name] == n)
|
69
|
+
element_call(:wait_for_present) { frame.radios(opt.merge name: n) }
|
70
|
+
elsif n.empty?
|
71
|
+
Watir::RadioCollection.new(frame, element: source.wd)
|
72
|
+
else
|
73
|
+
raise Watir::Exception::UnknownObjectException, "#{opt[:name]} does not match name of RadioSet: #{n}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Returns true if any radio buttons in the set are enabled.
|
79
|
+
#
|
80
|
+
# @return [Boolean]
|
81
|
+
#
|
82
|
+
|
83
|
+
def enabled?
|
84
|
+
any?(&:enabled?)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Returns true if all radio buttons in the set are disabled.
|
89
|
+
#
|
90
|
+
# @return [Boolean]
|
91
|
+
#
|
92
|
+
|
93
|
+
def disabled?
|
94
|
+
!enabled?
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Returns the name attribute for the set.
|
99
|
+
#
|
100
|
+
# @return [String]
|
101
|
+
#
|
102
|
+
|
103
|
+
def name
|
104
|
+
@name ||= source.name
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# If RadioSet exists, this always returns 'radio'.
|
109
|
+
#
|
110
|
+
# @return [String]
|
111
|
+
#
|
112
|
+
|
113
|
+
def type
|
114
|
+
source.send :assert_exists
|
115
|
+
'radio'
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Returns true if the radio set has one or more radio buttons where label matches the given value.
|
120
|
+
#
|
121
|
+
# @param [String, Regexp] str_or_rx
|
122
|
+
# @return [Boolean]
|
123
|
+
#
|
124
|
+
|
125
|
+
def include?(str_or_rx)
|
126
|
+
radio(label: str_or_rx).exist?
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# Select the radio button whose value or label matches the given string.
|
131
|
+
#
|
132
|
+
# @param [String, Regexp] str_or_rx
|
133
|
+
# @raise [Watir::Exception::UnknownObjectException] if the Radio does not exist.
|
134
|
+
# @return [String] The value or text of the radio selected.
|
135
|
+
#
|
136
|
+
|
137
|
+
def select(str_or_rx)
|
138
|
+
found_by_value = radio(value: str_or_rx)
|
139
|
+
found_by_text = radio(label: str_or_rx)
|
140
|
+
|
141
|
+
if found_by_value.exist?
|
142
|
+
found_by_value.click unless found_by_value.selected?
|
143
|
+
return found_by_value.value
|
144
|
+
elsif found_by_text.exist?
|
145
|
+
found_by_text.click unless found_by_text.selected?
|
146
|
+
return found_by_text.text
|
147
|
+
else
|
148
|
+
raise UnknownObjectException, "Unable to locate radio matching #{str_or_rx.inspect}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Returns true if any of the radio button label matches the given value.
|
154
|
+
#
|
155
|
+
# @param [String, Regexp] str_or_rx
|
156
|
+
# @raise [Watir::Exception::UnknownObjectException] if the options do not exist
|
157
|
+
# @return [Boolean]
|
158
|
+
#
|
159
|
+
|
160
|
+
def selected?(str_or_rx)
|
161
|
+
found = frame.radio(label: str_or_rx)
|
162
|
+
|
163
|
+
return found.selected? if found.exist?
|
164
|
+
raise UnknownObjectException, "Unable to locate radio matching #{str_or_rx.inspect}"
|
165
|
+
end
|
166
|
+
|
167
|
+
#
|
168
|
+
# Returns the value of the selected radio button in the set.
|
169
|
+
# Returns nil if no radio is selected.
|
170
|
+
#
|
171
|
+
# @return [String, nil]
|
172
|
+
#
|
173
|
+
|
174
|
+
def value
|
175
|
+
sel = selected
|
176
|
+
sel && sel.value
|
177
|
+
end
|
178
|
+
|
179
|
+
#
|
180
|
+
# Returns the text of the selected radio button in the set.
|
181
|
+
# Returns nil if no option is selected.
|
182
|
+
#
|
183
|
+
# @return [String, nil]
|
184
|
+
#
|
185
|
+
|
186
|
+
def text
|
187
|
+
sel = selected
|
188
|
+
sel && sel.text
|
189
|
+
end
|
190
|
+
|
191
|
+
#
|
192
|
+
# Returns the selected Radio element.
|
193
|
+
# Returns nil if no radio button is selected.
|
194
|
+
#
|
195
|
+
# @return [Watir::Radio, nil]
|
196
|
+
#
|
197
|
+
|
198
|
+
def selected
|
199
|
+
find(&:selected?)
|
200
|
+
end
|
201
|
+
|
202
|
+
#
|
203
|
+
# Returns true if two elements are equal.
|
204
|
+
#
|
205
|
+
# @example
|
206
|
+
# browser.radio_set(id: 'new_user_newsletter_yes') == browser.radio_set(id: 'new_user_newsletter_no')
|
207
|
+
# #=> true
|
208
|
+
#
|
209
|
+
|
210
|
+
def ==(other)
|
211
|
+
return false unless other.kind_of?(self.class)
|
212
|
+
radios == other.radios
|
213
|
+
end
|
214
|
+
alias_method :eql?, :==
|
215
|
+
|
216
|
+
private
|
217
|
+
|
218
|
+
def element_call(*args, &blk)
|
219
|
+
source.send :element_call, *args, &blk
|
220
|
+
end
|
221
|
+
end # RadioSet
|
222
|
+
|
223
|
+
module Container
|
224
|
+
def radio_set(*args)
|
225
|
+
RadioSet.new(self, extract_selector(args).merge(tag_name: "input", type: "radio"))
|
226
|
+
end
|
227
|
+
|
228
|
+
Watir.tag_to_class[:radio_set] = RadioSet
|
229
|
+
end # Container
|
230
|
+
|
231
|
+
end # Watir
|