title: Setting Cookies with Poltergeist PhantomJS Capybara Driver
body: <p>I'm running to issues attempting to set cookies using the Poltergeist gem, and from reading through the closed issues at the Poltergeist gem, it appears this is a user error issue on my part, but I've spent a full day now on attempting to get the cookies set properly, and I can't seem to set things up properly.</p>
  
  <p>Note: This test works fine in selenium, but I'd like to use poltergeist due to run time issues with selenium.</p>
  
  <p>The application I'm working on is using "_location" cookie to determine some overall settings, and I need to have the cookie accessible on my first visit of any page in the application. Otherwise I get a javascript error looking for a value that is not set due to the location not being set.</p>
  
  <p><a href="https://github.com/jonleighton/poltergeist" rel="nofollow">The README for the Poltergeist gem</a> shows the following usage for cookies</p>
  
  <p>Manipulating cookies</p>
  
  <p>The following methods are used to inspect and manipulate cookies:</p>
  
  <p><code>page.driver.cookies</code> - a hash of cookies accessible to the current page. The keys are cookie names. The values are Cookie objects, with the following methods: <code>name</code>, <code>value</code>, <code>domain</code>, <code>path</code>, <code>secure?</code>, <code>httponly?</code>, <code>expires</code>.</p>
  
  <p><code>page.driver.set_cookie(name, value, options = {})</code> - set a cookie. The options hash can take the following keys: <code>:domain</code>, <code>:path</code>, <code>:secure</code>, <code>:httponly</code>, <code>:expires</code>. <code>:expires</code> should be a Time object.</p>
  
  <p><code>page.driver.remove_cookie(name)</code> - remove a cookie</p>
  
  <p>-- specs/spec_helper.rb</p>
  
  <pre><code>Capybara.register_driver :poltergeist do |app|
    Capybara::Poltergeist::Driver.new(app, :debug =&gt; true)
  end
  
  Capybara.javascript_driver = :poltergeist
  </code></pre>
  
  <p>-- views/admin/article/new.html.haml</p>
  
  <pre><code>= link_to_function "test js", '$(this).html("js works")'
  </code></pre>
  
  <p>-- specs/requests/article_products_spec.rb</p>
  
  <pre><code>require 'spec_helper'
  
  describe "Associating Articles with Products and Product Categories" do
  
    before (:all) do
      @user = create(:user, role: "admin")
      5.times { create(:product_category) }
      @product_categories = ProductCategory.all
      @product_categories.each do |pc|
        4.times { create(:product, product_category: pc) }
      end
    end
  
    before (:each) do
      visit new_user_session_path
      page.driver.set_cookie("_location", "US")
      page.driver.cookies
      fill_in "Username Or Email", with: @user.email
      fill_in "Password", with: @user.password
      click_button "Sign In"
      visit new_admin_article_path
    end
  
    it "supports js", :js =&gt; true do
      click_link "test js"
      page.should have_content("js works")
    end
  
  end
  </code></pre>
  
  <p>test response</p>
  
  <pre><code>{"name"=&gt;"visit", "args"=&gt;["http://127.0.0.1:64554/users/sign_in"]}
  {"error"=&gt;{"name"=&gt;"Poltergeist.JavascriptError", "args"=&gt;[[{"message"=&gt;"TypeError: 'null' is not an object (evaluating 'response.custentitydefault_shipping_location')", "stack"=&gt;"TypeError: 'null' is not an object (evaluating 'response.custentitydefault_shipping_location')\n    at http://127.0.0.1:64554/assets/non_deferred.js:12338\n    at http://127.0.0.1:64554/assets/non_deferred.js:1076\n    at http://127.0.0.1:64554/assets/non_deferred.js:1194\n    at http://127.0.0.1:64554/assets/non_deferred.js:7539 in done\n    at http://127.0.0.1:64554/assets/non_deferred.js:8325"}]]}}
  {"name"=&gt;"reset", "args"=&gt;[]}
  {"response"=&gt;true}
  F
  
  Failures:
  
    1) Associating Articles with Products and Product Categories supports js
       Failure/Error: visit new_user_session_path
       Capybara::Poltergeist::JavascriptError:
         One or more errors were raised in the Javascript code on the page:
  
         TypeError: 'null' is not an object (evaluating 'response.custentitydefault_shipping_location')
             at http://127.0.0.1:64554/assets/non_deferred.js:12338
             at http://127.0.0.1:64554/assets/non_deferred.js:1076
             at http://127.0.0.1:64554/assets/non_deferred.js:1194
             at http://127.0.0.1:64554/assets/non_deferred.js:7539 in done
             at http://127.0.0.1:64554/assets/non_deferred.js:8325
       # ./spec/requests/article_products_spec.rb:15:in `block (2 levels) in &lt;top (required)&gt;'
       # ./spec/support/vcr.rb:14:in `block (2 levels) in &lt;top (required)&gt;'
  </code></pre>
  
  <p>With this failure, I thought perhaps I should be setting the cookies before visiting the page, however it appears that when I use the page.driver.set_cookie command before I use "visit" in my Capybara scripts, it doesn't actually set anything. As seen from this modified code block and this result set.</p>
  
  <p>-- specs/requests/article_products_spec.rb</p>
  
  <pre><code>describe "Associating Articles with Products and Product Categories" do
  
    before (:all) do
      @user = create(:user, role: "admin")
      5.times { create(:product_category) }
      @product_categories = ProductCategory.all
      @product_categories.each do |pc|
        4.times { create(:product, product_category: pc) }
      end
    end
  
    before (:each) do
      page.driver.set_cookie("_location", "US")
      page.driver.cookies
      visit new_user_session_path
      fill_in "Username Or Email", with: @user.email
      fill_in "Password", with: @user.password
      click_button "Sign In"
      visit new_admin_article_path
    end
  
    it "supports js", :js =&gt; true do
      click_link "test js"
      page.should have_content("js works")
    end
  end
  </code></pre>
  
  <p>test response</p>
  
  <pre><code>{"name"=&gt;"set_cookie", "args"=&gt;[{:name=&gt;"_location", :value=&gt;"US", :domain=&gt;"127.0.0.1"}]}
  {"response"=&gt;true}
  {"name"=&gt;"cookies", "args"=&gt;[]}
  {"response"=&gt;[]}
  {"name"=&gt;"visit", "args"=&gt;["http://127.0.0.1:64090/users/sign_in"]}
  {"error"=&gt;{"name"=&gt;"Poltergeist.JavascriptError", "args"=&gt;[[{"message"=&gt;"TypeError: 'null' is not an object (evaluating 'response.custentitydefault_shipping_location')", "stack"=&gt;"TypeError: 'null' is not an object (evaluating 'response.custentitydefault_shipping_location')\n    at http://127.0.0.1:64090/assets/non_deferred.js:12338\n    at http://127.0.0.1:64090/assets/non_deferred.js:1076\n    at http://127.0.0.1:64090/assets/non_deferred.js:1194\n    at http://127.0.0.1:64090/assets/non_deferred.js:7539 in done\n    at http://127.0.0.1:64090/assets/non_deferred.js:8325"}]]}}
  {"name"=&gt;"reset", "args"=&gt;[]}
  {"response"=&gt;true}
  F
  
  Failures:
  
    1) Associating Articles with Products and Product Categories supports js
       Failure/Error: visit new_user_session_path
       Capybara::Poltergeist::JavascriptError:
         One or more errors were raised in the Javascript code on the page:
  
         TypeError: 'null' is not an object (evaluating 'response.custentitydefault_shipping_location')
             at http://127.0.0.1:64554/assets/non_deferred.js:12338
             at http://127.0.0.1:64554/assets/non_deferred.js:1076
             at http://127.0.0.1:64554/assets/non_deferred.js:1194
             at http://127.0.0.1:64554/assets/non_deferred.js:7539 in done
             at http://127.0.0.1:64554/assets/non_deferred.js:8325
       # ./spec/requests/article_products_spec.rb:15:in `block (2 levels) in &lt;top (required)&gt;'
       # ./spec/support/vcr.rb:14:in `block (2 levels) in &lt;top (required)&gt;'
  </code></pre>
  
  <p>I've also attempted to pass in a phantomjs_options block to the poltergeist driver, with an external cookies file. That actually appeared to get me a bit farther, but I ended up with a null cookie_jar. You can see this attempt below:</p>
  
  <p>--spec/spec_helper.rb</p>
  
  <pre><code>  Capybara.register_driver :poltergeist do |app|
      Capybara::Poltergeist::Driver.new(app, [phantomjs_options: [--cookies-file="#{::Rails.root}/spec/requests/cookies.txt"]] )
    end
  
    Capybara.javascript_driver = :poltergeist
  </code></pre>
  
  <p>-- cookies.txt</p>
  
  <pre><code>phantom.addCookie({
      'name':     '_location',
      'value':    'US',
      'domain':   'localhost',
      'expires':  (new Date()).getTime() + 3600
  });
  </code></pre>
  
  <p>test response
      F</p>
  
  <pre><code>Failures:
  
    1) Associating Articles with Products and Product Categories supports js
       Failure/Error: visit new_user_session_path
       NoMethodError:
         undefined method `cookie_jar' for nil:NilClass
       # ./spec/requests/article_products_spec.rb:15:in `block (2 levels) in &lt;top (required)&gt;'
       # ./spec/support/vcr.rb:14:in `block (2 levels) in &lt;top (required)&gt;'
  
  Finished in 2.42 seconds
  1 example, 1 failure
  </code></pre>