Using Cookies with Rack::Test - ruby

I'm trying to write RSpec tests for my Sinatra application using Rack::Test. I can't understand how I can use cookies. For example if my application set cookies (not via :session) how can I check whether that cookie is properly set?
Also, how can I send requests with that cookie?

Rack::Test keeps a cookie jar that persists over requests. You can access it with rack_mock_session.cookies. Let's say you have a handler like this:
get '/cookie/set' do
response.set_cookie "foo", :value => "bar"
end
Now you could test it with something like this:
it 'defines a cookie' do
get '/'
rack_mock_session.cookie_jar["foo"].should == "bar"
end
You can also access cookies with last_request.cookies, but as the name says, it contains the cookies for the last request, not the response. You can set cookies with set_cookie and clear them with clear_cookies.
it 'shows how to set a cookie' do
clear_cookies
set_cookie "foo=quux"
get '/'
last_request.cookies.should == {"foo" => "quux"}
end
Update: If you want the cookie jar to persist across the test cases (it blocks), you need to initialize the Rack session before executing any test cases. To do so, add this before hook to your describe block.
before :all do
clear_cookies
end
Alternative, you could for example use before :each to set up the necessary cookies before each request.

Related

How do I add custom logging for which route is satisfying a request in Sinatra?

I'm working on a Sinatra app that has a bunch of routes of all sorts. I'd like to add some custom logging that logs the params of the get or post call that ends up generating the response for the request. I realize I could subclass the get/post definition to wrap the block with a logging call. But I suspect there is a more appropriate approach.
You can use Sinatra's before hook in your controller, and print out some information contained on the request
before do
if request.request_method == :get || request.request_method == :post
puts request.path_info, params.inspect # check out the request variable for more info you might like to ouput
end
end

Sinatra: how to store params hash in a session?

enable :sessions
post '/sending_out' do
session[:data] = params.inspect
params.inspect
end
params.inspect contains exactly the hash I want to pass in a session variable. If I copy it from the output on a page and paste in here session[:data] = {hash-from-page}, my further code works fine.
What's going on? Isn't params a simple hash?
Sessions are disabled by default. You need to enable them and then use the session hash from routes and views.
This means your code is correct you just forget to enable sessions so just add:
configure do
enable :sessions
end

check duplication of cookies in Ruby

I am writing automated test scripts to check the duplication of cookies in Ruby. I am using the following code to obtain the value of a particular cookie.
browser = Capybara.current_session.driver.browser
cookie = browser.manage.cookie_named("__utma")
if cookie[:value].eql? $tracking_parameter
else
puts cookie[:value]
exit
end
I would like to know if the cookie __utma is present twice or duplicated, then how the code can be changed in order to test?

Sinatra app that redirects POST/GET requests with parameters

I'm migrating servers but unfortunately the old server IP is hardcoded inside my iPhone app. Obviously I'm going to submit an update that sets the API endpoint to my new server, but in the meantime I need to setup an app on the old server that redirects all the requests to the new server. I've heard Sinatra would be perfect for this.
require 'sinatra'
get "/foo/bar" do
redirect "http://new-server.com/foo/bar", 303
end
post "/foo/bar" do
redirect "http://new-server.com/foo/bar", 303
end
The problem is that these do not forward the GET or POST parameters along with the request. I read on the Sinatra doc that you can do that by putting them in the URL directly (works for GET requests), or by setting session variables.
Is manually parsing and formatting the GET params to put them back into the redirect URL the only way to go for GET redirects? How are you supposed to forward POST parameters?
For GET requests, use request.fullpath or request.query_string. For POST request, use status code 307, so the subsequent request will be a POST with the same parameters.
helpers do
def new_url
"http://new-server.com" + request.fullpath
end
end
get "/foo/bar" do
redirect new_url
end
post "/foo/bar" do
redirect new_url, 307
end
I would overload the Hash class in lib/overload_hash.rb, like so:
class Hash
def to_url_params
elements = []
keys.size.times do |i|
elements << "#{keys[i]}=#{values[i]}"
end
elements.join('&')
end
end
EDIT (Better solution using net / http)
Place a require "lib/overload_hash", require "net/http" and require "uri" under require 'sinatra'. The following example can be translated into GET easily.
post '/foo/bar' do
uri = URI.parse("http://example.com/search")
response = Net::HTTP.post_form(uri, params.to_ur_params)
response
end

Ruby Sinatra: Can I update a view template multiple times within one client request

I want to do this:
get '/test' do
#dog = 'WOOF'
erb :test
sleep(1)
#dog = 'BOWWOW'
erb :test
sleep(1)
#dog = 'ARF'
erb :test
end
Is it possible to do something like this where the client sees each update or no, I've tried but can't get it to work.
In short: no.
I think you're confusing the way HTTP works. First, HTTP is stateless. This means that multiple requests know nothing about each other (this is mitigated by the use of sessions via cookies, or possibly HTTP basic auth).
Further, you cannot resend the HTTP body like you're doing. Once it's sent there's no going back. Techniques like long-polling delay sending the body so they can send it whenever they like, but once they send something the request is complete and a new one must be started. Thus, once you've rendered the body once via erb, you're request is finished.
What it seems like you're trying to achieve can only be done via Javascript with AJAX, or with completely separate full-page requests.

Resources