selenium-webdriver 2.53.4 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +363 -10
  3. data/LICENSE +1 -1
  4. data/README.md +2 -3
  5. data/lib/selenium-webdriver.rb +0 -2
  6. data/lib/selenium/server.rb +69 -70
  7. data/lib/selenium/webdriver.rb +32 -23
  8. data/lib/selenium/webdriver/atoms.rb +18 -0
  9. data/lib/selenium/webdriver/atoms/getAttribute.js +8 -0
  10. data/lib/selenium/webdriver/chrome.rb +8 -6
  11. data/lib/selenium/webdriver/chrome/driver.rb +112 -0
  12. data/lib/selenium/webdriver/chrome/options.rb +168 -0
  13. data/lib/selenium/webdriver/chrome/profile.rb +17 -17
  14. data/lib/selenium/webdriver/chrome/service.rb +22 -89
  15. data/lib/selenium/webdriver/common.rb +13 -6
  16. data/lib/selenium/webdriver/common/action_builder.rb +49 -57
  17. data/lib/selenium/webdriver/common/alert.rb +5 -15
  18. data/lib/selenium/webdriver/common/bridge_helper.rb +10 -17
  19. data/lib/selenium/webdriver/common/driver.rb +53 -68
  20. data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_addons.rb} +13 -23
  21. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +4 -8
  22. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +4 -7
  23. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +0 -4
  24. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +0 -4
  25. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +1 -5
  26. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +0 -5
  27. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +4 -9
  28. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +7 -7
  29. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +2 -7
  30. data/lib/selenium/webdriver/common/element.rb +57 -39
  31. data/lib/selenium/webdriver/common/error.rb +204 -106
  32. data/lib/selenium/webdriver/common/file_reaper.rb +3 -11
  33. data/lib/selenium/webdriver/common/html5/local_storage.rb +6 -10
  34. data/lib/selenium/webdriver/common/html5/session_storage.rb +6 -10
  35. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +7 -18
  36. data/lib/selenium/webdriver/{safari/options.rb → common/interactions/input_device.rb} +20 -31
  37. data/lib/selenium/webdriver/common/interactions/interaction.rb +50 -0
  38. data/lib/selenium/webdriver/{safari/browser.rb → common/interactions/interactions.rb} +16 -15
  39. data/lib/selenium/webdriver/common/interactions/key_actions.rb +143 -0
  40. data/lib/selenium/webdriver/common/interactions/key_input.rb +62 -0
  41. data/lib/selenium/webdriver/{android.rb → common/interactions/none_input.rb} +11 -6
  42. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +353 -0
  43. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +132 -0
  44. data/lib/selenium/webdriver/common/keyboard.rb +7 -14
  45. data/lib/selenium/webdriver/common/keys.rb +99 -82
  46. data/lib/selenium/webdriver/common/log_entry.rb +3 -6
  47. data/lib/selenium/webdriver/common/logger.rb +140 -0
  48. data/lib/selenium/webdriver/common/logs.rb +2 -6
  49. data/lib/selenium/webdriver/common/mouse.rb +9 -14
  50. data/lib/selenium/webdriver/common/navigation.rb +2 -6
  51. data/lib/selenium/webdriver/common/options.rb +20 -23
  52. data/lib/selenium/webdriver/common/platform.rb +70 -97
  53. data/lib/selenium/webdriver/common/port_prober.rb +3 -4
  54. data/lib/selenium/webdriver/common/profile_helper.rb +6 -11
  55. data/lib/selenium/webdriver/common/proxy.rb +58 -72
  56. data/lib/selenium/webdriver/common/search_context.rb +22 -29
  57. data/lib/selenium/webdriver/common/service.rb +161 -0
  58. data/lib/selenium/webdriver/common/socket_lock.rb +6 -14
  59. data/lib/selenium/webdriver/common/socket_poller.rb +5 -12
  60. data/lib/selenium/webdriver/common/target_locator.rb +11 -15
  61. data/lib/selenium/webdriver/common/timeouts.rb +4 -8
  62. data/lib/selenium/webdriver/common/touch_action_builder.rb +2 -6
  63. data/lib/selenium/webdriver/common/touch_screen.rb +19 -23
  64. data/lib/selenium/webdriver/common/w3c_action_builder.rb +209 -0
  65. data/lib/selenium/webdriver/{phantomjs.rb → common/w3c_options.rb} +16 -14
  66. data/lib/selenium/webdriver/common/wait.rb +6 -13
  67. data/lib/selenium/webdriver/common/window.rb +48 -17
  68. data/lib/selenium/webdriver/common/zipper.rb +6 -10
  69. data/lib/selenium/webdriver/edge.rb +5 -12
  70. data/lib/selenium/webdriver/edge/bridge.rb +32 -63
  71. data/lib/selenium/webdriver/edge/driver.rb +73 -0
  72. data/lib/selenium/webdriver/edge/service.rb +18 -87
  73. data/lib/selenium/webdriver/firefox.rb +20 -11
  74. data/lib/selenium/webdriver/firefox/binary.rb +40 -56
  75. data/lib/selenium/webdriver/firefox/driver.rb +48 -0
  76. data/lib/selenium/webdriver/firefox/extension.rb +18 -8
  77. data/lib/selenium/webdriver/firefox/extension/prefs.json +3 -11
  78. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  79. data/lib/selenium/webdriver/firefox/launcher.rb +13 -22
  80. data/lib/selenium/webdriver/firefox/legacy/driver.rb +79 -0
  81. data/lib/selenium/webdriver/{iphone.rb → firefox/marionette/bridge.rb} +25 -6
  82. data/lib/selenium/webdriver/firefox/marionette/driver.rb +96 -0
  83. data/lib/selenium/webdriver/firefox/options.rb +149 -0
  84. data/lib/selenium/webdriver/firefox/profile.rb +46 -46
  85. data/lib/selenium/webdriver/firefox/profiles_ini.rb +8 -18
  86. data/lib/selenium/webdriver/firefox/service.rb +23 -83
  87. data/lib/selenium/webdriver/firefox/util.rb +0 -4
  88. data/lib/selenium/webdriver/ie.rb +4 -8
  89. data/lib/selenium/webdriver/ie/driver.rb +90 -0
  90. data/lib/selenium/webdriver/ie/options.rb +136 -0
  91. data/lib/selenium/webdriver/ie/service.rb +58 -0
  92. data/lib/selenium/webdriver/remote.rb +8 -16
  93. data/lib/selenium/webdriver/remote/bridge.rb +96 -565
  94. data/lib/selenium/webdriver/remote/capabilities.rb +76 -94
  95. data/lib/selenium/webdriver/remote/driver.rb +49 -0
  96. data/lib/selenium/webdriver/remote/http/common.rb +22 -20
  97. data/lib/selenium/webdriver/remote/http/curb.rb +9 -12
  98. data/lib/selenium/webdriver/remote/http/default.rb +54 -41
  99. data/lib/selenium/webdriver/remote/http/persistent.rb +9 -8
  100. data/lib/selenium/webdriver/remote/oss/bridge.rb +586 -0
  101. data/lib/selenium/webdriver/remote/oss/commands.rb +221 -0
  102. data/lib/selenium/webdriver/remote/response.rb +39 -27
  103. data/lib/selenium/webdriver/remote/server_error.rb +1 -5
  104. data/lib/selenium/webdriver/remote/w3c/bridge.rb +573 -0
  105. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +290 -0
  106. data/lib/selenium/webdriver/remote/w3c/commands.rb +148 -0
  107. data/lib/selenium/webdriver/safari.rb +20 -29
  108. data/lib/selenium/webdriver/{firefox/w3c_bridge.rb → safari/driver.rb} +21 -30
  109. data/lib/selenium/webdriver/safari/service.rb +57 -0
  110. data/lib/selenium/webdriver/support.rb +1 -2
  111. data/lib/selenium/webdriver/support/abstract_event_listener.rb +17 -4
  112. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -5
  113. data/lib/selenium/webdriver/support/color.rb +57 -42
  114. data/lib/selenium/webdriver/support/escaper.rb +41 -0
  115. data/lib/selenium/webdriver/support/event_firing_bridge.rb +36 -40
  116. data/lib/selenium/webdriver/support/select.rb +33 -86
  117. data/selenium-webdriver.gemspec +22 -25
  118. metadata +254 -261
  119. data/lib/selenium-client.rb +0 -21
  120. data/lib/selenium/client.rb +0 -57
  121. data/lib/selenium/client/base.rb +0 -151
  122. data/lib/selenium/client/driver.rb +0 -29
  123. data/lib/selenium/client/errors.rb +0 -28
  124. data/lib/selenium/client/extensions.rb +0 -132
  125. data/lib/selenium/client/idiomatic.rb +0 -507
  126. data/lib/selenium/client/javascript_expression_builder.rb +0 -135
  127. data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -32
  128. data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -32
  129. data/lib/selenium/client/legacy_driver.rb +0 -1722
  130. data/lib/selenium/client/protocol.rb +0 -123
  131. data/lib/selenium/client/selenium_helper.rb +0 -49
  132. data/lib/selenium/rake/server_task.rb +0 -176
  133. data/lib/selenium/webdriver/android/bridge.rb +0 -68
  134. data/lib/selenium/webdriver/chrome/bridge.rb +0 -139
  135. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
  136. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
  137. data/lib/selenium/webdriver/common/html5/location.rb +0 -19
  138. data/lib/selenium/webdriver/common/w3c_error.rb +0 -194
  139. data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
  140. data/lib/selenium/webdriver/firefox/bridge.rb +0 -89
  141. data/lib/selenium/webdriver/ie/bridge.rb +0 -88
  142. data/lib/selenium/webdriver/ie/server.rb +0 -133
  143. data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
  144. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -78
  145. data/lib/selenium/webdriver/phantomjs/service.rb +0 -130
  146. data/lib/selenium/webdriver/remote/commands.rb +0 -211
  147. data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -668
  148. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -236
  149. data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -132
  150. data/lib/selenium/webdriver/safari/bridge.rb +0 -135
  151. data/lib/selenium/webdriver/safari/resources/client.js +0 -7255
  152. data/lib/selenium/webdriver/safari/server.rb +0 -187
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -24,19 +22,19 @@ require 'date'
24
22
  require 'json'
