Code cleanup driven by rubocop

This commit is contained in:
Thomas Walpole 2018-05-22 13:22:03 -07:00
parent e016661f60
commit 53beed0623
26 changed files with 438 additions and 347 deletions

102
.rubocop.yml Normal file
View File

@ -0,0 +1,102 @@
AllCops:
DisabledByDefault: false
TargetRubyVersion: 2.3.0
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyleAlignWith, AutoCorrect, Severity.
# SupportedStylesAlignWith: keyword, variable, start_of_line
Layout/EndAlignment:
EnforcedStyleAlignWith: variable
# Offense count: 2
Lint/HandleExceptions:
Exclude:
- 'lib/capybara/poltergeist/client.rb'
- 'lib/capybara/poltergeist/driver.rb'
# Offense count: 8
Metrics/AbcSize:
Max: 36
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/BlockLength:
Max: 1217
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 383
Metrics/CyclomaticComplexity:
Max: 12
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 28
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 1219
Metrics/PerceivedComplexity:
Max: 12
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Metrics/LineLength:
Max: 172
Naming/AccessorMethodName:
Exclude:
- 'lib/capybara/poltergeist/browser.rb'
- 'spec/**/*'
Naming/MemoizedInstanceVariableName:
Exclude:
- 'lib/capybara/poltergeist/inspector.rb'
Naming/UncommunicativeMethodParamName:
AllowedNames: io, id, to, by, on, in, at, x, y, ip
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: prefer_alias, prefer_alias_method
Style/Alias:
Exclude:
- 'lib/capybara/poltergeist/driver.rb'
- 'lib/capybara/poltergeist/node.rb'
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle.
# SupportedStyles: nested, compact
Style/ClassAndModuleChildren:
Enabled: false
Style/Documentation:
Enabled: false
Style/DoubleNegation:
Exclude:
- 'lib/capybara/poltergeist/browser.rb'
- 'lib/capybara/poltergeist/node.rb'
# Cop supports --auto-correct.
# Configuration parameters: Strict.
Style/NumericLiterals:
MinDigits: 6
# Cop supports --auto-correct.
Style/RescueModifier:
Exclude:
- 'lib/capybara/poltergeist/driver.rb'
- 'spec/**/*'
# Cop supports --auto-correct.
# Configuration parameters: AllowAsExpressionSeparator.
Style/Semicolon:
AllowAsExpressionSeparator: true
# Cop supports --auto-correct.
# Configuration parameters: .
# SupportedStyles: use_perl_names, use_english_names
Style/SpecialGlobalVars:
Enabled: false

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
source 'https://rubygems.org'
gemspec
@ -5,7 +7,7 @@ gemspec
gem 'puma'
platforms :rbx do
gem 'rubysl'
gem 'racc'
gem 'json'
gem 'racc'
gem 'rubysl'
end

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
guard 'coffeescript', input: 'lib/capybara/poltergeist/client',
output: 'lib/capybara/poltergeist/client/compiled',
bare: true

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'bundler/setup'
require 'rspec/core/rake_task'
@ -5,7 +7,7 @@ require 'capybara/poltergeist/version'
require 'coffee-script'
RSpec::Core::RakeTask.new('test')
task default: [:compile, :test]
task default: %i[compile test]
task(:autocompile) { system 'guard' }

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'bundler/setup'
require File.expand_path('spec/support/test_app')
run TestApp

View File

@ -1,10 +1,5 @@
# frozen_string_literal: true
if RUBY_VERSION < "1.9.2"
raise "This version of Capybara/Poltergeist does not support Ruby versions " \
"less than 1.9.2."
end
require 'capybara'
module Capybara

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require "capybara/poltergeist/errors"
require "capybara/poltergeist/command"
require 'capybara/poltergeist/errors'
require 'capybara/poltergeist/command'
require 'json'
require 'time'
@ -15,8 +15,8 @@ module Capybara::Poltergeist
'Poltergeist.NoSuchWindowError' => NoSuchWindowError,
'Poltergeist.ScriptTimeoutError' => ScriptTimeoutError,
'Poltergeist.UnsupportedFeature' => UnsupportedFeature,
'Poltergeist.KeyError' => KeyError,
}
'Poltergeist.KeyError' => KeyError
}.freeze
attr_reader :server, :client, :logger
@ -144,7 +144,7 @@ module Capybara::Poltergeist
command 'execute', script, *args
end
def within_frame(handle, &block)
def within_frame(handle)
if handle.is_a?(Capybara::Node::Base)
command 'push_frame', [handle.native.page_id, handle.native.id]
else
@ -192,10 +192,10 @@ module Capybara::Poltergeist
handle = command 'window_handle', locator
raise NoSuchWindowError unless handle
return handle
handle
end
def within_window(locator, &block)
def within_window(locator)
original = window_handle
handle = find_window_handle(locator)
switch_to_window(handle)
@ -204,15 +204,15 @@ module Capybara::Poltergeist
switch_to_window(original)
end
def click(page_id, id, keys=[], offset={})
def click(page_id, id, keys = [], offset = {})
command 'click', page_id, id, keys, offset
end
def right_click(page_id, id, keys=[], offset={})
def right_click(page_id, id, keys = [], offset = {})
command 'right_click', page_id, id, keys, offset
end
def double_click(page_id, id, keys=[], offset={})
def double_click(page_id, id, keys = [], offset = {})
command 'double_click', page_id, id, keys, offset
end
@ -313,7 +313,7 @@ module Capybara::Poltergeist
command 'add_headers', headers
end
def add_header(header, options={})
def add_header(header, options = {})
command 'add_header', header, options
end
@ -326,10 +326,7 @@ module Capybara::Poltergeist
end
def set_cookie(cookie)
if cookie[:expires]
cookie[:expires] = cookie[:expires].to_i * 1000
end
cookie[:expires] = cookie[:expires].to_i * 1000 if cookie[:expires]
command 'set_cookie', cookie
end
@ -389,11 +386,11 @@ module Capybara::Poltergeist
response = server.send(cmd)
log response
json = JSON.load(response)
json = JSON.parse(response)
if json['error']
klass = ERROR_MAPPINGS[json['error']['name']] || BrowserError
raise klass.new(json['error'])
raise klass, json['error']
else
json['response']
end
@ -443,14 +440,13 @@ module Capybara::Poltergeist
private
def log(message)
logger.puts message if logger
logger&.puts message
end
def check_render_options!(options)
if !!options[:full] && options.has_key?(:selector)
warn "Ignoring :selector in #render since :full => true was given at #{caller.first}"
options.delete(:selector)
end
return unless options[:full] && options.key?(:selector)
warn "Ignoring :selector in #render since :full => true was given at #{caller(1..1).first}"
options.delete(:selector)
end
KEY_ALIASES = {
@ -463,7 +459,7 @@ module Capybara::Poltergeist
divide: 'numpad/',
subtract: 'numpad-',
decimal: 'numpad.'
}
}.freeze
def normalize_keys(keys)
keys.map do |key_desc|
@ -474,9 +470,9 @@ module Capybara::Poltergeist
# [:Ctrl, :Left] => { modifier: "ctrl", key: 'Left' }
# [:Ctrl, :Shift, :Left] => { modifier: "ctrl,shift", key: 'Left' }
# [:Ctrl, :Left, :Left] => { modifier: "ctrl", key: [:Left, :Left] }
_keys = key_desc.chunk {|k| k.is_a?(Symbol) && %w(shift ctrl control alt meta command).include?(k.to_s.downcase) }
modifiers = if _keys.peek[0]
_keys.next[1].map do |k|
chunked_keys = key_desc.chunk { |k| k.is_a?(Symbol) && %w[shift ctrl control alt meta command].include?(k.to_s.downcase) }
modifiers = if chunked_keys.peek[0]
chunked_keys.next[1].map do |k|
k = k.to_s.downcase
k = 'ctrl' if k == 'control'
k = 'meta' if k == 'command'
@ -485,15 +481,15 @@ module Capybara::Poltergeist
else
''
end
letters = normalize_keys(_keys.next[1].map {|k| k.is_a?(String) ? k.upcase : k })
letters = normalize_keys(chunked_keys.next[1].map { |k| k.is_a?(String) ? k.upcase : k })
{ modifier: modifiers, keys: letters }
when Symbol
# Return a known sequence for PhantomJS
key = KEY_ALIASES.fetch(key_desc, key_desc)
if match = key.to_s.match(/numpad(.)/)
if (match = key.to_s.match(/numpad(.)/))
res = { keys: match[1], modifier: 'keypad' }
elsif key !~ /^[A-Z]/
key = key.to_s.split('_').map{ |e| e.capitalize }.join
key = key.to_s.split('_').map(&:capitalize).join
end
res || { key: key }
when String

View File

