selenium-webdriver 4.23.0 → 4.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +81 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +1 -1
  5. data/NOTICE +1 -1
  6. data/README.md +1 -1
  7. data/bin/linux/selenium-manager +0 -0
  8. data/bin/macos/selenium-manager +0 -0
  9. data/bin/windows/selenium-manager.exe +0 -0
  10. data/lib/selenium/server.rb +1 -1
  11. data/lib/selenium/webdriver/atoms/findElements.js +50 -118
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +3 -3
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +2 -2
  14. data/lib/selenium/webdriver/bidi/browsing_context.rb +73 -46
  15. data/lib/selenium/webdriver/bidi/log_handler.rb +4 -2
  16. data/lib/selenium/webdriver/{common/driver_extensions/has_web_storage.rb → bidi/network/cookies.rb} +12 -12
  17. data/lib/selenium/webdriver/{common/html5/shared_web_storage.rb → bidi/network/credentials.rb} +15 -25
  18. data/lib/selenium/webdriver/bidi/network/headers.rb +38 -0
  19. data/lib/selenium/webdriver/bidi/{browsing_context_info.rb → network/intercepted_auth.rb} +11 -8
  20. data/lib/selenium/webdriver/bidi/{navigate_result.rb → network/intercepted_item.rb} +10 -6
  21. data/lib/selenium/webdriver/{common/html5/session_storage.rb → bidi/network/intercepted_request.rb} +34 -26
  22. data/lib/selenium/webdriver/bidi/network/intercepted_response.rb +81 -0
  23. data/lib/selenium/webdriver/bidi/network/url_pattern.rb +65 -0
  24. data/lib/selenium/webdriver/bidi/network.rb +139 -0
  25. data/lib/selenium/webdriver/bidi/struct.rb +2 -4
  26. data/lib/selenium/webdriver/bidi.rb +5 -0
  27. data/lib/selenium/webdriver/chrome/service.rb +1 -0
  28. data/lib/selenium/webdriver/chromium/driver.rb +0 -1
  29. data/lib/selenium/webdriver/common/child_process.rb +20 -14
  30. data/lib/selenium/webdriver/common/driver.rb +12 -10
  31. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +4 -3
  32. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +7 -0
  33. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +7 -0
  34. data/lib/selenium/webdriver/common/error.rb +3 -1
  35. data/lib/selenium/webdriver/common/fedcm/account.rb +4 -5
  36. data/lib/selenium/webdriver/common/logger.rb +3 -3
  37. data/lib/selenium/webdriver/common/manager.rb +1 -1
  38. data/lib/selenium/webdriver/common/network.rb +102 -0
  39. data/lib/selenium/webdriver/common/service.rb +11 -4
  40. data/lib/selenium/webdriver/common/service_manager.rb +1 -0
  41. data/lib/selenium/webdriver/common/takes_screenshot.rb +1 -0
  42. data/lib/selenium/webdriver/common/target_locator.rb +3 -2
  43. data/lib/selenium/webdriver/common/wait.rb +1 -1
  44. data/lib/selenium/webdriver/common.rb +1 -4
  45. data/lib/selenium/webdriver/devtools.rb +7 -5
  46. data/lib/selenium/webdriver/edge/service.rb +1 -1
  47. data/lib/selenium/webdriver/firefox/driver.rb +0 -19
  48. data/lib/selenium/webdriver/firefox/service.rb +1 -0
  49. data/lib/selenium/webdriver/ie/driver.rb +1 -1
  50. data/lib/selenium/webdriver/ie/service.rb +1 -0
  51. data/lib/selenium/webdriver/remote/bidi_bridge.rb +22 -0
  52. data/lib/selenium/webdriver/remote/bridge.rb +3 -53
  53. data/lib/selenium/webdriver/remote/http/common.rb +2 -0
  54. data/lib/selenium/webdriver/remote/http/curb.rb +11 -5
  55. data/lib/selenium/webdriver/remote/response.rb +18 -0
  56. data/lib/selenium/webdriver/remote.rb +1 -1
  57. data/lib/selenium/webdriver/safari/driver.rb +1 -2
  58. data/lib/selenium/webdriver/safari/service.rb +1 -1
  59. data/lib/selenium/webdriver/support/guards.rb +2 -2
  60. data/lib/selenium/webdriver/version.rb +1 -1
  61. data/selenium-webdriver.gemspec +4 -2
  62. metadata +16 -10
  63. data/lib/selenium/webdriver/common/html5/local_storage.rb +0 -59