25
23
 
26
24
  require 'selenium/webdriver/common'
25
+ require 'selenium/webdriver/atoms'
27
26
 
28
27
  module Selenium
29
28
  module WebDriver
30
29
  Point = Struct.new(:x, :y)
31
30
  Dimension = Struct.new(:width, :height)
31
+ Rectangle = Struct.new(:x, :y, :width, :height)
32
32
  Location = Struct.new(:latitude, :longitude, :altitude)
33
33
 
34
- autoload :Android, 'selenium/webdriver/android'
35
34
  autoload :Chrome, 'selenium/webdriver/chrome'
36
35
  autoload :Edge, 'selenium/webdriver/edge'
37
36
  autoload :Firefox, 'selenium/webdriver/firefox'
38
37
  autoload :IE, 'selenium/webdriver/ie'
39
- autoload :IPhone, 'selenium/webdriver/iphone'
40
38
  autoload :PhantomJS, 'selenium/webdriver/phantomjs'
41
39
  autoload :Remote, 'selenium/webdriver/remote'
42
40
  autoload :Safari, 'selenium/webdriver/safari'
@@ -45,37 +43,39 @@ module Selenium
45
43
  # @api private
46
44
 
47
45
  def self.root
48
- @root ||= File.expand_path("../..", __FILE__)
46
+ @root ||= File.expand_path('../..', __FILE__)
49
47
  end
