Class RackBox
In: lib/rackbox/spec/helpers.rb
lib/rackbox/app.rb
lib/rackbox/rackbox.rb
lib/rackbox/matchers.rb
Parent: Object

To add blackbox testing to a Rails app, in your spec_helper.rb

  require 'rackbox'

  Spec::Runner.configure do |config|
    config.use_blackbox = true
  end

Methods

app   build_query   req  

Classes and Modules

Module RackBox::Matchers
Module RackBox::SpecHelpers
Class RackBox::App

External Aliases

req -> request

Attributes

app  [RW]  the Rack appliction to do ‘Black Box’ testing against

To set, in your spec_helper.rb or someplace:

  RackBox.app = Rack::Adapter::Rails.new :root => '/root/directory/of/rails/app', :environment => 'test'

If not explicitly set, uses RAILS_ROOT (if defined?) and RAILS_ENV (if defined?)

verbose  [RW]  to turn on some verbosity / logging, set:
  RackBox.verbose = true

Public Class methods

[Source]

     # File lib/rackbox/rackbox.rb, line 97
 97:     def app
 98:       unless @app and @app.respond_to?:call
 99:         if File.file? 'config.ru'
100:           @app = Rack::Builder.new { eval(File.read('config.ru')) }
101:         elsif defined?RAILS_ENV and defined?RAILS_ROOT
102:           raise "You need the Rack::Adapter::Rails to run Rails apps with RackBox." + 
103:                 " Try: sudo gem install thin" unless defined?Rack::Adapter::Rails
104:           @app = Rack::Adapter::Rails.new :root => RAILS_ROOT, :environment => RAILS_ENV
105:         else
106:           raise "RackBox.app not configured."
107:         end
108:       end
109:       @app
110:     end

helper method for taking a Hash of params and turning them into POST params

>> RackBox.build_query :hello => ‘there‘

> ‘hello=there‘

>> RackBox.build_query :hello => ‘there’, :foo => ‘bar‘

> ‘hello=there&foo=bar‘

>> RackBox.build_query :user => { :name => ‘bob’, :password => ‘secret’ }

> ‘user[name]=bob&user[password]=secret‘

[Source]

     # File lib/rackbox/rackbox.rb, line 123
123:     def build_query params_hash = { }
124:       # check to make sure no values are Hashes ...
125:       # if they are, we need to flatten them!
126:       params_hash.each do |key, value|
127:         # params_hash  :a => { :b => X, :c => Y }
128:         # needs to be  'a[b]' => X, 'a[b]' => Y
129:         if value.is_a? Hash
130:           inner_hash = params_hash.delete key # { :b => X, :c => Y }
131:           inner_hash.each do |subkey, subvalue|
132:             new_key = "#{ key }[#{ subkey }]" # a[b] or a[c]
133:             puts "warning: overwriting query parameter #{ new_key }" if params_hash[new_key]
134:             params_hash[new_key] = subvalue # 'a[b]' => X or a[c] => Y
135:           end
136:           # we really shouldn't keep going thru the #each now that we've altered data!
137:           return build_query(params_hash)
138:         end
139:       end
140:       Rack::Utils.build_query params_hash
141:     end

A port of Merb‘s request() method, used in tests

At the moment, we‘re using req instead because request conflicts with an existing RSpec-Rails method

Usage:

  req '/'
  req login_path
  req url_for(:controller => 'login')

  req '/', :method => :post, :params => { 'chunky' => 'bacon' }

  req '/', :data => "some XML data to POST"

TODO take any additional options and pass them along to the environment, so we can say

     req '/', :user_agent => 'some custom user agent'

[Source]

    # File lib/rackbox/rackbox.rb, line 38
38:     def req app_or_request, url = nil, options = {}
39:       puts "RackBox#request url:#{ url.inspect }, options:#{ options.inspect }" if RackBox.verbose
40: 
41:       # handle RackBox.request '/foo'
42:       if app_or_request.is_a?(String) && ( url.nil? || url.is_a?(Hash) )
43:         options        = url || {}
44:         url            = app_or_request
45:         app_or_request = RackBox.app
46:       end
47: 
48:       # need to find the request or app
49:       mock_request = nil
50:       if app_or_request.is_a? Rack::MockRequest
51:         mock_request = app_or_request
52:       elsif app_or_request.nil?
53:         if RackBox.app.nil?
54:           raise "Not sure howto to execute a request against app or request: #{ app_or_request.inspect }"
55:         else
56:           mock_request = Rack::MockRequest.new(RackBox.app) # default to RackBox.app if nil
57:         end
58:       elsif app_or_request.respond_to? :call
59:         mock_request = Rack::MockRequest.new(app_or_request)
60:       else
61:         raise "Not sure howto to execute a request against app or request: #{ app_or_request.inspect }"
62:       end
63: 
64:       options[:method] ||= ( options[:params] || options[:data] ) ? :post : :get # if params, default to POST, else default to GET
65:       options[:params] ||= { }
66: 
67:       if options[:data]
68:         # input should be the data we're likely POSTing ... this overrides any params
69:         input = options[:data]
70:       else
71:         # input should be params, if any
72:         input = RackBox.build_query options[:params]
73:       end
74: 
75:       headers = options.dup
76:       headers.delete :data   if headers[:data]
77:       headers.delete :params if headers[:params]
78:       headers.delete :method if headers[:method]
79:       
80:       # merge input
81:       headers[:input] = input
82:       
83:       puts "  requesting #{ options[:method].to_s.upcase } #{ url.inspect } #{ headers.inspect }" if RackBox.verbose
84:       mock_request.send options[:method], url, headers
85:     end

[Validate]