@@ -9,7 +9,7 @@ moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:
9
9
  seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};var ia="backgroundColor borderTopColor borderRightColor borderBottomColor borderLeftColor color outlineColor".split(" "),ja=/#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/,ka=/^#(?:[0-9a-f]{3}){1,2}$/i,la=/^(?:rgba)?\((\d{1,3}),\s?(\d{1,3}),\s?(\d{1,3}),\s?(0|1|0\.\d*)\)$/i,ma=/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;function m(a,b){this.code=a;this.a=p[a]||r;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(c){return c.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||""}ca(m,Error);var r="unknown error",p={15:"element not selectable",11:"element not visible"};p[31]=r;p[30]=r;p[24]="invalid cookie domain";p[29]="invalid element coordinates";p[12]="invalid element state";
10
10
  p[32]="invalid selector";p[51]="invalid selector";p[52]="invalid selector";p[17]="javascript error";p[405]="unsupported operation";p[34]="move target out of bounds";p[27]="no such alert";p[7]="no such element";p[8]="no such frame";p[23]="no such window";p[28]="script timeout";p[33]="session not created";p[10]="stale element reference";p[21]="timeout";p[25]="unable to set cookie";p[26]="unexpected alert open";p[13]=r;p[9]="unknown command";var u=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};
11
11
  function na(a,b){var c=0;a=u(String(a)).split(".");b=u(String(b)).split(".");for(var e=Math.max(a.length,b.length),d=0;0==c&&d<e;d++){var f=a[d]||"",h=b[d]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];h=/(\d*)(\D*)(.*)/.exec(h)||["","","",""];if(0==f[0].length&&0==h[0].length)break;c=v(0==f[1].length?0:parseInt(f[1],10),0==h[1].length?0:parseInt(h[1],10))||v(0==f[2].length,0==h[2].length)||v(f[2],h[2]);f=f[3];h=h[3]}while(0==c)}return c}function v(a,b){return a<b?-1:a>b?1:0};var w;a:{var oa=g.navigator;if(oa){var sa=oa.userAgent;if(sa){w=sa;break a}}w=""}function x(a){return-1!=w.indexOf(a)};function y(){return x("Firefox")||x("FxiOS")}function A(){return(x("Chrome")||x("CriOS"))&&!x("Edge")};function ta(a){return String(a).replace(/\-([a-z])/g,function(b,c){return c.toUpperCase()})};function B(){return x("iPhone")&&!x("iPod")&&!x("iPad")};function ua(a,b){var c=va;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var wa=x("Opera"),C=x("Trident")||x("MSIE"),xa=x("Edge"),ya=x("Gecko")&&!(-1!=w.toLowerCase().indexOf("webkit")&&!x("Edge"))&&!(x("Trident")||x("MSIE"))&&!x("Edge"),za=-1!=w.toLowerCase().indexOf("webkit")&&!x("Edge");function Aa(){var a=g.document;return a?a.documentMode:void 0}var E;
12
- a:{var F="",G=function(){var a=w;if(ya)return/rv:([^\);]+)(\)|;)/.exec(a);if(xa)return/Edge\/([\d\.]+)/.exec(a);if(C)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(za)return/WebKit\/(\S+)/.exec(a);if(wa)return/(?:Version)[ \/]?(\S+)/.exec(a)}();G&&(F=G?G[1]:"");if(C){var H=Aa();if(null!=H&&H>parseFloat(F)){E=String(H);break a}}E=F}var va={};function Ba(a){return ua(a,function(){return 0<=na(E,a)})}var I;I=g.document&&C?Aa():void 0;var Ca=y(),Da=B()||x("iPod"),Ea=x("iPad"),Fa=x("Android")&&!(A()||y()||x("Opera")||x("Silk")),Ga=A(),Ha=x("Safari")&&!(A()||x("Coast")||x("Opera")||x("Edge")||x("Edg/")||x("OPR")||y()||x("Silk")||x("Android"))&&!(B()||x("iPad")||x("iPod"));function J(a){return(a=a.exec(w))?a[1]:""}(function(){if(Ca)return J(/Firefox\/([0-9.]+)/);if(C||xa||wa)return E;if(Ga)return B()||x("iPad")||x("iPod")?J(/CriOS\/([0-9.]+)/):J(/Chrome\/([0-9.]+)/);if(Ha&&!(B()||x("iPad")||x("iPod")))return J(/Version\/([0-9.]+)/);if(Da||Ea){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(w);if(a)return a[1]+"."+a[2]}else if(Fa)return(a=J(/Android\s+([0-9.]+)/))?a:J(/Version\/([0-9.]+)/);return""})();var K;if(K=C)K=!(9<=Number(I));var Ia=K;function L(a,b){this.x=void 0!==a?a:0;this.y=void 0!==b?b:0}L.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};L.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};L.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function M(a,b){this.width=a;this.height=b}M.prototype.aspectRatio=function(){return this.width/this.height};M.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};M.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};M.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function N(a){return 9==a.nodeType?a:a.ownerDocument||a.document}function Ja(a,b){a&&(a=a.parentNode);for(var c=0;a;){if(b(a))return a;a=a.parentNode;c++}return null}function Ka(a){this.a=a||g.document||document};function P(a,b){b&&"string"!==typeof b&&(b=b.toString());return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)};function Q(a,b,c,e){this.f=a;this.a=b;this.b=c;this.c=e}Q.prototype.ceil=function(){this.f=Math.ceil(this.f);this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.c=Math.ceil(this.c);return this};Q.prototype.floor=function(){this.f=Math.floor(this.f);this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.c=Math.floor(this.c);return this};Q.prototype.round=function(){this.f=Math.round(this.f);this.a=Math.round(this.a);this.b=Math.round(this.b);this.c=Math.round(this.c);return this};function R(a,b,c,e){this.a=a;this.b=b;this.width=c;this.height=e}R.prototype.ceil=function(){this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};R.prototype.floor=function(){this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};
12
+ a:{var F="",G=function(){var a=w;if(ya)return/rv:([^\);]+)(\)|;)/.exec(a);if(xa)return/Edge\/([\d\.]+)/.exec(a);if(C)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(za)return/WebKit\/(\S+)/.exec(a);if(wa)return/(?:Version)[ \/]?(\S+)/.exec(a)}();G&&(F=G?G[1]:"");if(C){var H=Aa();if(null!=H&&H>parseFloat(F)){E=String(H);break a}}E=F}var va={};function Ba(a){return ua(a,function(){return 0<=na(E,a)})}var I;I=g.document&&C?Aa():void 0;var Ca=y(),Da=B()||x("iPod"),Ea=x("iPad"),Fa=x("Android")&&!(A()||y()||x("Opera")||x("Silk")),Ga=A(),Ha=x("Safari")&&!(A()||x("Coast")||x("Opera")||x("Edge")||x("Edg/")||x("OPR")||y()||x("Silk")||x("Android"))&&!(B()||x("iPad")||x("iPod"));function J(a){return(a=a.exec(w))?a[1]:""}(function(){if(Ca)return J(/Firefox\/([0-9.]+)/);if(C||xa||wa)return E;if(Ga)return B()||x("iPad")||x("iPod")?J(/CriOS\/([0-9.]+)/):J(/Chrome\/([0-9.]+)/);if(Ha&&!(B()||x("iPad")||x("iPod")))return J(/Version\/([0-9.]+)/);if(Da||Ea){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(w);if(a)return a[1]+"."+a[2]}else if(Fa)return(a=J(/Android\s+([0-9.]+)/))?a:J(/Version\/([0-9.]+)/);return""})();var K;if(K=C)K=!(9<=Number(I));var Ia=K;function L(a,b){this.x=void 0!==a?a:0;this.y=void 0!==b?b:0}L.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};L.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};L.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function M(a,b){this.width=a;this.height=b}M.prototype.aspectRatio=function(){return this.width/this.height};M.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};M.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};M.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function N(a){return 9==a.nodeType?a:a.ownerDocument||a.document}function Ja(a,b){a&&(a=a.parentNode);for(var c=0;a;){if(b(a))return a;a=a.parentNode;c++}return null}function Ka(a){this.a=a||g.document||document};function P(a,b){b&&"string"!==typeof b&&(b=b.toString());return a instanceof HTMLFormElement?!!a&&1==a.nodeType&&(!b||"FORM"==b):!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)};function Q(a,b,c,e){this.f=a;this.a=b;this.b=c;this.c=e}Q.prototype.ceil=function(){this.f=Math.ceil(this.f);this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.c=Math.ceil(this.c);return this};Q.prototype.floor=function(){this.f=Math.floor(this.f);this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.c=Math.floor(this.c);return this};Q.prototype.round=function(){this.f=Math.round(this.f);this.a=Math.round(this.a);this.b=Math.round(this.b);this.c=Math.round(this.c);return this};function R(a,b,c,e){this.a=a;this.b=b;this.width=c;this.height=e}R.prototype.ceil=function(){this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};R.prototype.floor=function(){this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};
13
13
  R.prototype.round=function(){this.a=Math.round(this.a);this.b=Math.round(this.b);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var La="function"===typeof ShadowRoot;function S(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return P(a)?a:null}
14
14
  function T(a,b){b=ta(b);if("float"==b||"cssFloat"==b||"styleFloat"==b)b=Ia?"styleFloat":"cssFloat";a:{var c=b;var e=N(a);if(e.defaultView&&e.defaultView.getComputedStyle&&(e=e.defaultView.getComputedStyle(a,null))){c=e[c]||e.getPropertyValue(c)||"";break a}c=""}a=c||Ma(a,b);if(null===a)a=null;else if(0<=da(ia,b)){b:{var d=a.match(la);if(d&&(b=Number(d[1]),c=Number(d[2]),e=Number(d[3]),d=Number(d[4]),0<=b&&255>=b&&0<=c&&255>=c&&0<=e&&255>=e&&0<=d&&1>=d)){b=[b,c,e,d];break b}b=null}if(!b)b:{if(e=a.match(ma))if(b=
15
15
  Number(e[1]),c=Number(e[2]),e=Number(e[3]),0<=b&&255>=b&&0<=c&&255>=c&&0<=e&&255>=e){b=[b,c,e,1];break b}b=null}if(!b)b:{b=a.toLowerCase();c=ha[b.toLowerCase()];if(!c&&(c="#"==b.charAt(0)?b:"#"+b,4==c.length&&(c=c.replace(ja,"#$1$1$2$2$3$3")),!ka.test(c))){b=null;break b}b=[parseInt(c.substr(1,2),16),parseInt(c.substr(3,2),16),parseInt(c.substr(5,2),16),1]}a=b?"rgba("+b.join(", ")+")":a}return a}
@@ -25,4 +25,4 @@ function Oa(a){var b=P(a,"MAP");if(!b&&!P(a,"AREA"))return null;var c=b?a:P(a.pa
25
25
  n&&1==n.nodeType?n:null)d=V(e),b||"default"==a.shape.toLowerCase()||(a=Ra(a),b=Math.min(Math.max(a.a,0),d.width),n=Math.min(Math.max(a.b,0),d.height),d=new R(b+d.a,n+d.b,Math.min(a.width,d.width-b),Math.min(a.height,d.height-n)))}return{image:e,rect:d||new R(0,0,0,0)}}
26
26
  function Ra(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4==a.length){b=a[0];var c=a[1];return new R(b,c,a[2]-b,a[3]-c)}if("circle"==b&&3==a.length)return b=a[2],new R(a[0]-b,a[1]-b,2*b,2*b);if("poly"==b&&2<a.length){b=a[0];c=a[1];for(var e=b,d=c,f=2;f+1<a.length;f+=2)b=Math.min(b,a[f]),e=Math.max(e,a[f]),c=Math.min(c,a[f+1]),d=Math.max(d,a[f+1]);return new R(b,c,e-b,d-c)}return new R(0,0,0,0)}function Qa(a){a=V(a);return new Q(a.b,a.a+a.width,a.b+a.height,a.a)}
27
27
  function Pa(a){if(Ia){if("relative"==T(a,"position"))return 1;a=T(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return Sa(a)}function Sa(a){var b=1,c=T(a,"opacity");c&&(b=Number(c));(a=S(a))&&(b*=Sa(a));return b};function Ta(a,b){function c(e){if(P(e)&&"none"==T(e,"display"))return!1;var d;if((d=e.parentNode)&&d.shadowRoot&&void 0!==e.assignedSlot)d=e.assignedSlot?e.assignedSlot.parentNode:null;else if(e.getDestinationInsertionPoints){var f=e.getDestinationInsertionPoints();0<f.length&&(d=f[f.length-1])}if(La&&d instanceof ShadowRoot){if(d.host.shadowRoot&&d.host.shadowRoot!==d)return!1;d=d.host}return!d||9!=d.nodeType&&11!=d.nodeType?d&&P(d,"DETAILS")&&!d.open&&!P(e,"SUMMARY")?!1:!!d&&c(d):!0}return U(a,
28
- !!b,c)}var X=["_"],Y=g;X[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+X[0]);for(var Z;X.length&&(Z=X.shift());)X.length||void 0===Ta?Y[Z]&&Y[Z]!==Object.prototype[Z]?Y=Y[Z]:Y=Y[Z]={}:Y[Z]=Ta;; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
28
+ !!b,c)}var X=["se_exportedFunctionSymbol"],Y=g;X[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+X[0]);for(var Z;X.length&&(Z=X.shift());)X.length||void 0===Ta?Y[Z]&&Y[Z]!==Object.prototype[Z]?Y=Y[Z]:Y=Y[Z]={}:Y[Z]=Ta;; return this.se_exportedFunctionSymbol.apply(null,arguments);}).apply(window, arguments);}
@@ -17,72 +17,99 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require_relative 'navigate_result'
21
- require_relative 'browsing_context_info'
22
-
23
20
  module Selenium