50
48
 
51
49
  #
52
50
  # Create a new Driver instance with the correct bridge for the given browser
53
51
  #
54
- # @param browser [:ie, :internet_explorer, :edge, :remote, :chrome, :firefox, :ff, :android, :iphone, :phantomjs, :safari]
55
- # the driver type to use
56
- # @param *rest
57
- # arguments passed to Bridge.new
52
+ # @overload for(browser)
53
+ # @param [:ie, :internet_explorer, :edge, :remote, :chrome, :firefox, :ff, :phantomjs, :safari] browser The browser to
54
+ # create the driver for
55
+ # @overload for(browser, opts)
56
+ # @param [:ie, :internet_explorer, :edge, :remote, :chrome, :firefox, :ff, :phantomjs, :safari] browser The browser to
57
+ # create the driver for
58
+ # @param [Hash] opts Options passed to Driver.new
58
59
  #
59
60
  # @return [Driver]
60
61
  #
61
- # @see Selenium::WebDriver::Remote::Bridge
62
- # @see Selenium::WebDriver::Firefox::Bridge
63
- # @see Selenium::WebDriver::IE::Bridge
64
- # @see Selenium::WebDriver::Edge::Bridge
65
- # @see Selenium::WebDriver::Chrome::Bridge
66
- # @see Selenium::WebDriver::Android::Bridge
67
- # @see Selenium::WebDriver::IPhone::Bridge
68
- # @see Selenium::WebDriver::PhantomJS::Bridge
69
- # @see Selenium::WebDriver::Safari::Bridge
62
+ # @see Selenium::WebDriver::Remote::Driver
63
+ # @see Selenium::WebDriver::Firefox::Driver
64
+ # @see Selenium::WebDriver::IE::Driver
65
+ # @see Selenium::WebDriver::Edge::Driver
66
+ # @see Selenium::WebDriver::Chrome::Driver
67
+ # @see Selenium::WebDriver::PhantomJS::Driver
68
+ # @see Selenium::WebDriver::Safari::Driver
70
69
  #
71
70
  # @example
72
71
  #
73
- # WebDriver.for :firefox, :profile => "some-profile"
74
- # WebDriver.for :firefox, :profile => Profile.new
75
- # WebDriver.for :remote, :url => "http://localhost:4444/wd/hub", :desired_capabilities => caps
72
+ # WebDriver.for :firefox, profile: 'some-profile'
73
+ # WebDriver.for :firefox, profile: Profile.new
74
+ # WebDriver.for :remote, url: "http://localhost:4444/wd/hub", desired_capabilities: caps
76
75
  #
