Compare commits

..

8 Commits

Author SHA1 Message Date
John Bintz f698dc7bda Bump version 2015-02-23 14:26:29 -05:00
John Bintz a83023b812 Chrome switch fixes 2015-02-23 14:26:12 -05:00
John Bintz b217fef4ee Add @frame_handles for iframe support 2015-02-23 14:26:00 -05:00
John Bintz 21a622ace0 Bump minor version 2015-01-09 15:06:03 -05:00
John Bintz 2034c864f3 Fixes for modern Capybara versions. 2015-01-09 15:05:44 -05:00
John Bintz ad5d5c5d05 Split up Cucumber and RSpec support 2015-01-09 15:05:05 -05:00
John Bintz e738bab0f4 improve chrome support, add chrome extension option, as well as project dotfile support 2013-08-14 12:08:40 -04:00
John Bintz f6bfa0cf29 add timeout option 2013-05-14 10:57:55 -04:00
8 changed files with 96 additions and 9 deletions

View File

@ -1,3 +1,5 @@
# Persistent Selenium
Now you can keep that precious browser window open when doing continuous integration testing. Now you can keep that precious browser window open when doing continuous integration testing.
Save seconds, and sanity, with every test re-run! Save seconds, and sanity, with every test re-run!
@ -7,7 +9,7 @@ fix your tests and/or code.
Start an instance: Start an instance:
``` bash ``` bash
persistent_selenium [ --port 9854 ] [ --browser firefox ] persistent_selenium [ --port 9854 ] [ --browser firefox ] [ --chrome-extensions <file.crx> ... ]
``` ```
Tell Capybara to use it: Tell Capybara to use it:
@ -36,11 +38,45 @@ these two differences:
The browser's cache is disabled, and cookies are reset before the next test runs, so you still get the state The browser's cache is disabled, and cookies are reset before the next test runs, so you still get the state
cleared out before your next set of tests. cleared out before your next set of tests.
### Under the hood ### .persistent_selenium
Configure everything in your app with a `.persistent_selenium` file:
``` ruby
# .persistent_selenium
PersistentSelenium.configure do |c|
c.browser = :chrome
c.chrome_extensions = %w{AngularJS-Batarang.crx}
end
```
### Chrome Extensions
If, for example, you do a lot with AngularJS and want to use [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en),
download the extension, put it in your project's folder somewhere, and call `persistent_selenium` with the path
to the extension:
``` bash
persistent_selenium --browser chrome --chrome-extensions AngularJS-Batarang.crx
```
## Best practice
Use it with Foreman and Guard. Start up your test suite via Guard, configure your test suite to
use persistent_selenium, and run persistent_selenium alongside it:
``` yaml
guard: guard -g wip
ps: persistent_selenium
```
It's an integral part of my [integration testing setup](http://github.com/johnbintz/bintz-integration_testing_setup).
## Under the hood
It's DRb, which mostly Just Works (tm), and has a little reshuffling of the default Capybara Selenium driver's code. It's DRb, which mostly Just Works (tm), and has a little reshuffling of the default Capybara Selenium driver's code.
#### When DRb doesn't Just Work (tm) ### When DRb doesn't Just Work (tm)
You're most likely using `all` and invoking an action on one of the nodes within, I'd wager. If you need to find a node You're most likely using `all` and invoking an action on one of the nodes within, I'd wager. If you need to find a node
to perform an action on, it's best to stick with `find`, since it's less likely that node will go out of to perform an action on, it's best to stick with `find`, since it's less likely that node will go out of

View File

@ -2,6 +2,10 @@
$: << File.expand_path('../../lib', __FILE__) $: << File.expand_path('../../lib', __FILE__)
require 'persistent_selenium'
PersistentSelenium.load_dotfile
require 'persistent_selenium/cli' require 'persistent_selenium/cli'
GC.disable GC.disable

View File

@ -3,7 +3,7 @@ require 'selenium-webdriver'
module PersistentSelenium module PersistentSelenium
class << self class << self
attr_writer :port, :browser attr_writer :port, :browser, :timeout, :chrome_extensions
def port def port
@port ||= 9854 @port ||= 9854
@ -13,6 +13,14 @@ module PersistentSelenium
@browser ||= :firefox @browser ||= :firefox
end end
def timeout
@timeout ||= 120
end
def chrome_extensions
@chrome_extensions ||= []
end
def url def url
"druby://localhost:#{port}" "druby://localhost:#{port}"
end end
@ -20,5 +28,11 @@ module PersistentSelenium
def configure def configure
yield self yield self
end end
def load_dotfile(file = '.persistent_selenium')
if File.file?(file)
load file
end
end
end end
end end

View File

@ -6,6 +6,7 @@ module PersistentSelenium
class Browser < Capybara::Selenium::Driver class Browser < Capybara::Selenium::Driver
def initialize(browser_type) def initialize(browser_type)
@browser_type = browser_type.to_s.to_sym @browser_type = browser_type.to_s.to_sym
@frame_handles = {}
@__found_elements__ = [] @__found_elements__ = []
end end
@ -20,7 +21,13 @@ module PersistentSelenium
options = { :profile => profile } options = { :profile => profile }
when :chrome when :chrome
options = { :switches => %w{--disk-cache-size=1 --media-cache-size=1} } switches = %w{--disk-cache-size=1 --media-cache-size=1}
PersistentSelenium.chrome_extensions.each do |extension|
switches.push("--load-extension=#{extension}")
end
options = { switches: switches }
end end
@browser ||= Selenium::WebDriver.for(@browser_type, options) @browser ||= Selenium::WebDriver.for(@browser_type, options)

View File

@ -10,14 +10,19 @@ module PersistentSelenium
end end
desc "start", "Start the server" desc "start", "Start the server"
method_options :port => PersistentSelenium.port, :browser => PersistentSelenium.browser method_options :port => PersistentSelenium.port,
:browser => PersistentSelenium.browser,
:timeout => PersistentSelenium.timeout
method_option :chrome_extensions, :type => :array, :default => []
def start def start
require 'persistent_selenium/browser' require 'persistent_selenium/browser'
require 'drb' require 'persistent_selenium/drb'
PersistentSelenium.configure do |c| PersistentSelenium.configure do |c|
c.port = options[:port] c.port = options[:port]
c.browser = options[:browser] c.browser = options[:browser] if options[:browser]
c.timeout = options[:timeout]
c.chrome_extensions = options[:chrome_extensions] if !options[:chrome_extensions].empty?
end end
puts "Starting persistent_selenium on #{PersistentSelenium.port} with #{PersistentSelenium.browser}" puts "Starting persistent_selenium on #{PersistentSelenium.port} with #{PersistentSelenium.browser}"

View File

@ -0,0 +1,17 @@
require 'drb'
module DRb
class DRbTCPSocket
alias :_set_sockopt :set_sockopt
def set_sockopt(soc)
_set_sockopt(soc)
optval = [ PersistentSelenium.timeout, 0 ].pack("l_2")
soc.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
soc.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
end
end
end

View File

@ -1,9 +1,12 @@
require 'persistent_selenium' require 'persistent_selenium'
require 'persistent_selenium/browser'
require 'capybara/selenium/driver' require 'capybara/selenium/driver'
# make sure these classes exist on this end # make sure these classes exist on this end
[ Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::UnhandledError, Selenium::WebDriver::Error::ElementNotVisibleError ] [ Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::UnhandledError, Selenium::WebDriver::Error::ElementNotVisibleError ]
require 'persistent_selenium/drb'
Capybara.register_driver :persistent_selenium do |app| Capybara.register_driver :persistent_selenium do |app|
require 'drb' require 'drb'
@ -16,6 +19,7 @@ Capybara.register_driver :persistent_selenium do |app|
end end
DRb.start_service DRb.start_service
browser = DRbObject.new nil, PersistentSelenium.url browser = DRbObject.new nil, PersistentSelenium.url
server = Capybara::Server.new(app) server = Capybara::Server.new(app)

View File

@ -1,3 +1,3 @@
module PersistentSelenium module PersistentSelenium
VERSION = "0.0.2" VERSION = "0.1.1"
end end