24
21
  module WebDriver
25
22
  class BiDi
23
+ # Implements the browsingContext Module of the WebDriver-BiDi specification
24
+ #
25
+ # @api private
26
+ #
26
27
  class BrowsingContext
27
- attr_accessor :id
28
-
29
28
  READINESS_STATE = {
30
- none: 'none',
31
- interactive: 'interactive',
32
- complete: 'complete'
29
+ 'none' => 'none',
30
+ 'eager' => 'interactive',
31
+ 'normal' => 'complete'
33
32
  }.freeze
34
33
 
35
- def initialize(driver:, browsing_context_id: nil, type: nil, reference_context: nil)
36
- unless driver.capabilities.web_socket_url
37
- raise Error::WebDriverError,
38
- 'WebDriver instance must support BiDi protocol'
39
- end
40
-
41
- unless type.nil? || %i[window tab].include?(type)
42
- raise ArgumentError,
43
- "Valid types are :window & :tab. Received: #{type.inspect}"
44
- end
45
-
46
- @bidi = driver.bidi
47
- @id = browsing_context_id.nil? ? create(type, reference_context)['context'] : browsing_context_id
34
+ # TODO: store current window handle in bridge object instead of always calling it
35
+ def initialize(bridge)
36
+ @bridge = bridge
37
+ @bidi = @bridge.bidi
38
+ page_load_strategy = bridge.capabilities[:page_load_strategy]
39
+ @readiness = READINESS_STATE[page_load_strategy]
48
40
  end