77
- # One special argument is not passed on to the bridges, :listener. You can pass a listener for this option
78
- # to get notified of WebDriver events. The passed object must respond to #call or implement the methods from AbstractEventListener.
76
+ # One special argument is not passed on to the bridges, :listener.
77
+ # You can pass a listener for this option to get notified of WebDriver events.
78
+ # The passed object must respond to #call or implement the methods from AbstractEventListener.
79
79
  #
80
80
  # @see Selenium::WebDriver::Support::AbstractEventListener
81
81
  #
@@ -84,5 +84,14 @@ module Selenium
84
84
  WebDriver::Driver.for(*args)
85
85
  end
86
86
 
87
+ #
88
+ # Returns logger instance that can be used across the whole Selenium.
89
+ #
90
+ # @return [Logger]
91
+ #
92
+
93
+ def self.logger
94
+ @logger ||= WebDriver::Logger.new
95
+ end
87
96
  end # WebDriver
88
97
  end # Selenium
@@ -0,0 +1,18 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Atoms
4
+
5
+ private
6
+
7
+ def read_atom(function)
8
+ File.read(File.expand_path("../atoms/#{function}.js", __FILE__))
9
+ end
10
+
11
+ def execute_atom(function_name, *arguments)
12
+ script = "return (%s).apply(null, arguments)" % read_atom(function_name)
13
+ execute_script(script, *arguments)
14
+ end
15
+
16
+ end # Atoms
17
+ end # WebDriver
18
+ end # Selenium
@@ -0,0 +1,8 @@
1
+ function(){return function(){var d=this;function f(a){return"string"==typeof a};function h(a,b){this.code=a;this.a=l[a]||m;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(a){return a.toUpperCase().replace(/^[\s\xa0]+/g,"")});b=a.length-5;if(0>b||a.indexOf("Error",b)!=b)a+="Error";this.name=a;a=Error(this.message);a.name=this.name;this.stack=a.stack||""}
2
+ (function(){var a=Error;function b(){}b.prototype=a.prototype;h.b=a.prototype;h.prototype=new b;h.prototype.constructor=h;h.a=function(b,c,g){for(var e=Array(arguments.length-2),k=2;k<arguments.length;k++)e[k-2]=arguments[k];return a.prototype[c].apply(b,e)}})();var m="unknown error",l={15:"element not selectable",11:"element not visible"};l[31]=m;l[30]=m;l[24]="invalid cookie domain";l[29]="invalid element coordinates";l[12]="invalid element state";l[32]="invalid selector";l[51]="invalid selector";
3
+ l[52]="invalid selector";l[17]="javascript error";l[405]="unsupported operation";l[34]="move target out of bounds";l[27]="no such alert";l[7]="no such element";l[8]="no such frame";l[23]="no such window";l[28]="script timeout";l[33]="session not created";l[10]="stale element reference";l[21]="timeout";l[25]="unable to set cookie";l[26]="unexpected alert open";l[13]=m;l[9]="unknown command";h.prototype.toString=function(){return this.name+": "+this.message};var n;a:{var p=d.navigator;if(p){var q=p.userAgent;if(q){n=q;break a}}n=""}function r(a){return-1!=n.indexOf(a)};function t(a,b){for(var e=a.length,c=f(a)?a.split(""):a,g=0;g<e;g++)g in c&&b.call(void 0,c[g],g,a)};function v(){return r("iPhone")&&!r("iPod")&&!r("iPad")};function w(){return(r("Chrome")||r("CriOS"))&&!r("Edge")};var x=r("Opera"),y=r("Trident")||r("MSIE"),z=r("Edge"),A=r("Gecko")&&!(-1!=n.toLowerCase().indexOf("webkit")&&!r("Edge"))&&!(r("Trident")||r("MSIE"))&&!r("Edge"),aa=-1!=n.toLowerCase().indexOf("webkit")&&!r("Edge");function B(){var a=d.document;return a?a.documentMode:void 0}var C;
4
+ a:{var D="",E=function(){var a=n;if(A)return/rv\:([^\);]+)(\)|;)/.exec(a);if(z)return/Edge\/([\d\.]+)/.exec(a);if(y)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(aa)return/WebKit\/(\S+)/.exec(a);if(x)return/(?:Version)[ \/]?(\S+)/.exec(a)}();E&&(D=E?E[1]:"");if(y){var F=B();if(null!=F&&F>parseFloat(D)){C=String(F);break a}}C=D}var G;var H=d.document;G=H&&y?B()||("CSS1Compat"==H.compatMode?parseInt(C,10):5):void 0;var ba=r("Firefox"),ca=v()||r("iPod"),da=r("iPad"),I=r("Android")&&!(w()||r("Firefox")||r("Opera")||r("Silk")),ea=w(),J=r("Safari")&&!(w()||r("Coast")||r("Opera")||r("Edge")||r("Silk")||r("Android"))&&!(v()||r("iPad")||r("iPod"));function K(a){return(a=a.exec(n))?a[1]:""}(function(){if(ba)return K(/Firefox\/([0-9.]+)/);if(y||z||x)return C;if(ea)return v()||r("iPad")||r("iPod")?K(/CriOS\/([0-9.]+)/):K(/Chrome\/([0-9.]+)/);if(J&&!(v()||r("iPad")||r("iPod")))return K(/Version\/([0-9.]+)/);if(ca||da){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(n);if(a)return a[1]+"."+a[2]}else if(I)return(a=K(/Android\s+([0-9.]+)/))?a:K(/Version\/([0-9.]+)/);return""})();var L,M=function(){if(!A)return!1;var a=d.Components;if(!a)return!1;try{if(!a.classes)return!1}catch(g){return!1}var b=a.classes,a=a.interfaces,e=b["@mozilla.org/xpcom/version-comparator;1"].getService(a.nsIVersionComparator),c=b["@mozilla.org/xre/app-info;1"].getService(a.nsIXULAppInfo).version;L=function(a){e.compare(c,""+a)};return!0}(),N=y&&!(8<=Number(G)),fa=y&&!(9<=Number(G));I&&M&&L(2.3);I&&M&&L(4);J&&M&&L(6);var ga={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},O={IMG:" ",BR:"\n"};function P(a,b,e){if(!(a.nodeName in ga))if(3==a.nodeType)e?b.push(String(a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):b.push(a.nodeValue);else if(a.nodeName in O)b.push(O[a.nodeName]);else for(a=a.firstChild;a;)P(a,b,e),a=a.nextSibling};function Q(a,b){b=b.toLowerCase();return"style"==b?ha(a.style.cssText):N&&"value"==b&&R(a,"INPUT")?a.value:fa&&!0===a[b]?String(a.getAttribute(b)):(a=a.getAttributeNode(b))&&a.specified?a.value:null}var ia=/[;]+(?=(?:(?:[^"]*"){2})*[^"]*$)(?=(?:(?:[^']*'){2})*[^']*$)(?=(?:[^()]*\([^()]*\))*[^()]*$)/;
5
+ function ha(a){var b=[];t(a.split(ia),function(a){var c=a.indexOf(":");0<c&&(a=[a.slice(0,c),a.slice(c+1)],2==a.length&&b.push(a[0].toLowerCase(),":",a[1],";"))});b=b.join("");return b=";"==b.charAt(b.length-1)?b:b+";"}function S(a,b){N&&"value"==b&&R(a,"OPTION")&&null===Q(a,"value")?(b=[],P(a,b,!1),a=b.join("")):a=a[b];return a}function R(a,b){b&&"string"!==typeof b&&(b=b.toString());return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}
6
+ function T(a){return R(a,"OPTION")?!0:R(a,"INPUT")?(a=a.type.toLowerCase(),"checkbox"==a||"radio"==a):!1};var ja={"class":"className",readonly:"readOnly"},U="async autofocus autoplay checked compact complete controls declare defaultchecked defaultselected defer disabled draggable ended formnovalidate hidden indeterminate iscontenteditable ismap itemscope loop multiple muted nohref noresize noshade novalidate nowrap open paused pubdate readonly required reversed scoped seamless seeking selected spellcheck truespeed willvalidate".split(" ");function V(a,b){var e=null,c=b.toLowerCase();if("style"==c)return(e=a.style)&&!f(e)&&(e=e.cssText),e;if(("selected"==c||"checked"==c)&&T(a)){if(!T(a))throw new h(15,"Element is not selectable");b="selected";e=a.type&&a.type.toLowerCase();if("checkbox"==e||"radio"==e)b="checked";return S(a,b)?"true":null}var g=R(a,"A");if(R(a,"IMG")&&"src"==c||g&&"href"==c)return(e=Q(a,c))&&(e=S(a,c)),e;if("spellcheck"==c){e=Q(a,c);if(null!==e){if("false"==e.toLowerCase())return"false";if("true"==e.toLowerCase())return"true"}return S(a,
7
+ c)+""}g=ja[b]||b;a:if(f(U))c=f(c)&&1==c.length?U.indexOf(c,0):-1;else{for(var u=0;u<U.length;u++)if(u in U&&U[u]===c){c=u;break a}c=-1}if(0<=c)return(e=null!==Q(a,b)||S(a,g))?"true":null;try{var k=S(a,g)}catch(ka){}(c=null==k)||(c=typeof k,c="object"==c&&null!=k||"function"==c);c?e=Q(a,b):e=k;return null!=e?e.toString():null}var W=["_"],X=d;W[0]in X||!X.execScript||X.execScript("var "+W[0]);
8
+ for(var Y;W.length&&(Y=W.shift());){var Z;if(Z=!W.length)Z=void 0!==V;Z?X[Y]=V:X[Y]&&X[Y]!==Object.prototype[Y]?X=X[Y]:X=X[Y]={}};; return this._.apply(null,arguments);}.apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -20,15 +18,20 @@
20
18
  require 'net/http'
21
19
 
22
20
  require 'selenium/webdriver/chrome/service'
23
- require 'selenium/webdriver/chrome/bridge'
21
+ require 'selenium/webdriver/chrome/driver'
24
22
  require 'selenium/webdriver/chrome/profile'
23
+ require 'selenium/webdriver/chrome/options'
25
24
 
26
25
  module Selenium
27
26
  module WebDriver
28
-
29
27
  module Chrome
30
28
  def self.driver_path=(path)
31
- Service.executable_path = path
29
+ Platform.assert_executable path
30
+ @driver_path = path
31
+ end
32
+
33
+ def self.driver_path
34
+ @driver_path ||= nil
32
35
  end
33
36
 
34
37
  def self.path=(path)
@@ -39,7 +42,6 @@ module Selenium
39
42
  def self.path
40
43
  @path ||= nil
41
44
  end
42
-
43
45
  end # Chrome
44
46
  end # WebDriver
45
47
  end # Selenium
@@ -0,0 +1,112 @@
1
+ # Licensed to the Software Freedom Conservancy (SFC) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The SFC licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ module Selenium
19
+ module WebDriver
20
+ module Chrome
21
+
22
+ #
23
+ # Driver implementation for Chrome.
24
+ # @api private
25
+ #
26
+
27
+ class Driver < WebDriver::Driver
28
+ include DriverExtensions::HasTouchScreen
29
+ include DriverExtensions::HasWebStorage
30
+ include DriverExtensions::TakesScreenshot
31
+
32
+ def initialize(opts = {})
33
+ opts[:desired_capabilities] = create_capabilities(opts)
34
+
35
+ unless opts.key?(:url)
36
+ driver_path = opts.delete(:driver_path) || Chrome.driver_path
37
+ driver_opts = opts.delete(:driver_opts) || {}
38
+ port = opts.delete(:port) || Service::DEFAULT_PORT
39
+
40
+ @service = Service.new(driver_path, port, driver_opts)
41
+ @service.start
42
+ opts[:url] = @service.uri
43
+ end
44
+
45
+ listener = opts.delete(:listener)
46
+ @bridge = Remote::Bridge.handshake(opts)
47
+ super(@bridge, listener: listener)
48
+ end
49
+
50
+ def browser
51
+ :chrome
52
+ end
53
+
54
+ def quit
55
+ super
56
+ ensure
57
+ @service.stop if @service
58
+ end
59
+
60
+ private
61
+
62
+ def create_capabilities(opts)
63
+ caps = opts.delete(:desired_capabilities) { Remote::Capabilities.chrome }
64
+ options = opts.delete(:options) { Options.new }
65
+
66
+ args = opts.delete(:args) || opts.delete(:switches)
67
+ if args
68
+ WebDriver.logger.deprecate ':args or :switches', 'Selenium::WebDriver::Chrome::Options#add_argument'
69
+ raise ArgumentError, ':args must be an Array of Strings' unless args.is_a? Array
70
+ args.each { |arg| options.add_argument(arg.to_s) }
71
+ end
72
+
73
+ profile = opts.delete(:profile)
74
+ if profile
75
+ profile = profile.as_json
76
+
77
+ if options.args.none? { |arg| arg =~ /user-data-dir/ }
78
+ options.add_argument("--user-data-dir=#{profile[:directory]}")
79
+ end
80
+
81
+ if profile[:extensions]
82
+ WebDriver.logger.deprecate 'Using Selenium::WebDriver::Chrome::Profile#extensions',
83
+ 'Selenium::WebDriver::Chrome::Options#add_extension'
84
+ profile[:extensions].each do |extension|
85
+ options.add_encoded_extension(extension)
86
+ end
87
+ end
88
+ end
89
+
90
+ detach = opts.delete(:detach)
91
+ options.add_option(:detach, true) if detach
92
+
93
+ prefs = opts.delete(:prefs)
94
+ if prefs
95
+ WebDriver.logger.deprecate ':prefs', 'Selenium::WebDriver::Chrome::Options#add_preference'
96
+ prefs.each do |key, value|
97
+ options.add_preference(key, value)
98
+ end
99
+ end
100
+
101
+ options = options.as_json
102
+ caps[:chrome_options] = options unless options.empty?
103
+
104
+ caps[:proxy] = opts.delete(:proxy) if opts.key?(:proxy)
105
+ caps[:proxy] ||= opts.delete('proxy') if opts.key?('proxy')
106
+
107
+ caps
108
+ end
109
+ end # Driver
110
+ end # Chrome
111
+ end # WebDriver
112
+ end # Selenium
@@ -0,0 +1,168 @@
1
+ # Licensed to the Software Freedom Conservancy (SFC) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The SFC licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ module Selenium
19
+ module WebDriver
20
+ module Chrome
21
+ class Options
22
+ attr_reader :args, :prefs, :options, :emulation, :extensions, :encoded_extensions
23
+ attr_accessor :binary
24
+
25
+ #
26
+ # Create a new Options instance.
27
+ #
28
+ # @example
29
+ # options = Selenium::WebDriver::Chrome::Options.new(args: ['start-maximized', 'user-data-dir=/tmp/temp_profile'])
30
+ # driver = Selenium::WebDriver.for(:chrome, options: options)
31
+ #
32
+ # @param [Hash] opts the pre-defined options to create the Chrome::Options with
33
+ # @option opts [Array<String>] :args List of command-line arguments to use when starting Chrome
34
+ # @option opts [String] :binary Path to the Chrome executable to use
35
+ # @option opts [Hash] :prefs A hash with each entry consisting of the name of the preference and its value
36
+ # @option opts [Array<String>] :extensions A list of paths to (.crx) Chrome extensions to install on startup
37
+ # @option opts [Hash] :options A hash for raw options
38
+ # @option opts [Hash] :emulation A hash for raw emulation options
39
+ #
40
+
41
+ def initialize(**opts)
42
+ @args = opts.delete(:args) || []
43
+ @binary = opts.delete(:binary) || Chrome.path
44
+ @prefs = opts.delete(:prefs) || {}
45
+ @extensions = opts.delete(:extensions) || []
46
+ @options = opts.delete(:options) || {}
47
+ @emulation = opts.delete(:emulation) || {}
48
+ @encoded_extensions = []
49
+ end
50
+
51
+ #
52
+ # Add an extension by local path.
53
+ #
54
+ # @example
55
+ # options = Selenium::WebDriver::Chrome::Options.new
56
+ # options.add_extension('/path/to/extension.crx')
57
+ #
58
+ # @param [String] path The local path to the .crx file
59
+ #
60
+
61
+ def add_extension(path)
62
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
63
+ raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
64
+ @extensions << path
65
+ end
66
+
67
+ #
68
+ # Add an extension by Base64-encoded string.
69
+ #
70
+ # @example
71
+ # options = Selenium::WebDriver::Chrome::Options.new
72
+ # options.add_encoded_extension(encoded_string)
73
+ #
74
+ # @param [String] encoded The Base64-encoded string of the .crx file
75
+ #
76
+
77
+ def add_encoded_extension(encoded)
78
+ @encoded_extensions << encoded
79
+ end
80
+
81
+ #
82
+ # Add a command-line argument to use when starting Chrome.
83
+ #
84
+ # @example Start Chrome maximized
85
+ # options = Selenium::WebDriver::Chrome::Options.new
86
+ # options.add_argument('start-maximized')
87
+ #
88
+ # @param [String] arg The command-line argument to add
89
+ #
90
+
91
+ def add_argument(arg)
92
+ @args << arg
93
+ end
94
+
95
+ #
96
+ # Add a new option not yet handled by bindings.
97
+ #
98
+ # @example Leave Chrome open when chromedriver is killed
99
+ # options = Selenium::WebDriver::Chrome::Options.new
100
+ # options.add_option(:detach, true)
101
+ #
102
+ # @param [String, Symbol] name Name of the option
103
+ # @param [Boolean, String, Integer] value Value of the option
104
+ #
105
+
106
+ def add_option(name, value)
107
+ @options[name] = value
108
+ end
109
+
110
+ #
111
+ # Add a preference that is only applied to the user profile in use.
112
+ #
113
+ # @example Set the default homepage
114
+ # options = Selenium::WebDriver::Chrome::Options.new
115
+ # options.add_preference('homepage', 'http://www.seleniumhq.com/')
116
+ #
117
+ # @param [String] name Key of the preference
118
+ # @param [Boolean, String, Integer] value Value of the preference
119
+ #
120
+
121
+ def add_preference(name, value)
122
+ prefs[name] = value
123
+ end
124
+
125
+ #
126
+ # Add an emulation device name
127
+ #
128
+ # @example Start Chrome in mobile emulation mode by device name
129
+ # options = Selenium::WebDriver::Chrome::Options.new
130
+ # options.add_emulation(device_name: 'iPhone 6')
131
+ #
132
+ # @example Start Chrome in mobile emulation mode by device metrics
133
+ # options = Selenium::WebDriver::Chrome::Options.new
134
+ # options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
135
+ #
136
+ # @param [String] device_name Name of the device or a hash containing width, height, pixelRatio, touch
137
+ # @param [Hash] device_metrics Hash containing width, height, pixelRatio, touch
138
+ # @param [String] user_agent Full user agent
139
+ #
140
+
141
+ def add_emulation(device_name: nil, device_metrics: nil, user_agent: nil)
142
+ @emulation[:deviceName] = device_name if device_name
143
+ @emulation[:deviceMetrics] = device_metrics if device_metrics
144
+ @emulation[:userAgent] = user_agent if user_agent
145
+ end
146
+
147
+ #
148
+ # @api private
149
+ #
150
+
151
+ def as_json(*)
152
+ extensions = @extensions.map do |crx_path|
153
+ File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
154
+ end
155
+ extensions.concat(@encoded_extensions)
156
+
157
+ opts = @options
158
+ opts[:binary] = @binary if @binary
159
+ opts[:args] = @args if @args.any?
160
+ opts[:extensions] = extensions if extensions.any?
161
+ opts[:mobileEmulation] = @emulation unless @emulation.empty?
162
+ opts[:prefs] = @prefs unless @prefs.empty?
163
+ opts
164
+ end
165
+ end # Options
166
+ end # Chrome
167
+ end # WebDriver
168
+ end # Selenium
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -20,7 +18,6 @@
20
18
  module Selenium
21
19
  module WebDriver
22
20
  module Chrome
23
-
24
21
  #
25
22
  # @private
26
23
  #
@@ -28,8 +25,10 @@ module Selenium
28
25
  class Profile
29
26
  include ProfileHelper
30
27
 
28
+ attr_reader :directory
29
+
31
30
  def initialize(model = nil)
32
- @model = verify_model(model)
31
+ @model = verify_model(model)
33
32
  @extensions = []
34
33
  @encoded_extensions = []
35
34
  end
@@ -53,32 +52,34 @@ module Selenium
53
52
  #
54
53
 
55
54
  def []=(key, value)
56
- parts = key.split(".")
57
- parts[0..-2].inject(prefs) { |pr, k| pr[k] ||= {} }[parts.last] = value
55
+ parts = key.split('.')
56
+ parts[0..-2].inject(prefs) { |a, e| a[e] ||= {} }[parts.last] = value
58
57
  end
59
58
 
60
59
  def [](key)
61
- parts = key.split(".")
62
- parts.inject(prefs) { |pr, k| pr.fetch(k) }
60
+ parts = key.split('.')
61
+ parts.inject(prefs) { |a, e| a.fetch(e) }
63
62
  end
64
63
 
65
64
  def layout_on_disk
66
- dir = @model ? create_tmp_copy(@model) : Dir.mktmpdir("webdriver-chrome-profile")
67
- FileReaper << dir
65
+ @directory = @model ? create_tmp_copy(@model) : Dir.mktmpdir('webdriver-chrome-profile')
66
+ FileReaper << @directory
68
67
 
69
- write_prefs_to dir
68
+ write_prefs_to @directory
70
69
 
71
- dir
70
+ @directory
72
71
  end
73
72
 
74
- def as_json(opts = nil)
73
+ def as_json(*)
75
74
  extensions = @extensions.map do |crx_path|
76
- File.open(crx_path, "rb") { |crx_file| Base64.strict_encode64 crx_file.read }
75
+ File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
77
76
  end
78
77
 
79
78
  extensions.concat(@encoded_extensions)
80
79
 
81
- super.merge('extensions' => extensions)
80
+ opts = {directory: @directory || layout_on_disk}
81
+ opts[:extensions] = extensions if extensions
82
+ opts
82
83
  end
83
84
 
84
85
  private
@@ -87,7 +88,7 @@ module Selenium
87
88
  prefs_file = prefs_file_for(dir)
88
89
 
89
90
  FileUtils.mkdir_p File.dirname(prefs_file)
90
- File.open(prefs_file, "w") { |file| file << JSON.generate(prefs) }
91
+ File.open(prefs_file, 'w') { |file| file << JSON.generate(prefs) }
91
92
  end
92
93
 
93
94
  def prefs
@@ -103,7 +104,6 @@ module Selenium
103
104
  File.join dir, 'Default', 'Preferences'
104
105
  end
105
106
  end # Profile
106
-
107
107
  end # Chrome
108
108
  end # WebDriver
109
109
  end # Selenium