@ -1,13 +1,12 @@
# frozen_string_literal: true
require "timeout"
require "capybara/poltergeist/utility"
require 'capybara/poltergeist/utility'
require 'cliver'
module Capybara::Poltergeist
class Client
PHANTOMJS_SCRIPT = File.expand_path('../client/compiled/main.js', __FILE__)
PHANTOMJS_VERSION = ['>= 1.8.1', '< 3.0']
PHANTOMJS_SCRIPT = File.expand_path('client/compiled/main.js', __dir__)
PHANTOMJS_VERSION = ['>= 1.8.1', '< 3.0'].freeze
PHANTOMJS_NAME = 'phantomjs'
KILL_TIMEOUT = 2 # seconds
@ -32,11 +31,10 @@ module Capybara::Poltergeist
start = Time.now
while Process.wait(pid, Process::WNOHANG).nil?
sleep 0.05
if (Time.now - start) > KILL_TIMEOUT
Process.kill('KILL', pid)
Process.wait(pid)
break
end
next unless (Time.now - start) > KILL_TIMEOUT
Process.kill('KILL', pid)
Process.wait(pid)
break
end
end
rescue Errno::ESRCH, Errno::ECHILD
@ -49,8 +47,8 @@ module Capybara::Poltergeist
def initialize(server, options = {})
@server = server
@path = Cliver::detect((options[:path] || PHANTOMJS_NAME), *['>=2.1.0', '< 3.0'])
@path ||= Cliver::detect!((options[:path] || PHANTOMJS_NAME), *PHANTOMJS_VERSION).tap do
@path = Cliver.detect((options[:path] || PHANTOMJS_NAME), '>=2.1.0', '< 3.0')
@path ||= Cliver.detect!((options[:path] || PHANTOMJS_NAME), *PHANTOMJS_VERSION).tap do
warn "You're running an old version of PhantomJS, update to >= 2.1.1 for a better experience."
end
@ -61,13 +59,13 @@ module Capybara::Poltergeist
def start
@read_io, @write_io = IO.pipe
@out_thread = Thread.new {
while !@read_io.eof? && data = @read_io.readpartial(1024)
@out_thread = Thread.new do
while !@read_io.eof? && (data = @read_io.readpartial(1024))
@phantomjs_logger.write(data)
end
}
end
process_options = {in: File::NULL}
process_options = { in: File::NULL }
process_options[:pgroup] = true unless Capybara::Poltergeist.windows?
process_options[:out] = @write_io if Capybara::Poltergeist.mri?
@ -78,12 +76,11 @@ module Capybara::Poltergeist
end
def stop
if pid
kill_phantomjs
@out_thread.kill
close_io
ObjectSpace.undefine_finalizer(self)
end
return unless pid
kill_phantomjs
@out_thread.kill
close_io
ObjectSpace.undefine_finalizer(self)
end
def restart

View File

@ -15,7 +15,7 @@ module Capybara::Poltergeist
end
def message
JSON.dump({ 'id' => @id, 'name' => @name, 'args' => @args })
JSON.dump('id' => @id, 'name' => @name, 'args' => @args)
end
end
end

View File

@ -45,11 +45,10 @@ module Capybara::Poltergeist
def client
@client ||= Client.start(server,
:path => options[:phantomjs],
:window_size => options[:window_size],
:phantomjs_options => phantomjs_options,
:phantomjs_logger => phantomjs_logger
)
path: options[:phantomjs],
window_size: options[:window_size],
phantomjs_options: phantomjs_options,
phantomjs_logger: phantomjs_logger)
end
def phantomjs_options
@ -58,9 +57,9 @@ module Capybara::Poltergeist
# PhantomJS defaults to only using SSLv3, which since POODLE (Oct 2014)
# many sites have dropped from their supported protocols (eg PayPal,
# Braintree).
list += ["--ignore-ssl-errors=yes"] unless list.grep(/ignore-ssl-errors/).any?
list += ["--ssl-protocol=TLSv1"] unless list.grep(/ssl-protocol/).any?
list += ["--remote-debugger-port=#{inspector.port}", "--remote-debugger-autorun=yes"] if inspector
list += ['--ignore-ssl-errors=yes'] unless list.grep(/ignore-ssl-errors/).any?
list += ['--ssl-protocol=TLSv1'] unless list.grep(/ssl-protocol/).any?
list += ["--remote-debugger-port=#{inspector.port}", '--remote-debugger-autorun=yes'] if inspector
list
end
@ -154,17 +153,17 @@ module Capybara::Poltergeist
end
def evaluate_script(script, *args)
result = browser.evaluate(script, *args.map { |arg| arg.is_a?(Capybara::Poltergeist::Node) ? arg.native : arg})
result = browser.evaluate(script, *native_args(args))
unwrap_script_result(result)
end
def evaluate_async_script(script, *args)
result = browser.evaluate_async(script, session_wait_time, *args.map { |arg| arg.is_a?(Capybara::Poltergeist::Node) ? arg.native : arg})
result = browser.evaluate_async(script, session_wait_time, *native_args(args))
unwrap_script_result(result)
end
def execute_script(script, *args)
browser.execute(script, *args.map { |arg| arg.is_a?(Capybara::Poltergeist::Node) ? arg.native : arg})
browser.execute(script, *native_args(args))
nil
end
@ -261,7 +260,7 @@ module Capybara::Poltergeist
browser.clear_network_traffic
end
def set_proxy(ip, port, type = "http", user = nil, password = nil)
def set_proxy(ip, port, type = 'http', user = nil, password = nil)
browser.set_proxy(ip, port, type, user, password)
end
@ -296,7 +295,7 @@ module Capybara::Poltergeist
if @started
URI.parse(browser.current_url).host
else
URI.parse(default_cookie_host).host || "127.0.0.1"
URI.parse(default_cookie_host).host || '127.0.0.1'
end
end
@ -338,8 +337,8 @@ module Capybara::Poltergeist
inspector.open(scheme)
pause
else
raise Error, "To use the remote debugging, you have to launch the driver " \
"with `:inspector => true` configuration option"
raise Error, 'To use the remote debugging, you have to launch the driver ' \
'with `:inspector => true` configuration option'
end
end
@ -358,12 +357,13 @@ module Capybara::Poltergeist
old_trap = trap('SIGCONT') { signal = true; STDERR.puts "\nSignal SIGCONT received" }
keyboard = IO.select([read], nil, nil, 1) until keyboard || signal # wait for data on STDIN or signal SIGCONT received
begin
input = read.read_nonblock(80) # clear out the read buffer
puts unless input && input =~ /\n\z/
rescue EOFError, IO::WaitReadable # Ignore problems reading from STDIN.
end unless signal
unless signal
begin
input = read.read_nonblock(80) # clear out the read buffer
puts unless input&.end_with?("\n")
rescue EOFError, IO::WaitReadable # Ignore problems reading from STDIN.
end
end
ensure
trap('SIGCONT', old_trap) # Restore the previous signal handler, if there was one.
STDERR.puts 'Continuing'
@ -416,8 +416,12 @@ module Capybara::Poltergeist
private
def native_args(args)
args.map { |arg| arg.is_a?(Capybara::Poltergeist::Node) ? arg.native : arg }
end
def screen_size
options[:screen_size] || [1366,768]
options[:screen_size] || [1366, 768]
end
def find_modal(options)

View File

@ -36,9 +36,9 @@ module Capybara
end
def message
"There was an error inside the PhantomJS portion of Poltergeist. " \
"If this is the error returned, and not the cause of a more detailed error response, " \
"this is probably a bug, so please report it. " \
'There was an error inside the PhantomJS portion of Poltergeist. ' \
'If this is the error returned, and not the cause of a more detailed error response, ' \
'this is probably a bug, so please report it. ' \
"\n\n#{name}: #{error_parameters}"
end
end
@ -49,10 +49,10 @@ module Capybara
end
def message
"One or more errors were raised in the Javascript code on the page. " \
'One or more errors were raised in the Javascript code on the page. ' \
"If you don't care about these errors, you can ignore them by " \
"setting js_errors: false in your Poltergeist configuration (see " \
"documentation for details)." \
'setting js_errors: false in your Poltergeist configuration (see ' \
'documentation for details).' \
"\n\n#{javascript_errors.map(&:to_s).join("\n")}"
end
end
@ -93,7 +93,7 @@ module Capybara
end
def message
"The browser raised a syntax error while trying to evaluate " \
'The browser raised a syntax error while trying to evaluate ' \
"#{method} selector #{selector.inspect}"
end
end
@ -109,11 +109,11 @@ module Capybara
class ObsoleteNode < NodeError
def message
"The element you are trying to interact with is either not part of the DOM, or is " \
"not currently visible on the page (perhaps display: none is set). " \
'The element you are trying to interact with is either not part of the DOM, or is ' \
'not currently visible on the page (perhaps display: none is set). ' \
"It's possible the element has been replaced by another element and you meant to interact with " \
"the new element. If so you need to do a new 'find' in order to get a reference to the " \
"new element."
'new element.'
end
end
@ -127,7 +127,7 @@ module Capybara
end
def version
response['args'][1].values_at(*%w(major minor patch)).join '.'
response['args'][1].values_at('major', 'minor', 'patch').join '.'
end
def message
@ -151,14 +151,14 @@ module Capybara
def message
"Firing a #{name} at co-ordinates [#{position.join(', ')}] failed. Poltergeist detected " \
"another element with CSS selector '#{selector}' at this position. " \
"It may be overlapping the element you are trying to interact with. " \
'It may be overlapping the element you are trying to interact with. ' \
"If you don't care about overlapping elements, try using node.trigger('#{name}')."
end
end
class KeyError < ::ArgumentError
def initialize(response)
super(response["args"].first)
super(response['args'].first)
end
end
@ -169,20 +169,19 @@ module Capybara
def message
"Timed out waiting for response to #{@message}. It's possible that this happened " \
"because something took a very long time (for example a page load was slow). " \
"If so, setting the Poltergeist :timeout option to a higher value will help " \
"(see the docs for details). If increasing the timeout does not help, this is " \
"probably a bug in Poltergeist - please report it to the issue tracker."
'because something took a very long time (for example a page load was slow). ' \
'If so, setting the Poltergeist :timeout option to a higher value will help ' \
'(see the docs for details). If increasing the timeout does not help, this is ' \
'probably a bug in Poltergeist - please report it to the issue tracker.'
end
end
class ScriptTimeoutError < Error
def message
"Timed out waiting for evaluated script to resturn a value"
'Timed out waiting for evaluated script to resturn a value'
end
end
class DeadClient < Error
def initialize(message)
@message = message
@ -195,10 +194,10 @@ module Capybara
class PhantomJSTooOld < Error
def self.===(other)
if Cliver::Dependency::VersionMismatch === other
warn "#{name} exception has been deprecated in favor of using the " +
"cliver gem for command-line dependency detection. Please " +
"handle Cliver::Dependency::VersionMismatch instead."
if other.is_a? Cliver::Dependency::VersionMismatch
warn "#{name} exception has been deprecated in favor of using the " \
'cliver gem for command-line dependency detection. Please ' \
'handle Cliver::Dependency::VersionMismatch instead.'
true
else
super
@ -208,10 +207,10 @@ module Capybara
class PhantomJSFailed < Error
def self.===(other)
if Cliver::Dependency::NotMet === other
warn "#{name} exception has been deprecated in favor of using the " +
"cliver gem for command-line dependency detection. Please " +
"handle Cliver::Dependency::NotMet instead."
if other.is_a? Cliver::Dependency::NotMet
warn "#{name} exception has been deprecated in favor of using the " \
'cliver gem for command-line dependency detection. Please ' \
'handle Cliver::Dependency::NotMet instead.'
true
else
super

View File

@ -2,7 +2,7 @@
module Capybara::Poltergeist
class Inspector
BROWSERS = %w(chromium chromium-browser google-chrome open)
BROWSERS = %w[chromium chromium-browser google-chrome open].freeze
DEFAULT_PORT = 9664
def self.detect_browser
@ -30,19 +30,19 @@ module Capybara::Poltergeist
else
raise Error, "Could not find a browser executable to open #{url(scheme)}. " \
"You can specify one manually using e.g. `:inspector => 'chromium'` " \
"as a configuration option for Poltergeist."
'as a configuration option for Poltergeist.'
end
end
def self.browser_binary_exists?(browser)
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
exts.each { |ext|
exts.each do |ext|
exe = "#{path}#{File::SEPARATOR}#{browser}#{ext}"
return exe if File.executable? exe
}
end
end
return nil
nil
end
end
end

View File

@ -39,4 +39,3 @@ module Capybara::Poltergeist::NetworkTraffic
end
end
end

View File

@ -53,8 +53,8 @@ module Capybara::Poltergeist
filter_text command(:visible_text)
else
command(:visible_text).to_s
.gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
.gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
.gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
.gsub(/\n+/, "\n")
.tr("\u00a0", ' ')
end
@ -67,10 +67,9 @@ module Capybara::Poltergeist
def [](name)
# Although the attribute matters, the property is consistent. Return that in
# preference to the attribute for links and images.
if (tag_name == 'img' and name == 'src') or (tag_name == 'a' and name == 'href' )
#if attribute exists get the property
value = command(:attribute, name) && command(:property, name)
return value
if ((tag_name == 'img') && (name == 'src')) || ((tag_name == 'a') && (name == 'href'))
# if attribute exists get the property
return command(:attribute, name) && command(:property, name)
end
value = property(name)
@ -115,8 +114,8 @@ module Capybara::Poltergeist
end
def unselect_option
command(:select, false) or
raise(Capybara::UnselectNotAllowed, "Cannot unselect option from single select box.")
command(:select, false) ||
raise(Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.')
end
def tag_name
@ -139,15 +138,15 @@ module Capybara::Poltergeist
command :disabled?
end
def click(keys=[], offset={})
def click(keys = [], offset = {})
command :click, keys, offset
end
def right_click(keys=[], offset={})
def right_click(keys = [], offset = {})
command :right_click, keys, offset
end
def double_click(keys=[], offset={})
def double_click(keys = [], offset = {})
command :double_click, keys, offset
end
@ -187,19 +186,19 @@ module Capybara::Poltergeist
# @api private
def as_json(*)
{ ELEMENT: {page_id: @page_id, id: @id} }
{ ELEMENT: { page_id: @page_id, id: @id } }
end
private
def filter_text(text, visible = true)
def filter_text(text)
if Capybara::VERSION.to_f < 3
Capybara::Helpers.normalize_whitespace(text.to_s)
else
text.gsub(/[\u200b\u200e\u200f]/, '')
.gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
.gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
.gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
.gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
.tr("\u00a0", ' ')
end
end

View File

@ -42,7 +42,7 @@ module Capybara::Poltergeist
command.args.push(timeout) # set the client set visit timeout parameter
receive_timeout = timeout + 5 # Add a couple of seconds to let the client timeout first
end
@socket.send(command.id, command.message, receive_timeout) or raise DeadClient.new(command.message)
@socket.send(command.id, command.message, receive_timeout) || raise(DeadClient, command.message)
end
end
end

View File

@ -4,11 +4,11 @@ module Capybara
module Poltergeist
class << self
def windows?
RbConfig::CONFIG["host_os"] =~ /mingw|mswin|cygwin/
RbConfig::CONFIG['host_os'] =~ /mingw|mswin|cygwin/
end
def mri?
defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby"
defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby'
end
end
end

View File

@ -2,6 +2,6 @@
module Capybara
module Poltergeist
VERSION = "1.18.1"
VERSION = '1.18.1'
end
end

View File

@ -38,12 +38,9 @@ module Capybara::Poltergeist
@host = server.addr[2]
end
rescue Errno::EADDRINUSE
if (Time.now - time) < BIND_TIMEOUT
sleep(0.01)
retry
else
raise
end
raise if (Time.now - time) >= BIND_TIMEOUT
sleep(0.01)
retry
end
end
@ -58,9 +55,9 @@ module Capybara::Poltergeist
@messages = {}
@driver = ::WebSocket::Driver.server(self)
@driver.on(:connect) { |event| @driver.start }
@driver.on(:connect) { |_event| @driver.start }
@driver.on(:message) do |event|
command_id = JSON.load(event.data)['command_id']
command_id = JSON.parse(event.data)['command_id']
@messages[command_id] = event.data
end
end
@ -71,15 +68,15 @@ module Capybara::Poltergeist
# Block until the next message is available from the Web Socket.
# Raises Errno::EWOULDBLOCK if timeout is reached.
def receive(cmd_id, receive_timeout=nil)
def receive(cmd_id, receive_timeout = nil)
receive_timeout ||= timeout
start = Time.now
until @messages.has_key?(cmd_id)
until @messages.key?(cmd_id)
raise Errno::EWOULDBLOCK if (Time.now - start) >= receive_timeout
if @receive_mutex.try_lock
begin
IO.select([socket], [], [], receive_timeout) or raise Errno::EWOULDBLOCK
IO.select([socket], [], [], receive_timeout) || raise(Errno::EWOULDBLOCK)
data = socket.recv(RECV_SIZE)
break if data.empty?
driver.parse(data)
@ -94,12 +91,12 @@ module Capybara::Poltergeist
end
# Send a message and block until there is a response
def send(cmd_id, message, accept_timeout=nil)
def send(cmd_id, message, accept_timeout = nil)
accept unless connected?
driver.text(message)
receive(cmd_id, accept_timeout)
rescue Errno::EWOULDBLOCK
raise TimeoutError.new(message)
raise TimeoutError, message
end
# Closing sockets separately as `close_read`, `close_write`

View File

@ -1,4 +1,6 @@
lib = File.expand_path('../lib/', __FILE__)
# frozen_string_literal: true
lib = File.expand_path('lib', __dir__)
$:.unshift lib unless $:.include?(lib)
require 'capybara/poltergeist/version'
@ -16,23 +18,23 @@ Gem::Specification.new do |s|
'PhantomJS.'
s.license = 'MIT'
s.require_paths = ['lib']
s.files = Dir.glob('{lib}/**/*') + %w(LICENSE README.md)
s.files = Dir.glob('{lib}/**/*') + %w[LICENSE README.md]
s.required_ruby_version = '>= 2.3.0'
s.add_runtime_dependency 'capybara', '>= 2.1', '< 4'
s.add_runtime_dependency 'websocket-driver', '>= 0.2.0'
s.add_runtime_dependency 'cliver', '~> 0.3.1'
s.add_runtime_dependency 'websocket-driver', '>= 0.2.0'
s.add_development_dependency 'coffee-script', '~> 2.2'
s.add_development_dependency 'coffee-script-source', '~>1.12.2'
s.add_development_dependency 'erubi' # required by rbx
s.add_development_dependency 'guard-coffeescript', '~> 2.0.0'
s.add_development_dependency 'image_size', '~> 1.0'
s.add_development_dependency 'launchy', '~> 2.0'
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 'pdf-reader', '< 3.0', '>= 1.3.3'
s.add_development_dependency 'rake'
s.add_development_dependency 'rspec', '~> 3.7'
s.add_development_dependency 'sinatra', '<= 3.0'
s.add_development_dependency 'rake'
s.add_development_dependency 'image_size', '~> 1.0'
s.add_development_dependency 'pdf-reader', '< 3.0', '>= 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.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 'erubi' # required by rbx
end

View File

@ -39,7 +39,7 @@ module Capybara::Poltergeist
expect(File.exist?(file)).to be true
ensure
driver.quit if driver
driver&.quit
end
end
@ -63,20 +63,20 @@ module Capybara::Poltergeist
end
it 'is threadsafe in how it captures console.log' do
pending("JRuby and Rubinius do not support the :out parameter to Process.spawn, so there is no threadsafe way to redirect output") unless Capybara::Poltergeist.mri?
pending('JRuby and Rubinius do not support the :out parameter to Process.spawn, so there is no threadsafe way to redirect output') unless Capybara::Poltergeist.mri?
# Write something to STDOUT right before Process.spawn is called
allow(Process).to receive(:spawn).and_wrap_original do |m,*args|
STDOUT.puts "1"
$stdout.puts "2"
allow(Process).to receive(:spawn).and_wrap_original do |m, *args|
STDOUT.puts '1'
$stdout.puts '2'
m.call(*args)
end
expect {
expect do
session.visit('/poltergeist/console_log')
}.to output("1\n2\n").to_stdout_from_any_process
end.to output("1\n2\n").to_stdout_from_any_process
expect(logger.string).not_to match /\d/
expect(logger.string).not_to match(/\d/)
end
end
@ -118,7 +118,7 @@ module Capybara::Poltergeist
@session.visit('/')
@session.current_window.maximize
expect(@session.current_window.size).to eq([1600, 1200])
ensure
ensure
@driver.options.delete(:screen_size)
end
end
@ -142,12 +142,12 @@ module Capybara::Poltergeist
)
end
driver = Capybara::Session.new(:poltergeist_with_custom_window_size, TestApp).driver
driver.visit(session_url '/')
driver.visit(session_url('/'))
expect(
driver.evaluate_script('[window.innerWidth, window.innerHeight]')
).to eq([800, 600])
ensure
driver.quit if driver
driver&.quit
end
end
@ -187,13 +187,13 @@ module Capybara::Poltergeist
create_screenshot file, selector: '#penultimate'
File.open(file, 'rb') do |f|
size = @driver.evaluate_script <<-EOS
size = @driver.evaluate_script <<-JS
function() {
var ele = document.getElementById('penultimate');
var rect = ele.getBoundingClientRect();
return [rect.width, rect.height];
}();
EOS
JS
expect(ImageSize.new(f.read).size).to eq(size)
end
end
@ -214,7 +214,7 @@ module Capybara::Poltergeist
it 'resets element positions after' do
@session.visit('poltergeist/long_page')
el = @session.find(:css, '#middleish')
#make the page scroll an element into view
# make the page scroll an element into view
el.click
position_script = 'document.querySelector("#middleish").getBoundingClientRect()'
offset = @session.evaluate_script(position_script)
@ -251,7 +251,7 @@ module Capybara::Poltergeist
it 'supports rendering the page to file without extension when format is specified' do
begin
file = POLTERGEIST_ROOT + "/spec/tmp/screenshot"
file = POLTERGEIST_ROOT + '/spec/tmp/screenshot'
FileUtils.rm_f file
@session.visit('/')
@ -286,8 +286,8 @@ module Capybara::Poltergeist
it 'changes image dimensions' do
@session.visit('/poltergeist/zoom_test')
black_pixels_count = ->(file) {
File.read(file).to_s[/{.*}/m][1...-1].split(/\W/).map{|n| n.hex.to_s(2).count('1')}.reduce(:+)
black_pixels_count = lambda { |file|
File.read(file).to_s[/{.*}/m][1...-1].split(/\W/).map { |n| n.hex.to_s(2).count('1') }.reduce(:+)
}
@driver.save_screenshot(file)
before = black_pixels_count[file]
@ -296,7 +296,7 @@ module Capybara::Poltergeist
@driver.save_screenshot(file)
after = black_pixels_count[file]
expect(after.to_f/before.to_f).to eq(zoom_factor**2)
expect(after.to_f / before.to_f).to eq(zoom_factor**2)
end
end
@ -408,8 +408,8 @@ module Capybara::Poltergeist
it 'sets headers on the initial request' do
@driver.headers = { 'PermanentA' => 'a' }
@driver.add_headers('PermanentB' => 'b')
@driver.add_header('Referer', 'http://google.com', :permanent => false)
@driver.add_header('TempA', 'a', :permanent => false)
@driver.add_header('Referer', 'http://google.com', permanent: false)
@driver.add_header('TempA', 'a', permanent: false)
@session.visit('/poltergeist/headers_with_ajax')
initial_request = @session.find(:css, '#initial_request').text
@ -427,14 +427,14 @@ module Capybara::Poltergeist
end
it 'keeps added headers on redirects by default' do
@driver.add_header('X-Custom-Header', '1', :permanent => false)
@driver.add_header('X-Custom-Header', '1', permanent: false)
@session.visit('/poltergeist/redirect_to_headers')
expect(@driver.body).to include('X_CUSTOM_HEADER: 1')
end
it 'does not keep added headers on redirect when ' \
'permanent is no_redirect' do
@driver.add_header('X-Custom-Header', '1', :permanent => :no_redirect)
@driver.add_header('X-Custom-Header', '1', permanent: :no_redirect)
@session.visit('/poltergeist/redirect_to_headers')
expect(@driver.body).not_to include('X_CUSTOM_HEADER: 1')
@ -476,7 +476,7 @@ module Capybara::Poltergeist
it 'keeps temporary headers local to the current window' do
@session.open_new_window
@driver.add_header('X-Custom-Header', '1', :permanent => false)
@driver.add_header('X-Custom-Header', '1', permanent: false)
@session.switch_to_window @session.windows.last
@session.visit('/poltergeist/headers')
@ -489,7 +489,7 @@ module Capybara::Poltergeist
it 'does not mix temporary headers with permanent ones when propagating to other windows' do
@session.open_new_window
@driver.add_header('X-Custom-Header', '1', :permanent => false)
@driver.add_header('X-Custom-Header', '1', permanent: false)
@driver.add_header('Host', 'foo.com')
@session.switch_to_window @session.windows.last
@ -505,7 +505,7 @@ module Capybara::Poltergeist
it 'does not propagate temporary headers to new windows' do
@session.visit '/'
@driver.add_header('X-Custom-Header', '1', :permanent => false)
@driver.add_header('X-Custom-Header', '1', permanent: false)
@session.open_new_window
@session.switch_to_window @session.windows.last
@ -562,8 +562,8 @@ module Capybara::Poltergeist
@extended_driver = Capybara::Poltergeist::Driver.new(
@session.app,
logger: TestSessions.logger,
inspector: ENV['DEBUG'] != nil,
extensions: %W% #{File.expand_path '../../support/geolocation.js', __FILE__ } %
inspector: !ENV['DEBUG'].nil?,
extensions: %W[#{File.expand_path '../support/geolocation.js', __dir__}]
)
end
@ -573,8 +573,9 @@ module Capybara::Poltergeist
it 'supports extending the phantomjs world' do
@extended_driver.visit session_url('/poltergeist/requiring_custom_extension')
expect(@extended_driver.body).
to include(%Q%Location: <span id="location">1,-1</span>%)
expect(
@extended_driver.body
).to include(%(Location: <span id="location">1,-1</span>))
expect(
@extended_driver.evaluate_script("document.getElementById('location').innerHTML")
).to eq('1,-1')
@ -588,8 +589,8 @@ module Capybara::Poltergeist
@failing_driver = Capybara::Poltergeist::Driver.new(
@session.app,
logger: TestSessions.logger,
inspector: ENV['DEBUG'] != nil,
extensions: %W% #{File.expand_path '../../support/non_existent.js', __FILE__} %
inspector: !ENV['DEBUG'].nil?,
extensions: %W[#{File.expand_path '../support/non_existent.js', __dir__}]
)
expect { @failing_driver.visit '/' }.to raise_error(Capybara::Poltergeist::BrowserError, /Unable to load extension: .*non_existent\.js/)
ensure
@ -600,9 +601,9 @@ module Capybara::Poltergeist
context 'javascript errors' do
it 'propagates a Javascript error inside Poltergeist to a ruby exception' do
expect {
expect do
@driver.browser.command 'browser_error'
}.to raise_error(BrowserError) { |e|
end.to raise_error(BrowserError) { |e|
expect(e.message).to include('Error: zomg')
# PhantomJS 2.1 refers to files as being in code subdirectory
expect(e.message).to include('compiled/browser.js').or include('code/browser.js')
@ -610,25 +611,25 @@ module Capybara::Poltergeist
end
it 'propagates an asynchronous Javascript error on the page to a ruby exception' do
expect {
expect do
@driver.execute_script 'setTimeout(function() { omg }, 0)'
sleep 0.01
@driver.execute_script ''
}.to raise_error(JavascriptError, /ReferenceError.*omg/)
end.to raise_error(JavascriptError, /ReferenceError.*omg/)
end
it 'propagates a synchronous Javascript error on the page to a ruby exception' do
expect {
expect do
@driver.execute_script 'omg'
}.to raise_error(JavascriptError, /ReferenceError.*omg/)
end.to raise_error(JavascriptError, /ReferenceError.*omg/)
end
it 'does not re-raise a Javascript error if it is rescued' do
expect {
expect do
@driver.execute_script 'setTimeout(function() { omg }, 0)'
sleep 0.01
@driver.execute_script ''
}.to raise_error(JavascriptError)
end.to raise_error(JavascriptError)
# should not raise again
expect(@driver.evaluate_script('1+1')).to eq(2)
@ -646,7 +647,7 @@ module Capybara::Poltergeist
sleep 0.1
expect(driver.body).to include('hello')
ensure
driver.quit if driver
driver&.quit
end
end
@ -659,7 +660,7 @@ module Capybara::Poltergeist
sleep 0.1
expect(driver.body).to include('hello')
ensure
driver.quit if driver
driver&.quit
end
end
@ -670,7 +671,7 @@ module Capybara::Poltergeist
driver.visit session_url('/poltergeist/headers')
expect(driver.body).to include('USER_AGENT: PageSettingsOverride')
ensure
driver.quit if driver
driver&.quit
end
end
@ -679,12 +680,11 @@ module Capybara::Poltergeist
# If PJS resource timeout is less than drivers timeout it should ignore resources not loading in time
driver = Capybara::Poltergeist::Driver.new(@session.app, page_settings: { resourceTimeout: 1000 }, logger: TestSessions.logger)
driver.timeout = 3
start = Time.now
expect{
expect do
driver.visit session_url('/poltergeist/visit_timeout')
}.not_to raise_error
end.not_to raise_error
ensure
driver.quit if driver
driver&.quit
end
end
end
@ -703,18 +703,18 @@ module Capybara::Poltergeist
it 'has a descriptive message when DNS incorrect' do
url = "http://nope:#{@port}/"
expect {
expect do
@session.visit(url)
}.to raise_error(StatusFailError, "Request to '#{url}' failed to reach server, check DNS and/or server status")
end.to raise_error(StatusFailError, "Request to '#{url}' failed to reach server, check DNS and/or server status")
end
it 'reports open resource requests' do
old_timeout = @session.driver.timeout
begin
@session.driver.timeout = 2
expect{
expect do
@session.visit('/poltergeist/visit_timeout')
}.to raise_error(StatusFailError, /resources still waiting http:\/\/.*\/poltergeist\/really_slow/)
end.to raise_error(StatusFailError, %r{resources still waiting http://.*/poltergeist/really_slow})
ensure
@session.driver.timeout = old_timeout
end
@ -724,9 +724,9 @@ module Capybara::Poltergeist
old_timeout = @session.driver.timeout
begin
@session.driver.timeout = 2
expect{
expect do
@session.visit('/poltergeist/really_slow')
}.to raise_error(StatusFailError) {|error|
end.to raise_error(StatusFailError) { |error|
expect(error.message).not_to include('resources still waiting')
}
ensure
@ -814,14 +814,13 @@ module Capybara::Poltergeist
end
end
context "memory cache clearing" do
context 'memory cache clearing' do
before do
@driver.restart
end
it "can clear memory cache when supported (phantomjs >=2.0.0)" do
skip "clear_memory_cache is not supported by tested PhantomJS" unless phantom_version_is? ">= 2.0.0", @driver
it 'can clear memory cache when supported (phantomjs >=2.0.0)' do
skip 'clear_memory_cache is not supported by tested PhantomJS' unless phantom_version_is? '>= 2.0.0', @driver
@driver.clear_memory_cache
@ -841,15 +840,15 @@ module Capybara::Poltergeist
expect(another_request.response_parts.last.status).to eq(200)
end
it "raises error when it is unsupported (phantomjs <2.0.0)" do
skip "clear_memory_cache is supported by tested PhantomJS" if phantom_version_is? ">= 2.0.0", @driver
it 'raises error when it is unsupported (phantomjs <2.0.0)' do
skip 'clear_memory_cache is supported by tested PhantomJS' if phantom_version_is? '>= 2.0.0', @driver
@session.visit('/poltergeist/cacheable')
first_request = @driver.network_traffic.last
expect(@driver.network_traffic.length).to eq(1)
expect(first_request.response_parts.last.status).to eq(200)
expect{@driver.clear_memory_cache}.to raise_error(Capybara::Poltergeist::UnsupportedFeature)
expect { @driver.clear_memory_cache }.to raise_error(Capybara::Poltergeist::UnsupportedFeature)
@session.visit('/poltergeist/cacheable')
expect(@driver.network_traffic.length).to eq(2)
@ -996,14 +995,14 @@ module Capybara::Poltergeist
# If var is unspecified, skip test
host = ENV['POLTERGEIST_TEST_HOST']
skip "POLTERGEIST_TEST_HOST not set" if host.nil?
skip 'POLTERGEIST_TEST_HOST not set' if host.nil?
driver = Capybara::Poltergeist::Driver.new(@driver.app, host: host, port: 12345)
driver.visit session_url('/')
expect { TCPServer.new(host, 12345) }.to raise_error(Errno::EADDRINUSE)
ensure
driver.quit if driver
driver&.quit
end
end
@ -1014,7 +1013,7 @@ module Capybara::Poltergeist
window.open('/poltergeist/simple', 'popup')
JS
expect(@driver.window_handles).to eq(['0', '1'])
expect(@driver.window_handles).to eq(%w[0 1])
popup2 = @session.window_opened_by do
@session.execute_script <<-JS
@ -1022,24 +1021,24 @@ module Capybara::Poltergeist
JS
end
expect(@driver.window_handles).to eq(['0', '1', '2'])
expect(@driver.window_handles).to eq(%w[0 1 2])
@session.within_window(popup2) do
expect(@session.html).to include('Test')
@session.execute_script('window.close()')
end
sleep 0.1;
sleep 0.1
expect(@driver.window_handles).to eq(['0', '1'])
expect(@driver.window_handles).to eq(%w[0 1])
end
context 'a new window inherits settings' do
it 'inherits size' do
@session.visit '/'
@session.current_window.resize_to(1200,800)
@session.current_window.resize_to(1200, 800)
new_tab = @session.open_new_window
expect(new_tab.size).to eq [1200,800]
expect(new_tab.size).to eq [1200, 800]
end
it 'inherits url_blacklist' do
@ -1067,14 +1066,13 @@ module Capybara::Poltergeist
expect(@session).to have_content('We should see this.')
end
@session.within_frame 'unwantedframe' do
#make sure non whitelisted urls are blocked
# make sure non whitelisted urls are blocked
expect(@session).not_to have_content("We shouldn't see this.")
end
end
end
end
it 'resizes windows' do
@session.visit '/'
@ -1090,11 +1088,11 @@ module Capybara::Poltergeist
JS
end
popup1.resize_to(100,200)
popup2.resize_to(200,100)
popup1.resize_to(100, 200)
popup2.resize_to(200, 100)
expect(popup1.size).to eq([100,200])
expect(popup2.size).to eq([200,100])
expect(popup1.size).to eq([100, 200])
expect(popup2.size).to eq([200, 100])
end
it 'clears local storage between tests' do
@ -1282,7 +1280,7 @@ module Capybara::Poltergeist
end
session.within_frame 'unwantedframe' do
#make sure non whitelisted urls are blocked
# make sure non whitelisted urls are blocked
expect(session).not_to have_content("We shouldn't see this.")
end
@ -1294,13 +1292,12 @@ module Capybara::Poltergeist
expect(session).to have_content('We should see this.')
end
session.within_frame 'unwantedframe' do
#make sure non whitelisted urls are blocked
# make sure non whitelisted urls are blocked
expect(session).not_to have_content("We shouldn't see this.")
end
end
end
context 'has ability to send keys' do
before { @session.visit('/poltergeist/send_keys') }
@ -1389,7 +1386,7 @@ module Capybara::Poltergeist
it 'sends sequences with modifiers and symbols' do
input = @session.find(:css, '#empty_input')
input.native.send_keys('t', 'r', 'i', 'n', 'g', [:Ctrl, :Left], 's')
input.native.send_keys('t', 'r', 'i', 'n', 'g', %i[Ctrl Left], 's')
expect(input.value).to eq('string')
end
@ -1397,7 +1394,7 @@ module Capybara::Poltergeist
it 'sends sequences with multiple modifiers and symbols' do
input = @session.find(:css, '#empty_input')
input.native.send_keys('t', 'r', 'i', 'n', 'g', [:Ctrl, :Shift, :Left], 's')
input.native.send_keys('t', 'r', 'i', 'n', 'g', %i[Ctrl Shift Left], 's')
expect(input.value).to eq('s')
end
@ -1413,7 +1410,7 @@ module Capybara::Poltergeist
it 'sends modifiers with multiple keys' do
input = @session.find(:css, '#empty_input')
input.native.send_keys('poltre', [:Shift, :Left, :Left], 'ergeist')
input.native.send_keys('poltre', %i[Shift Left Left], 'ergeist')
expect(input.value).to eq('poltergeist')
end
@ -1431,38 +1428,38 @@ module Capybara::Poltergeist
input.send_keys([:shift, '.'], [:shift, 't'])
expect(@session.find(:css, '#key-events-output')).to have_text("keydown:16 keydown:190 keydown:16 keydown:84")
expect(@session.find(:css, '#key-events-output')).to have_text('keydown:16 keydown:190 keydown:16 keydown:84')
end
it 'suuports snake_case sepcified keys (Capybara standard)' do
input = @session.find(:css, '#empty_input')
input.send_keys(:PageUp, :page_up)
expect(@session.find(:css, '#key-events-output')).to have_text("keydown:33", count: 2)
expect(@session.find(:css, '#key-events-output')).to have_text('keydown:33', count: 2)
end
it 'supports :control alias for :Ctrl' do
input = @session.find(:css, '#empty_input')
input.send_keys([:Ctrl, 'a'], [:control, 'a'])
expect(@session.find(:css, '#key-events-output')).to have_text("keydown:17 keydown:65", count: 2)
expect(@session.find(:css, '#key-events-output')).to have_text('keydown:17 keydown:65', count: 2)
end
it 'supports :command alias for :Meta' do
input = @session.find(:css, '#empty_input')
input.send_keys([:Meta, 'z'], [:command, 'z'])
expect(@session.find(:css, '#key-events-output')).to have_text("keydown:91 keydown:90", count: 2)
expect(@session.find(:css, '#key-events-output')).to have_text('keydown:91 keydown:90', count: 2)
end
it 'supports Capybara specified numpad keys' do
input = @session.find(:css, '#empty_input')
input.send_keys(:numpad2, :numpad8, :divide, :decimal)
expect(@session.find(:css, '#key-events-output')).to have_text("keydown:98 keydown:104 keydown:111 keydown:110")
expect(@session.find(:css, '#key-events-output')).to have_text('keydown:98 keydown:104 keydown:111 keydown:110')
end
it 'raises error for unknown keys' do
input = @session.find(:css, '#empty_input')
expect {
expect do
input.send_keys('abc', :blah)
}.to raise_error Capybara::Poltergeist::KeyError, 'Unknown key: Blah'
end.to raise_error Capybara::Poltergeist::KeyError, 'Unknown key: Blah'
end
end
@ -1487,10 +1484,10 @@ module Capybara::Poltergeist
expect(input.text).to eq('replacement text')
end
it "sets a content editable childs content" do
it 'sets a content editable childs content' do
@session.visit('/with_js')
@session.find(:css,'#existing_content_editable_child').set('WYSIWYG')
expect(@session.find(:css,'#existing_content_editable_child').text).to eq('WYSIWYG')
@session.find(:css, '#existing_content_editable_child').set('WYSIWYG')
expect(@session.find(:css, '#existing_content_editable_child').text).to eq('WYSIWYG')
end
end
@ -1512,22 +1509,22 @@ module Capybara::Poltergeist
end
end
context 'evaluate_script'do
context 'evaluate_script' do
it 'can return an element' do
@session.visit('/poltergeist/send_keys')
element = @session.driver.evaluate_script('document.getElementById("empty_input")')
expect(element).to eq(@session.find(:id, 'empty_input').native)
end
it 'can return structures with elements' do
it 'can return structures with elements' do
@session.visit('/poltergeist/send_keys')
result = @session.driver.evaluate_script('{ a: document.getElementById("empty_input"), b: { c: document.querySelectorAll("#empty_textarea, #filled_textarea") } }')
expect(result).to eq({
expect(result).to eq(
'a' => @session.driver.find_css('#empty_input').first,
'b' => {
'c' => @session.driver.find_css('#empty_textarea, #filled_textarea')
}
})
)
end
end
@ -1537,15 +1534,15 @@ module Capybara::Poltergeist
expect(@session.driver.evaluate_async_script('arguments[0](null)')).to be_nil
expect(@session.driver.evaluate_async_script('arguments[0](false)')).to be false
expect(@session.driver.evaluate_async_script('arguments[0](true)')).to be true
expect(@session.driver.evaluate_async_script("arguments[0]({foo: 'bar'})")).to eq({'foo' => 'bar'})
expect(@session.driver.evaluate_async_script("arguments[0]({foo: 'bar'})")).to eq('foo' => 'bar')
end
end
it 'will timeout' do
@session.using_wait_time(1) do
expect {
expect do
@session.driver.evaluate_async_script('var callback=arguments[0]; setTimeout(function(){callback(true)}, 4000)')
}.to raise_error Capybara::Poltergeist::ScriptTimeoutError
end.to raise_error Capybara::Poltergeist::ScriptTimeoutError
end
end
end

View File

@ -1,4 +1,3 @@
# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
@ -57,11 +56,11 @@ describe Capybara::Session do
context 'when someone (*cough* prototype *cough*) messes with Array#toJSON' do
before do
@session.visit('/poltergeist/index')
array_munge = <<-EOS
array_munge = <<-JS
Array.prototype.toJSON = function() {
return "ohai";
}
EOS
JS
@session.execute_script array_munge
end
@ -193,7 +192,7 @@ describe Capybara::Session do
it 'accepts negatives in a number field' do
element = @session.find(:css, '#change_me_number')
element.set -100
element.set(-100)
expect(element.value).to eq('-100')
end
@ -290,13 +289,13 @@ describe Capybara::Session do
end
it 'gets innerHTML' do
expect(@session.find(:css,'.some_other_class')['innerHTML']).to eq '<p>foobar</p>'
expect(@session.find(:css, '.some_other_class')['innerHTML']).to eq '<p>foobar</p>'
end
it 'gets attribute' do
link = @session.find(:link, 'Loop')
expect(link['data-random']).to eq '42'
expect(link['onclick']).to eq "return false;"
expect(link['onclick']).to eq 'return false;'
end
it 'gets boolean attributes as booleans' do
@ -355,7 +354,7 @@ describe Capybara::Session do
expect(@session.evaluate_script('null')).to be_nil
expect(@session.evaluate_script('false')).to be false
expect(@session.evaluate_script('true')).to be true
expect(@session.evaluate_script("{foo: 'bar'}")).to eq({'foo' => 'bar'})
expect(@session.evaluate_script("{foo: 'bar'}")).to eq('foo' => 'bar')
end
it 'can evaluate a statement ending with a semicolon' do
@ -382,8 +381,8 @@ describe Capybara::Session do
@session.driver.resize(200, 200)
log = @session.find(:css, '#log')
instructions = %w(one four one two three)
instructions.each do |instruction, i|
instructions = %w[one four one two three]
instructions.each do |instruction|
@session.find(:css, "##{instruction}").click
expect(log.text).to eq(instruction)
end
@ -411,18 +410,18 @@ describe Capybara::Session do
end
it 'detects if an element is obscured when clicking' do
expect {
expect do
@session.find(:css, '#one').click
}.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
end.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
expect(error.selector).to eq('html body div#two.box')
expect(error.message).to include('[200, 200]')
}
end
it 'clicks in the centre of an element' do
expect {
expect do
@session.find(:css, '#one').click
}.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
end.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
expect(error.position).to eq([200, 200])
}
end
@ -430,9 +429,9 @@ describe Capybara::Session do
it 'clicks in the centre of an element within the viewport, if part is outside the viewport' do
@session.driver.resize(200, 200)
expect {
expect do
@session.find(:css, '#one').click
}.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
end.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
expect(error.position.first).to eq(150)
}
end
@ -449,16 +448,16 @@ describe Capybara::Session do
end
it 'detects if an element is obscured when clicking' do
expect {
expect do
@session.find(:css, '#one').click
}.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
end.to raise_error(Capybara::Poltergeist::MouseEventFailed) { |error|
expect(error.selector).to eq('html body svg#svg.box')
expect(error.message).to include('[200, 200]')
}
end
end
context "with image maps" do
context 'with image maps' do
before do
@session.visit('/poltergeist/image_map')
end
@ -471,12 +470,12 @@ describe Capybara::Session do
end
it "doesn't click if the associated img is hidden" do
expect {
expect do
@session.find(:css, 'map[name=testmap2] area[shape=circle]').click
}.to raise_error(Capybara::ElementNotFound)
expect {
end.to raise_error(Capybara::ElementNotFound)
expect do
@session.find(:css, 'map[name=testmap2] area[shape=circle]', visible: false).click
}.to raise_error(Capybara::Poltergeist::MouseEventFailed)
end.to raise_error(Capybara::Poltergeist::MouseEventFailed)
end
end
end
@ -490,8 +489,8 @@ describe Capybara::Session do
@session.driver.resize(200, 200)
log = @session.find(:css, '#log')
instructions = %w(one four one two three)
instructions.each do |instruction, i|
instructions = %w[one four one two three]
instructions.each do |instruction|
@session.find(:css, "##{instruction}").base.double_click
expect(log.text).to eq(instruction)
end
@ -531,7 +530,7 @@ describe Capybara::Session do
return a;
})()
JS
expect(@session.evaluate_script(code)).to eq({"a"=>"(cyclic structure)", "b"=>{}, "c"=>{"a"=>"(cyclic structure)"}})
expect(@session.evaluate_script(code)).to eq('a' => '(cyclic structure)', 'b' => {}, 'c' => { 'a' => '(cyclic structure)' })
end
if Capybara::VERSION.to_f < 3.0
@ -548,12 +547,12 @@ describe Capybara::Session do
it 'handles hash changes' do
@session.visit '/#omg'
expect(@session.current_url).to match(/\/#omg$/)
expect(@session.current_url).to match(%r{/#omg$})
@session.execute_script <<-JS
window.onhashchange = function() { window.last_hashchange = window.location.hash }
JS
@session.visit '/#foo'
expect(@session.current_url).to match(/\/#foo$/)
expect(@session.current_url).to match(%r{/#foo$})
expect(@session.evaluate_script('window.last_hashchange')).to eq('#foo')
end
@ -571,12 +570,12 @@ describe Capybara::Session do
end
it 'supports url in parameter' do
@session.visit "/poltergeist/arbitrary_path/200/foo%20asd?a=http://example.com/asd%20asd"
@session.visit '/poltergeist/arbitrary_path/200/foo%20asd?a=http://example.com/asd%20asd'
expect(request_uri).to eq('/poltergeist/arbitrary_path/200/foo%20asd?a=http://example.com/asd%20asd')
end
it 'supports restricted characters " []:/+&="' do
@session.visit "/poltergeist/arbitrary_path/200/foo?a=%20%5B%5D%3A%2F%2B%26%3D"
@session.visit '/poltergeist/arbitrary_path/200/foo?a=%20%5B%5D%3A%2F%2B%26%3D'
expect(request_uri).to eq('/poltergeist/arbitrary_path/200/foo?a=%20%5B%5D%3A%2F%2B%26%3D')
end
@ -596,7 +595,7 @@ describe Capybara::Session do
droppable = @session.find(:css, '#drag_to #droppable')
draggable.drag_to(droppable)
expect( droppable ).to have_content( "Dropped" )
expect(droppable).to have_content('Dropped')
end
it 'supports drag_by on native element' do
@ -610,10 +609,9 @@ describe Capybara::Session do
top_after = @session.evaluate_script('$("#drag_by .draggable").position().top')
left_after = @session.evaluate_script('$("#drag_by .draggable").position().left')
expect( top_after ).to eq( top_before + 15 )
expect( left_after ).to eq( left_before + 15 )
expect(top_after).to eq(top_before + 15)
expect(left_after).to eq(left_before + 15)
end
end
context 'window switching support' do
@ -721,7 +719,7 @@ describe Capybara::Session do
expect(@session.driver.frame_url).to end_with('/poltergeist/frames')
end
context "with src == about:blank" do
context 'with src == about:blank' do
it "doesn't hang if no document created" do
@session.visit '/'
@session.execute_script <<-JS
@ -749,9 +747,9 @@ describe Capybara::Session do
end
end
context "with no src attribute" do
context 'with no src attribute' do
it "doesn't hang if the srcdoc attribute is used" do
skip "srcdoc attribute not supported by tested PhantomJS version" unless phantom_version_is? ">= 2.0.0", @session.driver
skip 'srcdoc attribute not supported by tested PhantomJS version' unless phantom_version_is? '>= 2.0.0', @session.driver
@session.visit '/'
@session.execute_script <<-JS
document.body.innerHTML += '<iframe srcdoc="<p>Hello Frame</p>" name="frame">'
@ -833,11 +831,11 @@ describe Capybara::Session do
it 'does not wait forever for the frame to load' do
@session.visit '/'
expect {
@session.within_frame('omg') { }
}.to raise_error { |e|
expect do
@session.within_frame('omg') {}
end.to(raise_error do |e|
expect(e).to be_a(Capybara::Poltergeist::FrameNotFound).or be_a(Capybara::ElementNotFound)
}
end)
end
end
@ -851,7 +849,7 @@ describe Capybara::Session do
@session.visit('/')
@session.find(:css, 'a').click
position = JSON.load(TestSessions.logger.messages.last)['response']['position']
position = JSON.parse(TestSessions.logger.messages.last)['response']['position']
expect(position['x']).to_not be_nil
expect(position['y']).to_not be_nil
end
@ -910,21 +908,21 @@ describe Capybara::Session do
end
it 'gets property innerHTML' do
expect(@session.find(:css,'.some_other_class').native.property('innerHTML')).to eq '<p>foobar</p>'
expect(@session.find(:css, '.some_other_class').native.property('innerHTML')).to eq '<p>foobar</p>'
end
it 'gets property outerHTML' do
expect(@session.find(:css,'.some_other_class').native.property('outerHTML')).to eq '<div class="some_other_class"><p>foobar</p></div>'
expect(@session.find(:css, '.some_other_class').native.property('outerHTML')).to eq '<div class="some_other_class"><p>foobar</p></div>'
end
it 'gets non existent property' do
expect(@session.find(:css,'.some_other_class').native.property('does_not_exist')).to eq nil
expect(@session.find(:css, '.some_other_class').native.property('does_not_exist')).to eq nil
end
end
it 'allows access to element attributes' do
@session.visit '/poltergeist/attributes_properties'
expect(@session.find(:css,'#my_link').native.attributes).to eq(
expect(@session.find(:css, '#my_link').native.attributes).to eq(
'href' => '#', 'id' => 'my_link', 'class' => 'some_class', 'data' => 'rah!'
)
end
@ -932,7 +930,7 @@ describe Capybara::Session do
it 'knows about its parents' do
@session.visit '/poltergeist/simple'
parents = @session.find(:css, '#nav').native.parents
expect(parents.map(&:tag_name)).to eq ['li','ul','body','html']
expect(parents.map(&:tag_name)).to eq %w[li ul body html]
end
context 'SVG tests' do
@ -948,33 +946,33 @@ describe Capybara::Session do
context 'modals' do
it 'matches on partial strings' do
@session.visit '/poltergeist/with_js'
expect {
expect do
@session.accept_confirm '[reg.exp] (chara©+er$)' do
@session.click_link('Open for match')
end
}.not_to raise_error
end.not_to raise_error
expect(@session).to have_xpath("//a[@id='open-match' and @confirmed='true']")
end
it 'matches on regular expressions' do
@session.visit '/poltergeist/with_js'
expect {
expect do
@session.accept_confirm(/^.t.ext.*\[\w{3}\.\w{3}\]/i) do
@session.click_link('Open for match')
end
}.not_to raise_error
end.not_to raise_error
expect(@session).to have_xpath("//a[@id='open-match' and @confirmed='true']")
end
it 'works with nested modals' do
@session.visit '/poltergeist/with_js'
expect {
expect do
@session.dismiss_confirm 'Are you really sure?' do
@session.accept_confirm 'Are you sure?' do
@session.click_link('Open check twice')
end
end
}.not_to raise_error
end.not_to raise_error
expect(@session).to have_xpath("//a[@id='open-twice' and @confirmed='false']")
end
@ -988,39 +986,39 @@ describe Capybara::Session do
end
@session.within_window(popup) do
expect {
expect do
@session.accept_confirm do
@session.click_link('Open for match')
end
expect(@session).to have_xpath("//a[@id='open-match' and @confirmed='true']")
}.not_to raise_error
end.not_to raise_error
end
popup.close
end
end
it "can go back when history state has been pushed" do
it 'can go back when history state has been pushed' do
@session.visit('/')
@session.execute_script('window.history.pushState({foo: "bar"}, "title", "bar2.html");')
expect(@session).to have_current_path('/bar2.html')
expect{@session.go_back}.not_to raise_error
expect { @session.go_back }.not_to raise_error
expect(@session).to have_current_path('/')
end
it "can go forward when history state is used" do
it 'can go forward when history state is used' do
@session.visit('/')
@session.execute_script('window.history.pushState({foo: "bar"}, "title", "bar2.html");')
expect(@session).to have_current_path('/bar2.html')
#don't use #go_back here to isolate the test
# don't use #go_back here to isolate the test
@session.execute_script('window.history.go(-1);')
expect(@session).to have_current_path('/')
expect{@session.go_forward}.not_to raise_error
expect { @session.go_forward }.not_to raise_error
expect(@session).to have_current_path('/bar2.html')
end
context "in threadsafe mode" do
context 'in threadsafe mode' do
before do
skip "No threadsafe mode in this version" unless Capybara.respond_to?(:threadsafe)
skip 'No threadsafe mode in this version' unless Capybara.respond_to?(:threadsafe)
Capybara::SpecHelper.reset_threadsafe(true, @session) if Capybara.respond_to?(:threadsafe)
end
@ -1028,7 +1026,7 @@ describe Capybara::Session do
Capybara::SpecHelper.reset_threadsafe(false, @session) if Capybara.respond_to?(:threadsafe)
end
it "uses per session wait setting" do
it 'uses per session wait setting' do
Capybara.default_max_wait_time = 1
@session.config.default_max_wait_time = 2
expect(@session.driver.send(:session_wait_time)).to eq 2
@ -1041,7 +1039,7 @@ describe Capybara::Session do
context 'with pty' do
before do
Tempfile.open(%w(test rb)) do |file|
Tempfile.open(%w[test rb]) do |file|
file.print(script)
file.flush
@ -1049,14 +1047,14 @@ describe Capybara::Session do
PTY.spawn("bundle exec ruby #{file.path}") do |read, write, pid|
sleep 0.1 until read.readline.chomp == 'Please type enter'
write.puts
sleep 0.1 until status = PTY.check(pid)
sleep 0.1 until (status = PTY.check(pid))
@status = status
end
end
end
end
let(:script) {
let(:script) do
<<-RUBY
require 'capybara/poltergeist'
@ -1068,7 +1066,7 @@ describe Capybara::Session do
sleep 1
browser.current_url
RUBY
}
end
it do
expect(@status).to be_success

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
POLTERGEIST_ROOT = File.expand_path('../..', __FILE__)
POLTERGEIST_ROOT = File.expand_path('..', __dir__)
$:.unshift(POLTERGEIST_ROOT + '/lib')
require 'bundler/setup'
@ -40,7 +40,7 @@ module Poltergeist
class << self
def set_capybara_wait_time(t)
Capybara.default_max_wait_time = t
rescue
rescue StandardError
Capybara.default_wait_time = t
end
end
@ -64,7 +64,7 @@ RSpec.configure do |config|
Capybara::SpecHelper.configure(config)
config.filter_run_excluding :full_description => lambda { |description, metadata|
config.filter_run_excluding full_description: lambda { |description, _metadata|
[
# test is marked pending in Capybara but Poltergeist passes - disable here - have our own test in driver spec
/Capybara::Session Poltergeist node #set should allow me to change the contents of a contenteditable elements child/,
@ -77,8 +77,8 @@ RSpec.configure do |config|
Poltergeist::SpecHelper.set_capybara_wait_time(0)
end
[:js, :modals, :windows].each do |cond|
config.before(:each, :requires => cond) do
%i[js modals windows].each do |cond|
config.before(:each, requires: cond) do
Poltergeist::SpecHelper.set_capybara_wait_time(1)
end
end
@ -87,4 +87,3 @@ end
def phantom_version_is?(ver_spec, driver)
Cliver.detect(driver.options[:phantomjs] || Capybara::Poltergeist::Client::PHANTOMJS_NAME, ver_spec)
end

View File

@ -4,10 +4,10 @@ require 'capybara/spec/test_app'
class TestApp
configure do
set :protection, :except => :frame_options
set :protection, except: :frame_options
end
POLTERGEIST_VIEWS = File.dirname(__FILE__) + "/views"
POLTERGEIST_PUBLIC = File.dirname(__FILE__) + "/public"
POLTERGEIST_VIEWS = File.dirname(__FILE__) + '/views'
POLTERGEIST_PUBLIC = File.dirname(__FILE__) + '/public'
helpers do
def requires_credentials(login, password)
@ -17,8 +17,8 @@ class TestApp
end
def authorized?(login, password)
@auth ||= Rack::Auth::Basic::Request.new(request.env)
@auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == [login, password]
@auth ||= Rack::Auth::Basic::Request.new(request.env)
@auth.provided? && @auth.basic? && @auth.credentials && (@auth.credentials == [login, password])
end
end
@ -57,12 +57,12 @@ class TestApp
get '/poltergeist/slow' do
sleep 0.2
"slow page"
'slow page'
end
get '/poltergeist/really_slow' do
sleep 3
"really slow page"
'really slow page'
end
get '/poltergeist/basic_auth' do
@ -77,7 +77,7 @@ class TestApp
get '/poltergeist/cacheable' do
cache_control :public, max_age: 60
etag "deadbeef"
etag 'deadbeef'
'Cacheable request'
end

View File

@ -19,7 +19,7 @@ module Capybara::Poltergeist
subject.command('where is', 'the love?')
expect(logger.string).to include('"name":"where is","args":["the love?"]')
expect(logger.string).to include("#{response}")
expect(logger.string).to include(response)
end
end
end

View File

@ -4,7 +4,7 @@ require 'spec_helper'
module Capybara::Poltergeist
describe Client do
let(:server) { double(port: 6000, host: "127.0.0.1") }
let(:server) { double(port: 6000, host: '127.0.0.1') }
let(:client_params) { {} }
subject { Client.new(server, client_params) }

View File

@ -23,22 +23,22 @@ module Capybara::Poltergeist
end
context 'with a phantomjs_options option' do
subject { Driver.new(nil, phantomjs_options: %w{--hello})}
subject { Driver.new(nil, phantomjs_options: %w[--hello]) }
it "is a combination of ssl settings and the provided options" do
expect(subject.phantomjs_options).to eq(%w{--hello --ignore-ssl-errors=yes --ssl-protocol=TLSv1})
it 'is a combination of ssl settings and the provided options' do
expect(subject.phantomjs_options).to eq(%w[--hello --ignore-ssl-errors=yes --ssl-protocol=TLSv1])
end
end
context 'with phantomjs_options containing ssl-protocol settings' do
subject { Driver.new(nil, phantomjs_options: %w{--ssl-protocol=any --ignore-ssl-errors=no})}
subject { Driver.new(nil, phantomjs_options: %w[--ssl-protocol=any --ignore-ssl-errors=no]) }
it "uses the provided ssl-protocol" do
it 'uses the provided ssl-protocol' do
expect(subject.phantomjs_options).to include('--ssl-protocol=any')
expect(subject.phantomjs_options).not_to include('--ssl-protocol=TLSv1')
end
it "uses the provided ssl-errors" do
it 'uses the provided ssl-errors' do
expect(subject.phantomjs_options).to include('--ignore-ssl-errors=no')
expect(subject.phantomjs_options).not_to include('--ignore-ssl-errors=yes')
end
@ -78,11 +78,11 @@ module Capybara::Poltergeist
end
it 'can pause indefinitely' do
expect {
Timeout::timeout(3) do
expect do
Timeout.timeout(3) do
subject.pause
end
}.to raise_error(Timeout::Error)
end.to raise_error(Timeout::Error)
end
it 'can pause and resume with keyboard input' do
@ -91,7 +91,7 @@ module Capybara::Poltergeist
write_io.write "\n"
begin
Timeout::timeout(3) do
Timeout.timeout(3) do
subject.pause
end
ensure
@ -102,11 +102,10 @@ module Capybara::Poltergeist
it 'can pause and resume with signal' do
Thread.new { sleep(2); Process.kill('CONT', Process.pid); }
Timeout::timeout(4) do
Timeout.timeout(4) do
subject.pause
end
end
end
context 'with a :timeout option' do