49
41
 
50
- def navigate(url:, readiness_state: nil)
51
- unless readiness_state.nil? || READINESS_STATE.key?(readiness_state)
52
- raise ArgumentError,
53
- "Valid readiness states are :none, :interactive & :complete. Received: #{readiness_state.inspect}"
54
- end
42
+ # Navigates to the specified URL in the given browsing context.
43
+ #
44
+ # @param url [String] The URL to navigate to.
45
+ # @param context_id [String, NilClass] The ID of the browsing context to navigate in.
46
+ # Defaults to the window handle of the current context.
47
+ def navigate(url, context_id: nil)
48
+ context_id ||= @bridge.window_handle
49
+ @bidi.send_cmd('browsingContext.navigate', context: context_id, url: url, wait: @readiness)
50
+ end
55
51
 
56
- navigate_result = @bidi.send_cmd('browsingContext.navigate', context: @id, url: url,
57
- wait: READINESS_STATE[readiness_state])
52
+ # Traverses the browsing context history by a given delta.
53
+ #
54
+ # @param delta [Integer] The number of steps to traverse.
55
+ # Positive values go forwards, negative values go backwards.
56
+ # @param context_id [String, NilClass] The ID of the context to traverse.
57
+ # Defaults to the window handle of the current context.
58
+ def traverse_history(delta, context_id: nil)
59
+ context_id ||= @bridge.window_handle
60
+ @bidi.send_cmd('browsingContext.traverseHistory', context: context_id, delta: delta)
61
+ end
58
62
 
