Skip to content

Commit

Permalink
Add browser local/session storage option
Browse files Browse the repository at this point in the history
  • Loading branch information
twalpole committed Apr 1, 2017
1 parent cc5168b commit 9bf791f
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 23 deletions.
4 changes: 3 additions & 1 deletion lib/capybara.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class << self
attr_accessor :default_selector, :default_max_wait_time, :ignore_hidden_elements
attr_accessor :save_path, :wait_on_first_by_default, :automatic_label_click, :automatic_reload
attr_reader :reuse_server
attr_accessor :raise_server_errors, :server_errors
attr_accessor :raise_server_errors, :server_errors, :clear_storage_on_reset
attr_writer :default_driver, :current_driver, :javascript_driver, :session_name, :server_host
attr_reader :save_and_open_page_path
attr_accessor :exact_text
Expand Down Expand Up @@ -58,6 +58,7 @@ class << self
# [automatic_label_click = Boolean] Whether Node#choose, Node#check, Node#uncheck will attempt to click the associated label element if the checkbox/radio button are non-visible (Default: false)
# [enable_aria_label = Boolean] Whether fields, links, and buttons will match against aria-label attribute (Default: false)
# [reuse_server = Boolean] Reuse the server thread between multiple sessions using the same app object (Default: true)
# [clear_storage_on_reset = Boolean] Clear localStorage and sessionStorage when session is reset (Default: false)
# === DSL Options
#
# when using capybara/dsl, the following options are also available:
Expand Down Expand Up @@ -504,6 +505,7 @@ module Selenium; end
config.automatic_label_click = false
config.enable_aria_label = false
config.reuse_server = true
config.clear_storage_on_reset = false
end

Capybara.register_driver :rack_test do |app|
Expand Down
4 changes: 4 additions & 0 deletions lib/capybara/driver/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ def wait?
def reset!
end

def clear_storage
yield
end

def needs_server?
false
end
Expand Down
17 changes: 17 additions & 0 deletions lib/capybara/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ def pending_requests?
def call(env)
if env["PATH_INFO"] == "/__identify__"
[200, {}, [@app.object_id.to_s]]
elsif
env["PATH_INFO"] == "/__clear_storage__"
[200, {}, [ <<-HTML
<html>
<head>
<title>Clear Storage</title>
<script>
window.localStorage.clear();
window.sessionStorage.clear();
</script>
</head>
<body>
Clearing Storage
</body>
</html>
HTML
]]
else
@counter.increment
begin
Expand Down
57 changes: 36 additions & 21 deletions lib/capybara/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ def driver
#
def reset!
if @touched
clear_storage if @server && Capybara.clear_storage_on_reset
driver.reset!
@touched = false
end
Expand Down Expand Up @@ -231,27 +232,7 @@ def current_url
def visit(visit_uri)
raise_server_error!
@touched = true

visit_uri = URI.parse(visit_uri.to_s)

uri_base = if @server
visit_uri.port = @server.port if Capybara.always_include_port && (visit_uri.port == visit_uri.default_port)
URI.parse(Capybara.app_host || "http://#{@server.host}:#{@server.port}")
else
Capybara.app_host && URI.parse(Capybara.app_host)
end

# TODO - this is only for compatability with previous 2.x behavior that concatenated
# Capybara.app_host and a "relative" path - Consider removing in 3.0
# @abotalov brought up a good point about this behavior potentially being useful to people
# deploying to a subdirectory and/or single page apps where only the url fragment changes
if visit_uri.scheme.nil? && uri_base
visit_uri.path = uri_base.path + visit_uri.path
end

visit_uri = uri_base.merge(visit_uri) unless uri_base.nil?

driver.visit(visit_uri.to_s)
driver.visit(computed_uri(visit_uri).to_s)
end

##
Expand Down Expand Up @@ -845,6 +826,40 @@ def element_script_result(arg)
end
end

def computed_uri(visit_uri)
visit_uri = URI.parse(visit_uri.to_s)

uri_base = if @server
visit_uri.port = @server.port if Capybara.always_include_port && (visit_uri.port == visit_uri.default_port)
URI.parse(Capybara.app_host || "http://#{@server.host}:#{@server.port}")
else
Capybara.app_host && URI.parse(Capybara.app_host)
end

# TODO - this is only for compatability with previous 2.x behavior that concatenated
# Capybara.app_host and a "relative" path - Consider removing in 3.0
# @abotalov brought up a good point about this behavior potentially being useful to people
# deploying to a subdirectory and/or single page apps where only the url fragment changes
if visit_uri.scheme.nil? && uri_base
visit_uri.path = uri_base.path + visit_uri.path
end

visit_uri = uri_base.merge(visit_uri) unless uri_base.nil?
visit_uri
end

def clear_storage
if
begin
driver.clear_storage do
driver.visit(computed_uri("/__clear_storage__"))
end
rescue => e
warn "Session storage may not have been cleared due to #{e.message}"
end
end
end

def _find_frame(*args)
within(document) do # Previous 2.x versions ignored current scope when finding frames - consider changing in 3.0
case args[0]
Expand Down
15 changes: 15 additions & 0 deletions lib/capybara/spec/session/reset_session_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,19 @@
@session.visit("/")
expect(@session.current_path).to eq("/")
end

context "Capybara.clear_storage_on_reset" do
it "resets storage when true", requires: [:server] do
Capybara.clear_storage_on_reset = true
@session.visit("/set_storage")
expect(@session.evaluate_script(
"[window.localStorage.getItem('capybara'), window.sessionStorage.getItem('capybara_unload')]"
)).to eq ['42', '42']
@session.reset!
@session.visit("/")
expect(@session.evaluate_script(
"[window.localStorage.getItem('capybara'), window.sessionStorage.getItem('capybara_unload')]"
)).to eq [nil, nil]
end
end
end
1 change: 1 addition & 0 deletions lib/capybara/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def reset!
Capybara.match = :smart
Capybara.wait_on_first_by_default = false
Capybara.enable_aria_label = false
Capybara.clear_storage_on_reset = true
end

def filter(requires, metadata)
Expand Down
18 changes: 18 additions & 0 deletions lib/capybara/spec/views/set_storage.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<html>
<head>
<script>
window.localStorage.setItem("capybara", 42);
window.sessionStorage.setItem("capybara", 42);
window.localStorage.setItem("capybara_unload", 42);
window.sessionStorage.setItem("capybara_unload", 42);

window.onbeforeunload = function(e) {
window.localStorage.setItem("capybara_unload", 43);
window.sessionStorage.setItem("capybara_unload", 43);
};
</script>
</head>
<body>
<div>This sets storage</div>
</body>
</html>
6 changes: 6 additions & 0 deletions spec/selenium_spec_chrome.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ module TestSessions

context "storage" do
describe "#reset!" do
before do
# TODO: remove these tests
# only test the driver resetting
Capybara.clear_storage_on_reset = false
end

it "does not clear either storage by default" do
@session = TestSessions::Chrome
@session.visit('/with_js')
Expand Down
8 changes: 7 additions & 1 deletion spec/selenium_spec_marionette.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Capybara::Selenium::Driver.new(
app,
browser: :firefox,
desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: true)
desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: true),
)
end

Expand Down Expand Up @@ -89,6 +89,12 @@ module TestSessions

context "storage" do
describe "#reset!" do
before do
# TODO: remove these tests
# only test the driver resetting
Capybara.clear_storage_on_reset = false
end

it "does not clear either storage by default" do
@session = TestSessions::SeleniumMarionette
@session.visit('/with_js')
Expand Down

0 comments on commit 9bf791f

Please sign in to comment.