mirror of
https://github.com/thoughtbot/capybara-webkit
synced 2023-03-27 23:22:28 -04:00
Add Capybara evaluate_async_script support
This commit is contained in:
parent
5a56c48f21
commit
e0e9854145
11 changed files with 122 additions and 10 deletions
|
@ -134,7 +134,7 @@ module Capybara::Webkit
|
|||
end
|
||||
|
||||
def get_window_handles
|
||||
JSON.parse(command('GetWindowHandles'))
|
||||
JSON.parse(command("GetWindowHandles"))
|
||||
end
|
||||
|
||||
def window_handles
|
||||
|
@ -144,7 +144,7 @@ module Capybara::Webkit
|
|||
end
|
||||
|
||||
def get_window_handle
|
||||
command('GetWindowHandle')
|
||||
command("GetWindowHandle")
|
||||
end
|
||||
|
||||
def window_handle
|
||||
|
@ -236,12 +236,17 @@ https://github.com/thoughtbot/capybara-webkit/wiki/Reporting-Crashes
|
|||
end
|
||||
|
||||
def evaluate_script(script, *args)
|
||||
json = command('Evaluate', script, args.to_json)
|
||||
json = command("Evaluate", script, args.to_json)
|
||||
JSON.parse("[#{json}]").first
|
||||
end
|
||||
|
||||
def evaluate_async_script(script, *args)
|
||||
json = command("EvaluateAsync", script, args.to_json)
|
||||
JSON.parse("[#{json}]").first
|
||||
end
|
||||
|
||||
def execute_script(script, *args)
|
||||
command('Execute', script, args.to_json)
|
||||
command("Execute", script, args.to_json)
|
||||
end
|
||||
|
||||
def render(path, width, height)
|
||||
|
|
|
@ -91,6 +91,11 @@ module Capybara::Webkit
|
|||
decode_result(result)
|
||||
end
|
||||
|
||||
def evaluate_async_script(script, *args)
|
||||
result = @browser.evaluate_async_script(script, *encode_args(args))
|
||||
decode_result(result)
|
||||
end
|
||||
|
||||
def console_messages
|
||||
@browser.console_messages
|
||||
end
|
||||
|
|
|
@ -554,12 +554,11 @@ describe Capybara::Webkit::Driver do
|
|||
|
||||
it "evaluates Javascript and returns an object" do
|
||||
result = driver.evaluate_script(%<({ 'one' : 1 })>)
|
||||
expect(result).to eq 'one' => 1
|
||||
expect(result).to eq "one" => 1
|
||||
end
|
||||
|
||||
it "evaluate Javascript and returns an object when the original was readonly" do
|
||||
result = driver.evaluate_script(%<window.getComputedStyle(document.getElementById('greeting'))>)
|
||||
# result = driver.evaluate_script(%<document.getElementById('greeting')>)
|
||||
expect(result).to be_a Hash
|
||||
expect(result["zIndex"]).to eq "auto"
|
||||
end
|
||||
|
@ -584,6 +583,27 @@ describe Capybara::Webkit::Driver do
|
|||
expect(result).to eq [1, 2]
|
||||
end
|
||||
|
||||
it "evaluates asynchronous JS which isn't" do
|
||||
result = driver.evaluate_async_script("arguments[0](4)")
|
||||
expect(result).to eq 4
|
||||
end
|
||||
|
||||
it "evaluates asynchronous JS" do
|
||||
result = driver.evaluate_async_script("setTimeout(function(callback){ callback('jaguar') }, 100, arguments[0])")
|
||||
expect(result).to eq "jaguar"
|
||||
end
|
||||
|
||||
it "evaluates asynchronous JS and returns an object" do
|
||||
result = driver.evaluate_async_script(%<setTimeout(function(callback){ callback({ 'one' : 1 }) }, 100, arguments[0])>)
|
||||
expect(result).to eq "one" => 1
|
||||
end
|
||||
|
||||
it "evaluates asynchronous JS and returns an object when the original was readonly" do
|
||||
result = driver.evaluate_async_script(%<setTimeout(function(callback){ callback(window.getComputedStyle(document.getElementById('greeting'))) }, 100, arguments[0])>)
|
||||
expect(result).to be_a Hash
|
||||
expect(result["zIndex"]).to eq "auto"
|
||||
end
|
||||
|
||||
it "executes Javascript" do
|
||||
driver.execute_script(%<document.getElementById('greeting').innerHTML = 'yo'>)
|
||||
expect(driver.find_xpath("//p[contains(., 'yo')]")).not_to be_empty
|
||||
|
@ -612,6 +632,12 @@ describe Capybara::Webkit::Driver do
|
|||
expect(driver.find_xpath("//p[@id='greeting'][contains(., 'new content')]")).not_to be_empty
|
||||
end
|
||||
|
||||
it "passes elements as arguments to asynchronous script" do
|
||||
greeting = driver.find_xpath("//p[@id='greeting']").first
|
||||
result = driver.evaluate_async_script(%<arguments[2]([arguments[1], arguments[0]])>, greeting, "a string")
|
||||
expect(result).to eq ["a string", greeting]
|
||||
end
|
||||
|
||||
it "passes arguments to evaaluated Javascript" do
|
||||
expect(driver.evaluate_script(%<arguments[0]>, 3)).to eq 3
|
||||
end
|
||||
|
|
|
@ -2,7 +2,8 @@ require "spec_helper"
|
|||
require "capybara/webkit/server"
|
||||
|
||||
describe Capybara::Webkit::Connection do
|
||||
it "ensures the process ends", skip_on_windows: true, skip_on_jruby: true do
|
||||
it "ensures the process ends when the parent process ends", skip_on_windows: true, skip_on_jruby: true do
|
||||
sleep 1 # Without this sleep popen3 hangs on OSX when running the tests - not really sure why
|
||||
read_io, write_io = IO.pipe
|
||||
|
||||
fork_pid = fork do
|
||||
|
|
|
@ -13,7 +13,7 @@ $webkit_server = Capybara::Webkit::Server.new
|
|||
$webkit_connection = Capybara::Webkit::Connection.new(server: $webkit_server)
|
||||
$webkit_browser = Capybara::Webkit::Browser.new($webkit_connection)
|
||||
|
||||
if ENV['DEBUG']
|
||||
if ENV["DEBUG"]
|
||||
$webkit_browser.enable_logging
|
||||
end
|
||||
|
||||
|
@ -61,6 +61,9 @@ RSpec.configure do |c|
|
|||
end
|
||||
)
|
||||
}
|
||||
|
||||
c.filter_run :focus unless ENV["TRAVIS"]
|
||||
c.run_all_when_everything_filtered = true
|
||||
end
|
||||
|
||||
def with_env_vars(vars)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Reset.h"
|
||||
#include "Node.h"
|
||||
#include "Evaluate.h"
|
||||
#include "EvaluateAsync.h"
|
||||
#include "Execute.h"
|
||||
#include "FrameFocus.h"
|
||||
#include "Header.h"
|
||||
|
|
|
@ -18,8 +18,8 @@ void Evaluate::start() {
|
|||
QString eval_script = QString("(function(){"
|
||||
" for(var i=0; i<arguments.length; i++) {"
|
||||
" arguments[i] = JSON.parse(arguments[i]);"
|
||||
" var elem_id;"
|
||||
" if (elem_id = arguments[i]['element-581e-422e-8be1-884c4e116226']) {"
|
||||
" var elem_id = arguments[i]['element-581e-422e-8be1-884c4e116226'];"
|
||||
" if (elem_id) {"
|
||||
" arguments[i] = Capybara.getNode(elem_id);"
|
||||
" };"
|
||||
" };"
|
||||
|
|
54
src/EvaluateAsync.cpp
Normal file
54
src/EvaluateAsync.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "EvaluateAsync.h"
|
||||
#include "WebPage.h"
|
||||
#include "WebPageManager.h"
|
||||
#include "JsonSerializer.h"
|
||||
#include <iostream>
|
||||
|
||||
EvaluateAsync::EvaluateAsync(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
|
||||
}
|
||||
|
||||
void EvaluateAsync::start() {
|
||||
QString script = arguments()[0];
|
||||
QString jsonArgs;
|
||||
if (arguments().length()>1){
|
||||
jsonArgs = arguments()[1];
|
||||
} else {
|
||||
jsonArgs ="[]";
|
||||
}
|
||||
QString eval_script = QString("(function(){"
|
||||
" for(var i=0; i<arguments.length-1; i++) {"
|
||||
" arguments[i] = JSON.parse(arguments[i]);"
|
||||
" var elem_id = arguments[i]['element-581e-422e-8be1-884c4e116226'];"
|
||||
" if (elem_id) {"
|
||||
" arguments[i] = Capybara.getNode(elem_id);"
|
||||
" };"
|
||||
" };"
|
||||
" eval(\"%1\");"
|
||||
" return;"
|
||||
" }).apply(null, %2.concat(function(res){ "
|
||||
" res = Capybara.wrapResult(res);"
|
||||
// This isn't necessary in Qt 5.5 but is in older (at least 5.2 on Travis)
|
||||
" if (res instanceof Array) {"
|
||||
" CapybaraAsync['asyncResult(QVariantList)'](res);"
|
||||
" } else { "
|
||||
" CapybaraAsync['asyncResult(QVariant)'](res);"
|
||||
" }"
|
||||
" }))").arg(script.replace("\"","\\\"").remove("\n"), jsonArgs);
|
||||
QObject invocation_stub;
|
||||
invocation_stub.setProperty("allowUnattached", false);
|
||||
page()->currentFrame()->addToJavaScriptWindowObject("CapybaraInvocation", &invocation_stub);
|
||||
page()->currentFrame()->addToJavaScriptWindowObject("CapybaraAsync", this);
|
||||
page()->currentFrame()->evaluateJavaScript(eval_script);
|
||||
}
|
||||
|
||||
void EvaluateAsync::asyncResult(QVariantList result) {
|
||||
JsonSerializer serializer;
|
||||
finish(true, serializer.serialize(result));
|
||||
}
|
||||
|
||||
void EvaluateAsync::asyncResult(QVariant result) {
|
||||
JsonSerializer serializer;
|
||||
finish(true, serializer.serialize(result));
|
||||
}
|
||||
|
||||
|
14
src/EvaluateAsync.h
Normal file
14
src/EvaluateAsync.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "SocketCommand.h"
|
||||
|
||||
#include <QVariantList>
|
||||
|
||||
class EvaluateAsync : public SocketCommand {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EvaluateAsync(WebPageManager *, QStringList &arguments, QObject *parent = 0);
|
||||
virtual void start();
|
||||
Q_INVOKABLE void asyncResult(QVariant result);
|
||||
Q_INVOKABLE void asyncResult(QVariantList result);
|
||||
};
|
||||
|
|
@ -8,6 +8,7 @@ CHECK_COMMAND(FindXpath)
|
|||
CHECK_COMMAND(Reset)
|
||||
CHECK_COMMAND(Node)
|
||||
CHECK_COMMAND(Evaluate)
|
||||
CHECK_COMMAND(EvaluateAsync)
|
||||
CHECK_COMMAND(Execute)
|
||||
CHECK_COMMAND(FrameFocus)
|
||||
CHECK_COMMAND(Header)
|
||||
|
|
|
@ -47,6 +47,7 @@ HEADERS = \
|
|||
Node.h \
|
||||
JavascriptInvocation.h \
|
||||
Evaluate.h \
|
||||
EvaluateAsync.h \
|
||||
Execute.h \
|
||||
FrameFocus.h \
|
||||
Response.h \
|
||||
|
@ -132,6 +133,7 @@ SOURCES = \
|
|||
Node.cpp \
|
||||
JavascriptInvocation.cpp \
|
||||
Evaluate.cpp \
|
||||
EvaluateAsync.cpp \
|
||||
Execute.cpp \
|
||||
FrameFocus.cpp \
|
||||
Response.cpp \
|
||||
|
|
Loading…
Reference in a new issue