59
- NavigateResult.new(
60
- url: navigate_result['url'],
61
- navigation_id: navigate_result['navigation']
62
- )
63
+ # Reloads the browsing context.
64
+ # @param [String, NilClass] context_id The ID of the context to reload.
65
+ # Defaults to the window handle of the current context.
66
+ # @param [Boolean] ignore_cache Whether to bypass the cache when reloading.
67
+ # Defaults to false.
68
+ def reload(context_id: nil, ignore_cache: false)
69
+ context_id ||= @bridge.window_handle
70
+ params = {context: context_id, ignore_cache: ignore_cache, wait: @readiness}
71
+ @bidi.send_cmd('browsingContext.reload', **params)
63
72
  end
64
73
 
65
- def get_tree(max_depth: nil)
66
- result = @bidi.send_cmd('browsingContext.getTree', root: @id, maxDepth: max_depth).dig('contexts', 0)
74
+ # Closes the browsing context.
75
+ #
76
+ # @param [String] context_id The ID of the context to close.
77
+ # Defaults to the window handle of the current context.
78
+ def close(context_id: nil)
79
+ context_id ||= @bridge.window_handle
80
+ @bidi.send_cmd('browsingContext.close', context: context_id)
81
+ end
67
82
 
68
- BrowsingContextInfo.new(
69
- id: result['context'],
70
- url: result['url'],
71
- children: result['children'],
72
- parent_context: result['parent']
73
- )
83
+ # Create a new browsing context.
84
+ #
85
+ # @param [Symbol] type The type of browsing context to create.
86
+ # Valid options are :tab and :window with :window being the default
87
+ # @param [String] context_id The reference context for the new browsing context.
88
+ # Defaults to the current window handle.
89
+ #
90
+ # @return [String] The context ID of the created browsing context.
91
+ def create(type: nil, context_id: nil)
92
+ type ||= :window
93
+ context_id ||= @bridge.window_handle
94
+ result = @bidi.send_cmd('browsingContext.create', type: type.to_s, referenceContext: context_id)
95
+ result['context']
74
96
  end
75
97
 
76
- def close
77
- @bidi.send_cmd('browsingContext.close', context: @id)
98
+ def set_viewport(context_id: nil, width: nil, height: nil, device_pixel_ratio: nil)
99
+ context_id ||= @bridge.window_handle
100
+ params = {context: context_id, viewport: {width:, height:}, device_pixel_ratio:}
101
+ @bidi.send_cmd('browsingContext.setViewport', **params)
78
102
  end
79
103
 
80
- private
104
+ def handle_user_prompt(context_id, accept: true, text: nil)
105
+ @bidi.send_cmd('browsingContext.handleUserPrompt', context: context_id, accept: accept, text: text)
106
+ end
81
107
 
82
- def create(type, reference_context)
83
- @bidi.send_cmd('browsingContext.create', type: type.to_s, referenceContext: reference_context)
108
+ def activate(context_id: nil)
109
+ context_id ||= @bridge.window_handle
110
+ @bidi.send_cmd('browsingContext.activate', context: context_id)
84
111
  end
85
- end # BrowsingContext
112
+ end
86
113
  end # BiDi
87
114
  end # WebDriver
88
115
  end # Selenium
@@ -21,8 +21,8 @@ module Selenium
21
21
  module WebDriver
22
22
  class BiDi
23
23
  class LogHandler
24
- ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :method, :args, :type)
25
- JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type)
24
+ ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source, :method, :args)
25
+ JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source)
26
26
 
27
27
  def initialize(bidi)
28
28
  @bidi = bidi
@@ -30,6 +30,7 @@ module Selenium
30
30
  end
31
31
 
32
32
  # @return [int] id of the handler
33
+ # steep:ignore:start
33
34
  def add_message_handler(type)
34
35
  subscribe_log_entry unless @log_entry_subscribed
35
36
  @bidi.add_callback('log.entryAdded') do |params|
@@ -39,6 +40,7 @@ module Selenium
39
40
  end
40
41
  end
41
42
  end
43
+ # steep:ignore:end
42
44
 
43
45
  # @param [int] id of the handler previously added
44
46
  def remove_message_handler(id)
@@ -19,20 +19,20 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- #
23
- # @api private
24
- #
25
-
26
- module DriverExtensions
27
- module HasWebStorage
28
- def local_storage
29
- HTML5::LocalStorage.new @bridge
22
+ class BiDi
23
+ class Cookies < Hash
24
+ def initialize(cookies = {})
25
+ super()
26
+ merge!(cookies)
30
27
  end
