Support Capybara 2.11
* Update versions being tested against * Implement missing APIs from newer versions
This commit is contained in:
parent
b22df5fe67
commit
43ebe80704
|
@ -25,18 +25,18 @@ addons:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- rvm: 1.9.3
|
- rvm: 1.9.3
|
||||||
gemfile: gemfiles/2.6.gemfile
|
gemfile: gemfiles/2.7.gemfile
|
||||||
env: QMAKE=/usr/lib/x86_64-linux-gnu/qt4/bin/qmake
|
env: QMAKE=/usr/lib/x86_64-linux-gnu/qt4/bin/qmake
|
||||||
- rvm: 1.9.3
|
- rvm: 1.9.3
|
||||||
gemfile: gemfiles/2.5.gemfile
|
gemfile: gemfiles/2.11.gemfile
|
||||||
env: QMAKE=/usr/lib/x86_64-linux-gnu/qt4/bin/qmake
|
env: QMAKE=/usr/lib/x86_64-linux-gnu/qt4/bin/qmake
|
||||||
- rvm: 2.3.1
|
- rvm: 2.3.1
|
||||||
gemfile: gemfiles/master.gemfile
|
gemfile: gemfiles/master.gemfile
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- gemfile: gemfiles/master.gemfile
|
- gemfile: gemfiles/master.gemfile
|
||||||
gemfile:
|
gemfile:
|
||||||
- gemfiles/2.6.gemfile
|
- gemfiles/2.7.gemfile
|
||||||
- gemfiles/2.5.gemfile
|
- gemfiles/2.11.gemfile
|
||||||
before_install:
|
before_install:
|
||||||
- gem install bundler
|
- gem install bundler
|
||||||
install: bundle
|
install: bundle
|
||||||
|
|
12
Appraisals
12
Appraisals
|
@ -1,9 +1,13 @@
|
||||||
appraise "2.6" do
|
|
||||||
gem "capybara", "~> 2.6.0"
|
|
||||||
end
|
|
||||||
|
|
||||||
appraise "2.7" do
|
appraise "2.7" do
|
||||||
gem "capybara", "~> 2.7.0"
|
gem "capybara", "~> 2.7.0"
|
||||||
|
gem 'addressable', '< 2.5.0', :platforms=>[:ruby_19, :jruby_19] # 2.5 requires public_suffix which requires ruby 2.0
|
||||||
|
gem 'nokogiri', '< 1.7.0', :platforms=>[:ruby_19, :jruby_19] # 1.7.0 requires ruby 2.1+
|
||||||
|
end
|
||||||
|
|
||||||
|
appraise "2.11" do
|
||||||
|
gem "capybara", "~> 2.11.0"
|
||||||
|
gem 'addressable', '< 2.5.0', :platforms=>[:ruby_19, :jruby_19] # 2.5 requires public_suffix which requires ruby 2.0
|
||||||
|
gem 'nokogiri', '< 1.7.0', :platforms=>[:ruby_19, :jruby_19] # 1.7.0 requires ruby 2.1+
|
||||||
end
|
end
|
||||||
|
|
||||||
appraise "master" do
|
appraise "master" do
|
||||||
|
|
87
Gemfile.lock
87
Gemfile.lock
|
@ -2,70 +2,63 @@ PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
capybara-webkit (1.11.1)
|
capybara-webkit (1.11.1)
|
||||||
capybara (>= 2.3.0, < 2.8.0)
|
capybara (>= 2.3.0, < 2.13.0)
|
||||||
json
|
json
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
addressable (2.3.6)
|
addressable (2.5.0)
|
||||||
appraisal (0.4.0)
|
public_suffix (~> 2.0, >= 2.0.2)
|
||||||
|
appraisal (0.4.1)
|
||||||
bundler
|
bundler
|
||||||
rake
|
rake
|
||||||
capybara (2.5.0)
|
capybara (2.11.0)
|
||||||
|
addressable
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
nokogiri (>= 1.3.3)
|
nokogiri (>= 1.3.3)
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
rack-test (>= 0.5.4)
|
rack-test (>= 0.5.4)
|
||||||
xpath (~> 2.0)
|
xpath (~> 2.0)
|
||||||
childprocess (0.5.5)
|
diff-lcs (1.2.5)
|
||||||
ffi (~> 1.0, >= 1.0.11)
|
ffi (1.9.14-java)
|
||||||
diff-lcs (1.2.4)
|
|
||||||
ffi (1.9.8)
|
|
||||||
ffi (1.9.8-java)
|
|
||||||
ffi (1.9.8-x86-mingw32)
|
|
||||||
json (1.8.3)
|
json (1.8.3)
|
||||||
launchy (2.4.2)
|
json (1.8.3-java)
|
||||||
|
launchy (2.4.3)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
launchy (2.4.2-java)
|
launchy (2.4.3-java)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
spoon (~> 0.0.1)
|
spoon (~> 0.0.1)
|
||||||
mime-types (2.6.1)
|
mime-types (2.99.3)
|
||||||
mini_magick (3.2.1)
|
mini_magick (4.6.0)
|
||||||
subexec (~> 0.0.4)
|
mini_portile2 (2.1.0)
|
||||||
mini_portile2 (2.0.0)
|
nokogiri (1.7.0.1)
|
||||||
multi_json (1.11.0)
|
mini_portile2 (~> 2.1.0)
|
||||||
nokogiri (1.6.7.2)
|
nokogiri (1.7.0.1-java)
|
||||||
mini_portile2 (~> 2.0.0.rc2)
|
nokogiri (1.7.0.1-x86-mingw32)
|
||||||
rack (1.6.4)
|
mini_portile2 (~> 2.1.0)
|
||||||
rack-protection (1.3.2)
|
public_suffix (2.0.5)
|
||||||
|
rack (1.6.5)
|
||||||
|
rack-protection (1.5.3)
|
||||||
rack
|
rack
|
||||||
rack-test (0.6.3)
|
rack-test (0.6.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
rake (0.9.2)
|
rake (11.3.0)
|
||||||
rspec (2.14.1)
|
rspec (2.99.0)
|
||||||
rspec-core (~> 2.14.0)
|
rspec-core (~> 2.99.0)
|
||||||
rspec-expectations (~> 2.14.0)
|
rspec-expectations (~> 2.99.0)
|
||||||
rspec-mocks (~> 2.14.0)
|
rspec-mocks (~> 2.99.0)
|
||||||
rspec-core (2.14.4)
|
rspec-core (2.99.2)
|
||||||
rspec-expectations (2.14.1)
|
rspec-expectations (2.99.2)
|
||||||
diff-lcs (>= 1.1.3, < 2.0)
|
diff-lcs (>= 1.1.3, < 2.0)
|
||||||
rspec-mocks (2.14.3)
|
rspec-mocks (2.99.4)
|
||||||
rubyzip (1.1.7)
|
sinatra (1.4.7)
|
||||||
selenium-webdriver (2.45.0)
|
rack (~> 1.5)
|
||||||
childprocess (~> 0.5)
|
rack-protection (~> 1.4)
|
||||||
multi_json (~> 1.0)
|
tilt (>= 1.3, < 3)
|
||||||
rubyzip (~> 1.0)
|
spoon (0.0.6)
|
||||||
websocket (~> 1.0)
|
|
||||||
sinatra (1.3.5)
|
|
||||||
rack (~> 1.4)
|
|
||||||
rack-protection (~> 1.3)
|
|
||||||
tilt (~> 1.3, >= 1.3.3)
|
|
||||||
spoon (0.0.4)
|
|
||||||
ffi
|
ffi
|
||||||
subexec (0.0.4)
|
tilt (2.0.5)
|
||||||
tilt (1.3.3)
|
|
||||||
websocket (1.2.1)
|
|
||||||
xpath (2.0.0)
|
xpath (2.0.0)
|
||||||
nokogiri (~> 1.3)
|
nokogiri (~> 1.3)
|
||||||
|
|
||||||
|
@ -77,13 +70,13 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
appraisal (~> 0.4.0)
|
appraisal (~> 0.4.0)
|
||||||
capybara-webkit!
|
capybara-webkit!
|
||||||
|
json (< 2.0)
|
||||||
launchy
|
launchy
|
||||||
mime-types (< 3.0)
|
mime-types (< 3.0)
|
||||||
mini_magick
|
mini_magick
|
||||||
rake
|
rake (< 12.0.0)
|
||||||
rspec (~> 2.14.0)
|
rspec (~> 2.14)
|
||||||
selenium-webdriver
|
|
||||||
sinatra
|
sinatra
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.11.2
|
1.13.6
|
||||||
|
|
|
@ -21,16 +21,15 @@ Gem::Specification.new do |s|
|
||||||
|
|
||||||
s.requirements << "Qt >= 4.8"
|
s.requirements << "Qt >= 4.8"
|
||||||
|
|
||||||
s.add_runtime_dependency("capybara", ">= 2.3.0", "< 2.8.0")
|
s.add_runtime_dependency("capybara", ">= 2.3.0", "< 2.13.0")
|
||||||
s.add_runtime_dependency("json")
|
s.add_runtime_dependency("json")
|
||||||
|
|
||||||
s.add_development_dependency("rspec", "~> 2.14.0")
|
s.add_development_dependency("rspec", "~> 2.14")
|
||||||
# Sinatra is used by Capybara's TestApp
|
# Sinatra is used by Capybara's TestApp
|
||||||
s.add_development_dependency("sinatra")
|
s.add_development_dependency("sinatra")
|
||||||
s.add_development_dependency("mini_magick")
|
s.add_development_dependency("mini_magick")
|
||||||
s.add_development_dependency("rake")
|
s.add_development_dependency("rake", "< 12.0.0")
|
||||||
s.add_development_dependency("appraisal", "~> 0.4.0")
|
s.add_development_dependency("appraisal", "~> 0.4.0")
|
||||||
s.add_development_dependency("selenium-webdriver")
|
|
||||||
s.add_development_dependency("launchy")
|
s.add_development_dependency("launchy")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ source "https://rubygems.org"
|
||||||
|
|
||||||
gem "mime-types", "< 3.0", :platforms=>[:ruby_19, :jruby_19]
|
gem "mime-types", "< 3.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
gem "json", "< 2.0", :platforms=>[:ruby_19, :jruby_19]
|
gem "json", "< 2.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
|
gem "capybara", "~> 2.11.0"
|
||||||
gem "capybara", "~> 2.6.0"
|
gem "addressable", "< 2.5.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
|
gem "nokogiri", "< 1.7.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
|
|
||||||
gemspec :path=>"../"
|
gemspec :path=>"../"
|
|
@ -4,7 +4,8 @@ source "https://rubygems.org"
|
||||||
|
|
||||||
gem "mime-types", "< 3.0", :platforms=>[:ruby_19, :jruby_19]
|
gem "mime-types", "< 3.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
gem "json", "< 2.0", :platforms=>[:ruby_19, :jruby_19]
|
gem "json", "< 2.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
|
|
||||||
gem "capybara", "~> 2.7.0"
|
gem "capybara", "~> 2.7.0"
|
||||||
|
gem "addressable", "< 2.5.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
|
gem "nokogiri", "< 1.7.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
|
|
||||||
gemspec :path=>"../"
|
gemspec :path=>"../"
|
|
@ -4,7 +4,6 @@ source "https://rubygems.org"
|
||||||
|
|
||||||
gem "mime-types", "< 3.0", :platforms=>[:ruby_19, :jruby_19]
|
gem "mime-types", "< 3.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
gem "json", "< 2.0", :platforms=>[:ruby_19, :jruby_19]
|
gem "json", "< 2.0", :platforms=>[:ruby_19, :jruby_19]
|
||||||
|
|
||||||
gem "capybara", :github=>"jnicklas/capybara"
|
gem "capybara", :github=>"jnicklas/capybara"
|
||||||
|
|
||||||
gemspec :path=>"../"
|
gemspec :path=>"../"
|
|
@ -223,13 +223,13 @@ https://github.com/thoughtbot/capybara-webkit/wiki/Reporting-Crashes
|
||||||
MESSAGE
|
MESSAGE
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate_script(script)
|
def evaluate_script(script, *args)
|
||||||
json = command('Evaluate', script)
|
json = command('Evaluate', script, args.to_json)
|
||||||
JSON.parse("[#{json}]").first
|
JSON.parse("[#{json}]").first
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_script(script)
|
def execute_script(script, *args)
|
||||||
command('Execute', script)
|
command('Execute', script, args.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render(path, width, height)
|
def render(path, width, height)
|
||||||
|
|
|
@ -76,13 +76,18 @@ module Capybara::Webkit
|
||||||
@browser.title
|
@browser.title
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_script(script)
|
def execute_script(script, *args)
|
||||||
value = @browser.execute_script script
|
value = @browser.execute_script(script, *encode_args(args))
|
||||||
value.empty? ? nil : value
|
|
||||||
|
if value.empty?
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate_script(script)
|
def evaluate_script(script, *args)
|
||||||
@browser.evaluate_script script
|
@browser.evaluate_script(script, *encode_args(args))
|
||||||
end
|
end
|
||||||
|
|
||||||
def console_messages
|
def console_messages
|
||||||
|
@ -144,6 +149,21 @@ module Capybara::Webkit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def switch_to_frame(frame)
|
||||||
|
case frame
|
||||||
|
when :top
|
||||||
|
begin
|
||||||
|
loop { @browser.frame_focus }
|
||||||
|
rescue Capybara::Webkit::InvalidResponseError => e
|
||||||
|
raise unless e.message =~ /Already at parent frame/
|
||||||
|
end
|
||||||
|
when :parent
|
||||||
|
@browser.frame_focus
|
||||||
|
else
|
||||||
|
@browser.frame_focus(frame)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def within_window(selector)
|
def within_window(selector)
|
||||||
current_window = current_window_handle
|
current_window = current_window_handle
|
||||||
switch_to_window(selector)
|
switch_to_window(selector)
|
||||||
|
@ -391,5 +411,15 @@ module Capybara::Webkit
|
||||||
"This option is global and can be configured once" \
|
"This option is global and can be configured once" \
|
||||||
" (not in a `before` or `setup` block)."
|
" (not in a `before` or `setup` block)."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def encode_args(args)
|
||||||
|
args.map do |arg|
|
||||||
|
if arg.is_a?(Capybara::Webkit::Node)
|
||||||
|
{ ELEMENT: arg.native }.to_json
|
||||||
|
else
|
||||||
|
arg.to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -114,11 +114,13 @@ module Capybara::Webkit
|
||||||
end
|
end
|
||||||
|
|
||||||
def disabled?
|
def disabled?
|
||||||
if %w(option optgroup).include? tag_name
|
xpath = "parent::optgroup[@disabled] | " \
|
||||||
self['disabled'] || find_xpath("parent::*")[0].disabled?
|
"ancestor::select[@disabled] | " \
|
||||||
else
|
"parent::fieldset[@disabled] | " \
|
||||||
self['disabled']
|
"ancestor::*[not(self::legend) or " \
|
||||||
end
|
"preceding-sibling::legend][parent::fieldset[@disabled]]"
|
||||||
|
|
||||||
|
self["disabled"] || !find_xpath(xpath).empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def path
|
def path
|
||||||
|
|
|
@ -62,12 +62,25 @@ describe Capybara::Webkit::Driver do
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
document.write("<p id='farewell'>goodbye</p>");
|
document.write("<p id='farewell'>goodbye</p><iframe id='g' src='/iframe2'></iframe>");
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
HTML
|
HTML
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get '/iframe2' do
|
||||||
|
<<-HTML
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Frame 2</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>In frame 2</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -95,6 +108,37 @@ describe Capybara::Webkit::Driver do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "switches to frame by element" do
|
||||||
|
frame = driver.find_xpath('//iframe').first
|
||||||
|
element = double(Capybara::Node::Base, base: frame)
|
||||||
|
driver.switch_to_frame(element)
|
||||||
|
driver.find_xpath("//*[contains(., 'goodbye')]").should_not be_empty
|
||||||
|
driver.switch_to_frame(:parent)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can switch back to the parent frame" do
|
||||||
|
frame = driver.find_xpath('//iframe').first
|
||||||
|
element = double(Capybara::Node::Base, base: frame)
|
||||||
|
driver.switch_to_frame(element)
|
||||||
|
driver.switch_to_frame(:parent)
|
||||||
|
driver.find_xpath("//*[contains(., 'greeting')]").should_not be_empty
|
||||||
|
driver.find_xpath("//*[contains(., 'goodbye')]").should be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can switch to the top frame" do
|
||||||
|
frame = driver.find_xpath('//iframe').first
|
||||||
|
element = double(Capybara::Node::Base, base: frame)
|
||||||
|
driver.switch_to_frame(element)
|
||||||
|
frame2 = driver.find_xpath('//iframe[@id="g"]').first
|
||||||
|
element2 = double(Capybara::Node::Base, base: frame2)
|
||||||
|
driver.switch_to_frame(element2)
|
||||||
|
driver.find_xpath("//div[contains(., 'In frame 2')]").should_not be_empty
|
||||||
|
driver.switch_to_frame(:top)
|
||||||
|
driver.find_xpath("//*[contains(., 'greeting')]").should_not be_empty
|
||||||
|
driver.find_xpath("//*[contains(., 'goodbye')]").should be_empty
|
||||||
|
driver.find_xpath("//div[contains(., 'In frame 2')]").should be_empty
|
||||||
|
end
|
||||||
|
|
||||||
it "raises error for missing frame by index" do
|
it "raises error for missing frame by index" do
|
||||||
expect { driver.within_frame(1) { } }.
|
expect { driver.within_frame(1) { } }.
|
||||||
to raise_error(Capybara::Webkit::InvalidResponseError)
|
to raise_error(Capybara::Webkit::InvalidResponseError)
|
||||||
|
@ -528,6 +572,38 @@ describe Capybara::Webkit::Driver do
|
||||||
to raise_error(Capybara::Webkit::InvalidResponseError)
|
to raise_error(Capybara::Webkit::InvalidResponseError)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "passes arguments to executed Javascript" do
|
||||||
|
driver.execute_script(%<document.getElementById('greeting').innerHTML = arguments[0]>, "My argument")
|
||||||
|
driver.find_xpath("//p[contains(., 'My argument')]").should_not be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes multiple arguments to executed Javascript" do
|
||||||
|
driver.execute_script(
|
||||||
|
%<document.getElementById('greeting').innerHTML = arguments[0] + arguments[1] + arguments[2].color>,
|
||||||
|
"random", 4, {color: 'red'})
|
||||||
|
driver.find_xpath("//p[contains(., 'random4red')]").should_not be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes page elements to executed Javascript" do
|
||||||
|
greeting = driver.find_xpath("//p[@id='greeting']").first
|
||||||
|
driver.execute_script(%<arguments[0].innerHTML = arguments[1]>, greeting, "new content")
|
||||||
|
driver.find_xpath("//p[@id='greeting'][contains(., 'new content')]").should_not be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes arguments to evaaluated Javascript" do
|
||||||
|
driver.evaluate_script(%<arguments[0]>, 3).should eq 3
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes multiple arguments to evaluated Javascript" do
|
||||||
|
driver.evaluate_script(%<arguments[0] + arguments[1] + arguments[2].num>, 3, 4, {num: 5}).should eq 12
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes page elements to evaluated Javascript" do
|
||||||
|
greeting = driver.find_xpath("//p[@id='greeting']").first
|
||||||
|
driver.evaluate_script(%<arguments[1].innerHTML = arguments[0]; arguments[2]>, "newer content", greeting, 7).should eq 7
|
||||||
|
driver.find_xpath("//p[@id='greeting'][contains(., 'newer content')]").should_not be_empty
|
||||||
|
end
|
||||||
|
|
||||||
it "doesn't raise an error for Javascript that doesn't return anything" do
|
it "doesn't raise an error for Javascript that doesn't return anything" do
|
||||||
lambda { driver.execute_script(%<(function () { "returns nothing" })()>) }.
|
lambda { driver.execute_script(%<(function () { "returns nothing" })()>) }.
|
||||||
should_not raise_error
|
should_not raise_error
|
||||||
|
|
|
@ -8,7 +8,26 @@ Evaluate::Evaluate(WebPageManager *manager, QStringList &arguments, QObject *par
|
||||||
}
|
}
|
||||||
|
|
||||||
void Evaluate::start() {
|
void Evaluate::start() {
|
||||||
QVariant result = page()->currentFrame()->evaluateJavaScript(arguments()[0]);
|
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; i++) {"
|
||||||
|
" arguments[i] = JSON.parse(arguments[i]);"
|
||||||
|
" if (arguments[i]['ELEMENT']) {"
|
||||||
|
" arguments[i] = Capybara.getNode(arguments[i]['ELEMENT']);"
|
||||||
|
" };"
|
||||||
|
" };"
|
||||||
|
" return eval(\"%1\");"
|
||||||
|
" }).apply(null, %2)").arg(script.replace("\"","\\\"").remove("\n"), jsonArgs);
|
||||||
|
QObject invocation_stub;
|
||||||
|
invocation_stub.setProperty("allowUnattached", false);
|
||||||
|
page()->currentFrame()->addToJavaScriptWindowObject("CapybaraInvocation", &invocation_stub);
|
||||||
|
QVariant result = page()->currentFrame()->evaluateJavaScript(eval_script);
|
||||||
JsonSerializer serializer;
|
JsonSerializer serializer;
|
||||||
finish(true, serializer.serialize(result));
|
finish(true, serializer.serialize(result));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,24 @@ Execute::Execute(WebPageManager *manager, QStringList &arguments, QObject *paren
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::start() {
|
void Execute::start() {
|
||||||
QString script = arguments()[0] + QString("; 'success'");
|
QString jsonArgs;
|
||||||
|
if (arguments().length()>1){
|
||||||
|
jsonArgs = arguments()[1];
|
||||||
|
} else {
|
||||||
|
jsonArgs ="[]";
|
||||||
|
}
|
||||||
|
QString script = QString("(function(){"
|
||||||
|
" for(var i=0; i<arguments.length; i++) {"
|
||||||
|
" arguments[i] = JSON.parse(arguments[i]);"
|
||||||
|
" if (arguments[i]['ELEMENT']) {"
|
||||||
|
" arguments[i] = Capybara.getNode(arguments[i]['ELEMENT']);"
|
||||||
|
" };"
|
||||||
|
" };"
|
||||||
|
" %1 }).apply(null, %2); 'success'").arg(arguments()[0], jsonArgs);
|
||||||
|
|
||||||
|
QObject invocation_stub;
|
||||||
|
invocation_stub.setProperty("allowUnattached", false);
|
||||||
|
page()->currentFrame()->addToJavaScriptWindowObject("CapybaraInvocation", &invocation_stub);
|
||||||
QVariant result = page()->currentFrame()->evaluateJavaScript(script);
|
QVariant result = page()->currentFrame()->evaluateJavaScript(script);
|
||||||
if (result.isValid()) {
|
if (result.isValid()) {
|
||||||
finish(true);
|
finish(true);
|
||||||
|
|
|
@ -8,7 +8,6 @@ FrameFocus::FrameFocus(WebPageManager *manager, QStringList &arguments, QObject
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameFocus::start() {
|
void FrameFocus::start() {
|
||||||
findFrames();
|
|
||||||
switch(arguments().length()) {
|
switch(arguments().length()) {
|
||||||
case 1:
|
case 1:
|
||||||
focusId(arguments()[0]);
|
focusId(arguments()[0]);
|
||||||
|
@ -26,8 +25,10 @@ void FrameFocus::findFrames() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameFocus::focusIndex(int index) {
|
void FrameFocus::focusIndex(int index) {
|
||||||
|
findFrames();
|
||||||
if (isFrameAtIndex(index)) {
|
if (isFrameAtIndex(index)) {
|
||||||
frames[index]->setFocus();
|
frames[index]->setFocus();
|
||||||
|
page()->setCurrentFrameParent(frames[index]->parentFrame());
|
||||||
success();
|
success();
|
||||||
} else {
|
} else {
|
||||||
frameNotFound();
|
frameNotFound();
|
||||||
|
@ -39,9 +40,11 @@ bool FrameFocus::isFrameAtIndex(int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameFocus::focusId(QString name) {
|
void FrameFocus::focusId(QString name) {
|
||||||
|
findFrames();
|
||||||
for (int i = 0; i < frames.length(); i++) {
|
for (int i = 0; i < frames.length(); i++) {
|
||||||
if (frames[i]->frameName().compare(name) == 0) {
|
if (frames[i]->frameName().compare(name) == 0) {
|
||||||
frames[i]->setFocus();
|
frames[i]->setFocus();
|
||||||
|
page()->setCurrentFrameParent(frames[i]->parentFrame());
|
||||||
success();
|
success();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -51,10 +54,13 @@ void FrameFocus::focusId(QString name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameFocus::focusParent() {
|
void FrameFocus::focusParent() {
|
||||||
if (page()->currentFrame()->parentFrame() == 0) {
|
// if (page()->currentFrame()->parentFrame() == 0) {
|
||||||
|
if (page()->currentFrameParent() == 0) {
|
||||||
finish(false, new ErrorMessage("Already at parent frame."));
|
finish(false, new ErrorMessage("Already at parent frame."));
|
||||||
} else {
|
} else {
|
||||||
page()->currentFrame()->parentFrame()->setFocus();
|
// page()->currentFrame()->parentFrame()->setFocus();
|
||||||
|
page()->currentFrameParent()->setFocus();
|
||||||
|
page()->setCurrentFrameParent(page()->currentFrameParent()->parentFrame());
|
||||||
success();
|
success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,14 @@ InvocationResult JavascriptInvocation::invoke(QWebFrame *frame) {
|
||||||
QVariant result = frame->evaluateJavaScript("Capybara.invoke()");
|
QVariant result = frame->evaluateJavaScript("Capybara.invoke()");
|
||||||
if (getError().isValid())
|
if (getError().isValid())
|
||||||
return InvocationResult(getError(), true);
|
return InvocationResult(getError(), true);
|
||||||
else
|
else {
|
||||||
|
if (functionName() == "leftClick") {
|
||||||
|
// Don't trigger the left click from JS incase the frame closes
|
||||||
|
QVariantMap qm = result.toMap();
|
||||||
|
leftClick(qm["absoluteX"].toInt(), qm["absoluteY"].toInt());
|
||||||
|
}
|
||||||
return InvocationResult(result);
|
return InvocationResult(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavascriptInvocation::leftClick(int x, int y) {
|
void JavascriptInvocation::leftClick(int x, int y) {
|
||||||
|
|
|
@ -11,6 +11,9 @@ void Node::start() {
|
||||||
QString functionName = functionArguments.takeFirst();
|
QString functionName = functionArguments.takeFirst();
|
||||||
QString allowUnattached = functionArguments.takeFirst();
|
QString allowUnattached = functionArguments.takeFirst();
|
||||||
InvocationResult result = page()->invokeCapybaraFunction(functionName, allowUnattached == "true", functionArguments);
|
InvocationResult result = page()->invokeCapybaraFunction(functionName, allowUnattached == "true", functionArguments);
|
||||||
|
if (functionName == "focus") {
|
||||||
|
page()->setCurrentFrameParent(page()->currentFrame()->parentFrame());
|
||||||
|
}
|
||||||
finish(&result);
|
finish(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ WebPage::WebPage(WebPageManager *manager, QObject *parent) : QWebPage(parent) {
|
||||||
m_uuid = QUuid::createUuid().toString();
|
m_uuid = QUuid::createUuid().toString();
|
||||||
m_confirmAction = true;
|
m_confirmAction = true;
|
||||||
m_promptAction = false;
|
m_promptAction = false;
|
||||||
|
m_currentFrameParent = 0;
|
||||||
|
|
||||||
setForwardUnsupportedContent(true);
|
setForwardUnsupportedContent(true);
|
||||||
loadJavascript();
|
loadJavascript();
|
||||||
|
@ -255,6 +256,7 @@ bool WebPage::javaScriptPrompt(QWebFrame *frame, const QString &message, const Q
|
||||||
|
|
||||||
void WebPage::loadStarted() {
|
void WebPage::loadStarted() {
|
||||||
m_loading = true;
|
m_loading = true;
|
||||||
|
m_currentFrameParent = currentFrame()->parentFrame();
|
||||||
m_errorPageMessage = QString();
|
m_errorPageMessage = QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,3 +487,13 @@ void WebPage::addModalMessage(bool expectedType, const QString &message, const Q
|
||||||
m_modalMessages << QString();
|
m_modalMessages << QString();
|
||||||
emit modalReady();
|
emit modalReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWebFrame* WebPage::currentFrameParent() {
|
||||||
|
return m_currentFrameParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebPage::setCurrentFrameParent(QWebFrame* frame) {
|
||||||
|
m_currentFrameParent = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ class WebPage : public QWebPage {
|
||||||
void resize(int, int);
|
void resize(int, int);
|
||||||
int modalCount();
|
int modalCount();
|
||||||
QString modalMessage();
|
QString modalMessage();
|
||||||
|
void setCurrentFrameParent(QWebFrame* frame);
|
||||||
|
QWebFrame* currentFrameParent();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool shouldInterruptJavaScript();
|
bool shouldInterruptJavaScript();
|
||||||
|
@ -105,6 +107,7 @@ class WebPage : public QWebPage {
|
||||||
QList<QVariantMap> m_modalResponses;
|
QList<QVariantMap> m_modalResponses;
|
||||||
QStringList m_modalMessages;
|
QStringList m_modalMessages;
|
||||||
void addModalMessage(bool, const QString &, const QRegExp &);
|
void addModalMessage(bool, const QString &, const QRegExp &);
|
||||||
|
QWebFrame* m_currentFrameParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_WEBPAGE_H
|
#endif //_WEBPAGE_H
|
||||||
|
|
|
@ -5,7 +5,11 @@ Capybara = {
|
||||||
|
|
||||||
invoke: function () {
|
invoke: function () {
|
||||||
try {
|
try {
|
||||||
return this[CapybaraInvocation.functionName].apply(this, CapybaraInvocation.arguments);
|
if (CapybaraInvocation.functionName == "leftClick") {
|
||||||
|
return this["verifiedClickPosition"].apply(this, CapybaraInvocation.arguments);
|
||||||
|
} else {
|
||||||
|
return this[CapybaraInvocation.functionName].apply(this, CapybaraInvocation.arguments);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
CapybaraInvocation.error = e;
|
CapybaraInvocation.error = e;
|
||||||
}
|
}
|
||||||
|
@ -204,12 +208,17 @@ Capybara = {
|
||||||
throw new Capybara.UnpositionedElement(this.pathForNode(node), visible);
|
throw new Capybara.UnpositionedElement(this.pathForNode(node), visible);
|
||||||
},
|
},
|
||||||
|
|
||||||
click: function (index, action) {
|
verifiedClickPosition: function (index) {
|
||||||
var node = this.getNode(index);
|
var node = this.getNode(index);
|
||||||
node.scrollIntoViewIfNeeded();
|
node.scrollIntoViewIfNeeded();
|
||||||
var pos = this.clickPosition(node);
|
var pos = this.clickPosition(node);
|
||||||
CapybaraInvocation.hover(pos.relativeX, pos.relativeY);
|
CapybaraInvocation.hover(pos.relativeX, pos.relativeY);
|
||||||
this.expectNodeAtPosition(node, pos);
|
this.expectNodeAtPosition(node, pos);
|
||||||
|
return pos;
|
||||||
|
},
|
||||||
|
|
||||||
|
click: function (index, action) {
|
||||||
|
var pos = this.verifiedClickPosition(index);
|
||||||
action(pos.absoluteX, pos.absoluteY);
|
action(pos.absoluteX, pos.absoluteY);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue