From e2cdf53c739297bde829d55ec3e4f7f4bfc28bed Mon Sep 17 00:00:00 2001 From: Thomas Walpole Date: Thu, 22 Dec 2016 16:25:16 -0800 Subject: [PATCH] Support passing of arguments to execute/evaluate_script --- lib/capybara/poltergeist/browser.rb | 8 ++-- .../poltergeist/client/browser.coffee | 14 ++++-- .../poltergeist/client/compiled/browser.js | 44 ++++++++++++++----- .../poltergeist/client/compiled/web_page.js | 4 +- .../poltergeist/client/web_page.coffee | 16 ++++++- lib/capybara/poltergeist/driver.rb | 8 ++-- lib/capybara/poltergeist/node.rb | 10 +++++ poltergeist.gemspec | 2 +- 8 files changed, 79 insertions(+), 27 deletions(-) diff --git a/lib/capybara/poltergeist/browser.rb b/lib/capybara/poltergeist/browser.rb index c194c69..0e9d333 100644 --- a/lib/capybara/poltergeist/browser.rb +++ b/lib/capybara/poltergeist/browser.rb @@ -120,12 +120,12 @@ module Capybara::Poltergeist command 'click_coordinates', x, y end - def evaluate(script) - command 'evaluate', script + def evaluate(script, *args) + command 'evaluate', script, *args end - def execute(script) - command 'execute', script + def execute(script, *args) + command 'execute', script, *args end def within_frame(handle, &block) diff --git a/lib/capybara/poltergeist/client/browser.coffee b/lib/capybara/poltergeist/client/browser.coffee index ec76dd5..9ddb7b8 100644 --- a/lib/capybara/poltergeist/client/browser.coffee +++ b/lib/capybara/poltergeist/client/browser.coffee @@ -199,11 +199,15 @@ class Poltergeist.Browser path: (page_id, id) -> @current_command.sendResponse this.node(page_id, id).path() - evaluate: (script) -> - @current_command.sendResponse @currentPage.evaluate("function() { return #{script} }") + evaluate: (script, args...) -> + for arg in args when @_isElementArgument(arg) + throw new Poltergeist.ObsoleteNode if arg["ELEMENT"]["page_id"] != @currentPage.id + @current_command.sendResponse @currentPage.evaluate("function() { return #{script} }", args...) - execute: (script) -> - @currentPage.execute("function() { #{script} }") + execute: (script, args...) -> + for arg in args when @_isElementArgument(arg) + throw new Poltergeist.ObsoleteNode if arg["ELEMENT"]["page_id"] != @currentPage.id + @currentPage.execute("function() { #{script} }", args...) @current_command.sendResponse(true) frameUrl: (frame_name) -> @@ -535,3 +539,5 @@ class Poltergeist.Browser wildcard = wildcard.replace(/\?/g, ".") new RegExp(wildcard, "i") + _isElementArgument: (arg)-> + typeof(arg) == "object" and typeof(arg['ELEMENT']) == "object" diff --git a/lib/capybara/poltergeist/client/compiled/browser.js b/lib/capybara/poltergeist/client/compiled/browser.js index 488d2d9..e226bb4 100644 --- a/lib/capybara/poltergeist/client/compiled/browser.js +++ b/lib/capybara/poltergeist/client/compiled/browser.js @@ -1,5 +1,5 @@ -var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; +var slice = [].slice, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Poltergeist.Browser = (function() { function Browser(width, height) { @@ -249,12 +249,32 @@ Poltergeist.Browser = (function() { return this.current_command.sendResponse(this.node(page_id, id).path()); }; - Browser.prototype.evaluate = function(script) { - return this.current_command.sendResponse(this.currentPage.evaluate("function() { return " + script + " }")); + Browser.prototype.evaluate = function() { + var arg, args, i, len, ref, script; + script = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + for (i = 0, len = args.length; i < len; i++) { + arg = args[i]; + if (this._isElementArgument(arg)) { + if (arg["ELEMENT"]["page_id"] !== this.currentPage.id) { + throw new Poltergeist.ObsoleteNode; + } + } + } + return this.current_command.sendResponse((ref = this.currentPage).evaluate.apply(ref, ["function() { return " + script + " }"].concat(slice.call(args)))); }; - Browser.prototype.execute = function(script) { - this.currentPage.execute("function() { " + script + " }"); + Browser.prototype.execute = function() { + var arg, args, i, len, ref, script; + script = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + for (i = 0, len = args.length; i < len; i++) { + arg = args[i]; + if (this._isElementArgument(arg)) { + if (arg["ELEMENT"]["page_id"] !== this.currentPage.id) { + throw new Poltergeist.ObsoleteNode; + } + } + } + (ref = this.currentPage).execute.apply(ref, ["function() { " + script + " }"].concat(slice.call(args))); return this.current_command.sendResponse(true); }; @@ -477,9 +497,9 @@ Poltergeist.Browser = (function() { return this.current_command.sendResponse(true); }; - Browser.prototype.render_base64 = function(format, arg) { + Browser.prototype.render_base64 = function(format, arg1) { var dimensions, encoded_image, full, ref, ref1, ref2, ref3, selector, window_scroll_position; - ref = arg != null ? arg : {}, full = (ref1 = ref.full) != null ? ref1 : false, selector = (ref2 = ref.selector) != null ? ref2 : null; + ref = arg1 != null ? arg1 : {}, full = (ref1 = ref.full) != null ? ref1 : false, selector = (ref2 = ref.selector) != null ? ref2 : null; window_scroll_position = this.currentPage["native"]().evaluate("function(){ return [window.pageXOffset, window.pageYOffset] }"); dimensions = this.set_clip_rect(full, selector); encoded_image = this.currentPage.renderBase64(format); @@ -491,9 +511,9 @@ Poltergeist.Browser = (function() { return this.current_command.sendResponse(encoded_image); }; - Browser.prototype.render = function(path, arg) { + Browser.prototype.render = function(path, arg1) { var dimensions, format, full, options, quality, ref, ref1, ref2, ref3, ref4, ref5, selector, window_scroll_position; - ref = arg != null ? arg : {}, full = (ref1 = ref.full) != null ? ref1 : false, selector = (ref2 = ref.selector) != null ? ref2 : null, format = (ref3 = ref.format) != null ? ref3 : null, quality = (ref4 = ref.quality) != null ? ref4 : null; + ref = arg1 != null ? arg1 : {}, full = (ref1 = ref.full) != null ? ref1 : false, selector = (ref2 = ref.selector) != null ? ref2 : null, format = (ref3 = ref.format) != null ? ref3 : null, quality = (ref4 = ref.quality) != null ? ref4 : null; window_scroll_position = this.currentPage["native"]().evaluate("function(){ return [window.pageXOffset, window.pageYOffset] }"); dimensions = this.set_clip_rect(full, selector); options = {}; @@ -733,6 +753,10 @@ Poltergeist.Browser = (function() { return new RegExp(wildcard, "i"); }; + Browser.prototype._isElementArgument = function(arg) { + return typeof arg === "object" && typeof arg['ELEMENT'] === "object"; + }; + return Browser; })(); diff --git a/lib/capybara/poltergeist/client/compiled/web_page.js b/lib/capybara/poltergeist/client/compiled/web_page.js index 2aaede1..28ac89c 100644 --- a/lib/capybara/poltergeist/client/compiled/web_page.js +++ b/lib/capybara/poltergeist/client/compiled/web_page.js @@ -505,13 +505,13 @@ Poltergeist.WebPage = (function() { var args, fn, ref2; fn = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; this.injectAgent(); - return (ref2 = this["native"]()).evaluate.apply(ref2, ["function() { var _result = " + (this.stringifyCall(fn)) + "; return (_result == null) ? undefined : _result; }"].concat(slice.call(args))); + return (ref2 = this["native"]()).evaluate.apply(ref2, ["function() { for(var i=0; i < arguments.length; i++){ if ((typeof(arguments[i]) == 'object') && (typeof(arguments[i]['ELEMENT']) == 'object')){ arguments[i] = window.__poltergeist.get(arguments[i]['ELEMENT']['id']).element; } } var _result = " + (this.stringifyCall(fn)) + "; return (_result == null) ? undefined : _result; }"].concat(slice.call(args))); }; WebPage.prototype.execute = function() { var args, fn, ref2; fn = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; - return (ref2 = this["native"]()).evaluate.apply(ref2, ["function() { " + (this.stringifyCall(fn)) + " }"].concat(slice.call(args))); + return (ref2 = this["native"]()).evaluate.apply(ref2, ["function() { for(var i=0; i < arguments.length; i++){ if ((typeof(arguments[i]) == 'object') && (typeof(arguments[i]['ELEMENT']) == 'object')){ arguments[i] = window.__poltergeist.get(arguments[i]['ELEMENT']['id']).element; } } " + (this.stringifyCall(fn)) + " }"].concat(slice.call(args))); }; WebPage.prototype.stringifyCall = function(fn) { diff --git a/lib/capybara/poltergeist/client/web_page.coffee b/lib/capybara/poltergeist/client/web_page.coffee index 0672fec..1f45a80 100644 --- a/lib/capybara/poltergeist/client/web_page.coffee +++ b/lib/capybara/poltergeist/client/web_page.coffee @@ -345,11 +345,23 @@ class Poltergeist.WebPage evaluate: (fn, args...) -> this.injectAgent() - this.native().evaluate("function() { var _result = #{this.stringifyCall(fn)}; + this.native().evaluate("function() { + for(var i=0; i < arguments.length; i++){ + if ((typeof(arguments[i]) == 'object') && (typeof(arguments[i]['ELEMENT']) == 'object')){ + arguments[i] = window.__poltergeist.get(arguments[i]['ELEMENT']['id']).element; + } + } + var _result = #{this.stringifyCall(fn)}; return (_result == null) ? undefined : _result; }", args...) execute: (fn, args...) -> - this.native().evaluate("function() { #{this.stringifyCall(fn)} }", args...) + this.native().evaluate("function() { + for(var i=0; i < arguments.length; i++){ + if ((typeof(arguments[i]) == 'object') && (typeof(arguments[i]['ELEMENT']) == 'object')){ + arguments[i] = window.__poltergeist.get(arguments[i]['ELEMENT']['id']).element; + } + } + #{this.stringifyCall(fn)} }", args...) stringifyCall: (fn) -> "(#{fn.toString()}).apply(this, arguments)" diff --git a/lib/capybara/poltergeist/driver.rb b/lib/capybara/poltergeist/driver.rb index a692573..beaf75d 100644 --- a/lib/capybara/poltergeist/driver.rb +++ b/lib/capybara/poltergeist/driver.rb @@ -134,12 +134,12 @@ module Capybara::Poltergeist browser.click_coordinates(x, y) end - def evaluate_script(script) - browser.evaluate(script) + def evaluate_script(script, *args) + browser.evaluate(script, *args) end - def execute_script(script) - browser.execute(script) + def execute_script(script, *args) + browser.execute(script, *args) nil end diff --git a/lib/capybara/poltergeist/node.rb b/lib/capybara/poltergeist/node.rb index 555c0ec..636db67 100644 --- a/lib/capybara/poltergeist/node.rb +++ b/lib/capybara/poltergeist/node.rb @@ -168,6 +168,16 @@ module Capybara::Poltergeist command :path end + # @api private + def to_json(*) + JSON.generate as_json + end + + # @api private + def as_json(*) + { ELEMENT: {page_id: @page_id, id: @id} } + end + private def filter_text(text) diff --git a/poltergeist.gemspec b/poltergeist.gemspec index 3f5c815..d4cb46f 100644 --- a/poltergeist.gemspec +++ b/poltergeist.gemspec @@ -32,7 +32,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'pdf-reader', '~> 1.3', '>= 1.3.3' s.add_development_dependency 'coffee-script', '~> 2.2' s.add_development_dependency 'guard-coffeescript', '~> 2.0.0' - s.add_development_dependency 'coffee-script-source', '~>1.11.1' + s.add_development_dependency 'coffee-script-source', '~>1.12.2' s.add_development_dependency 'listen', '~> 3.0.6' # listen is required by guard and listen 3.1.0 requires ruby 2.2+ s.add_development_dependency 'erubis' # required by rbx end