31
28
 
32
- def session_storage
33
- HTML5::SessionStorage.new @bridge
29
+ def as_json
30
+ self[:name] = self[:name].to_s
31
+ self[:value] = {type: 'string', value: self[:value].to_s}
32
+
33
+ [compact]
34
34
  end
35
- end # HasWebStorage
36
- end # DriverExtensions
35
+ end
36
+ end # BiDi
37
37
  end # WebDriver
38
38
  end # Selenium
@@ -19,35 +19,25 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- module HTML5
23
- module SharedWebStorage
24
- include Enumerable
22
+ class BiDi
23
+ class Credentials
24
+ attr_accessor :username, :password
25
25
 
26
- def key?(key)
27
- keys.include? key
26
+ def initialize(username: nil, password: nil)
27
+ @username = username
28
+ @password = password
28
29
  end
29
- alias member? key?
30
- alias has_key? key?
31
30
 
32
- def fetch(key)
33
- return self[key] if key? key
34
- return yield(key) if block_given?
31
+ def as_json
32
+ return nil unless username && password
35
33
 
36
- raise KeyError, "missing key #{key.inspect}"
34
+ {
35
+ type: 'password',
36
+ username: username,
37
+ password: password
38
+ }
37
39
  end
38
-
39
- def empty?
40
- to_a.empty?
41
- end
42
-
43
- def each
44
- return enum_for(:each) unless block_given?
45
-
46
- keys.each do |k|
47
- yield k, self[k]
48
- end
49
- end
50
- end # SharedWebStorage
51
- end # HTML5
40
+ end
41
+ end # BiDi
52
42
  end # WebDriver
53
43
  end # Selenium
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ module Selenium
21
+ module WebDriver
22
+ class BiDi
23
+ class Headers < Hash
24
+ def as_json
25
+ map do |name, val|
26
+ {
27
+ name: name.to_s,
28
+ value: {
29
+ type: 'string',
30
+ value: val.to_s
31
+ }
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end # BiDi
37
+ end # WebDriver
38
+ end # Selenium
@@ -20,16 +20,19 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class BiDi
23
- class BrowsingContextInfo
24
- attr_accessor :id, :url, :children, :parent_browsing_context
23
+ class InterceptedAuth < InterceptedItem
24
+ def authenticate(username, password)
25
+ network.continue_with_auth(id, username, password)
26
+ end
27
+
28
+ def skip
29
+ network.continue_without_auth(id)
30
+ end
25
31
 
26
- def initialize(id:, url:, children:, parent_context:)
27
- @id = id
28
- @url = url
29
- @children = children
30
- @parent_browsing_context = parent_context
32
+ def cancel
33
+ network.cancel_auth(id)
31
34
  end
32
- end # BrowsingContextInfo
35
+ end
33
36
  end # BiDi
34
37
  end # WebDriver
35
38
  end # Selenium
@@ -20,14 +20,18 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class BiDi
23
- class NavigateResult
24
- attr_accessor :url, :navigation_id
23
+ class InterceptedItem
24
+ attr_reader :network, :request
25
25
 
26
- def initialize(url:, navigation_id:)
27
- @url = url
28
- @navigation_id = navigation_id
26
+ def initialize(network, request)
27
+ @network = network
28
+ @request = request
29
29
  end
30
- end # NavigateResult
30
+
31
+ def id
32
+ @id ||= @request['request']
33
+ end
34
+ end
31
35
  end # BiDi
32
36
  end # WebDriver
33
37
  end # Selenium
@@ -17,45 +17,53 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require_relative 'cookies'
21
+ require_relative 'headers'
22
+
20
23
  module Selenium
21
24
  module WebDriver
22
- module HTML5
23
- class SessionStorage
24
- include Enumerable
25
- include SharedWebStorage
26
-
27
- def [](key)
28
- @bridge.session_storage_item key
29
- end
25
+ class BiDi
26
+ class InterceptedRequest < InterceptedItem
27
+ attr_accessor :method, :url
28
+ attr_reader :body
30
29
 
31
- def []=(key, value)
32
- @bridge.session_storage_item key, value
30
+ def initialize(network, request)
31
+ super
32
+ @method = nil
33
+ @url = nil
34
+ @body = nil
33
35
  end
34
36
 
35
- def delete(key)
36
- @bridge.remove_session_storage_item key
37
+ def continue
38
+ network.continue_request(
39
+ id: id,
40
+ body: body,
41
+ cookies: cookies.as_json,
42
+ headers: headers.as_json,
43
+ method: method,
44
+ url: url
45
+ )
37
46
  end
38
47
 
39
- def clear
40
- @bridge.clear_session_storage
48
+ def fail
49
+ network.fail_request(id)
41
50
  end
42
51
 
43
- def size
44
- @bridge.session_storage_size
52
+ def body=(value)
53
+ @body = {
54
+ type: 'string',
55
+ value: value.to_json
56
+ }
45
57
  end
46
58
 
47
- def keys
48
- @bridge.session_storage_keys.reverse
59
+ def headers
60
+ @headers ||= Headers.new
49
61
  end
50
62
 
51
- #
52
- # @api private
53
- #
54
-
55
- def initialize(bridge)
56
- @bridge = bridge
63
+ def cookies(cookies = {})
64
+ @cookies ||= Cookies.new(cookies)
57
65
  end
58
- end # SessionStorage
59
- end # HTML5
66
+ end
67
+ end # BiDi
60
68
  end # WebDriver
61
69
  end # Selenium
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ require_relative 'credentials'
21
+ require_relative 'headers'
22
+ require_relative 'cookies'
23
+
24
+ module Selenium
25
+ module WebDriver
26
+ class BiDi
27
+ class InterceptedResponse < InterceptedItem
28
+ attr_accessor :reason, :status
29
+ attr_reader :body
30
+
31
+ def initialize(network, request)
32
+ super
33
+ @reason = nil
34
+ @status = nil
35
+ @body = nil
36
+ end
37
+
38
+ def continue
39
+ network.continue_response(
40
+ id: id,
41
+ cookies: cookies.as_json,
42
+ headers: headers.as_json,
43
+ credentials: credentials.as_json,
44
+ reason: reason,
45
+ status: status
46
+ )
47
+ end
48
+
49
+ def provide_response
50
+ network.provide_response(
51
+ id: id,
52
+ cookies: cookies.as_json,
53
+ headers: headers.as_json,
54
+ body: body,
55
+ reason: reason,
56
+ status: status
57
+ )
58
+ end
59
+
60
+ def credentials(username: nil, password: nil)
61
+ @credentials ||= Credentials.new(username: username, password: password)
62
+ end
63
+
64
+ def headers
65
+ @headers ||= Headers.new
66
+ end
67
+
68
+ def cookies(cookies = {})
69
+ @cookies ||= Cookies.new(cookies)
70
+ end
71
+
72
+ def body=(value)
73
+ @body = {
74
+ type: 'string',
75
+ value: value.to_json
76
+ }
77
+ end
78
+ end
79
+ end # BiDi
80
+ end # WebDriver
81
+ end # Selenium
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ require 'uri'
21
+
22
+ module Selenium
23
+ module WebDriver
24
+ class BiDi
25
+ module UrlPattern
26
+ module_function
27
+
28
+ def format_pattern(url_patterns, pattern_type)
29
+ case pattern_type
30
+ when :string
31
+ to_url_string_pattern(url_patterns)
32
+ when :url
33
+ to_url_pattern(url_patterns)
34
+ else
35
+ raise ArgumentError, "Unknown pattern type: #{pattern_type}"
36
+ end
37
+ end
38
+
39
+ def to_url_pattern(*url_patterns)
40
+ url_patterns.flatten.map do |url_pattern|
41
+ uri = URI.parse(url_pattern)
42
+
43
+ {
44
+ type: 'pattern',
45
+ protocol: uri.scheme || '',
46
+ hostname: uri.host || '',
47
+ port: uri.port.to_s || '',
48
+ pathname: uri.path || '',
49
+ search: uri.query || ''
50
+ }
51
+ end
52
+ end
53
+
54
+ def to_url_string_pattern(*url_patterns)
55
+ url_patterns.flatten.map do |url_pattern|
56
+ {
57
+ type: 'string',
58
+ pattern: url_pattern
59
+ }
60
+ end
61
+ end
62
+ end
63
+ end # BiDi
64
+ end # WebDriver
65
+ end # Selenium