Module: Gin::Test::Helpers

Includes:
Assertions
Defined in:
lib/gin/test.rb

Overview

Helper methods for tests. To contextualize tests to a specific app, use the automatically generated module assigned to your app’s class:

class MyCtrlTest < Test::Unit::TestCase
  include MyApp::TestHelper     # Sets App for mock requests.
  controller MyHomeController   # Sets default controller to use.

  def test_home
    get :home
    assert_response :success
  end
end

All requests are full stack, meaning any in-app middleware will be run as a part of a request. The goal is to test controllers in the context of the whole app, and easily do integration-level tests as well.

Constant Summary collapse

/\A([^(),\/<>@;:\\\"\[\]?={}\s]+)(?:=([^;]*))?\Z/

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Assertions

#assert_cookie, #assert_css, #assert_data, #assert_layout, #assert_redirect, #assert_response, #assert_route, #assert_select, #assert_view, #assert_xpath

Class Method Details

.setup_klass(subclass) ⇒ Object

:nodoc:



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/gin/test.rb', line 279

def self.setup_klass subclass   # :nodoc:
  return if subclass.respond_to?(:app_klass)

  subclass.instance_eval do
    def app_klass klass=nil
      @app_klass = klass if klass
      defined?(@app_klass) && @app_klass
    end


    ##
    # Sets the default controller to use when making requests
    # for all tests in the given class.
    #   class MyCtrlTest < Test::Unit::TestCase
    #     include MyApp::TestHelper
    #     controller MyCtrl
    #   end

    def controller ctrl_klass=nil
      @default_controller = ctrl_klass if ctrl_klass
      defined?(@default_controller) && @default_controller
    end
  end
end

Instance Method Details

#appObject

The App instance being used for the requests.



320
321
322
# File 'lib/gin/test.rb', line 320

def app
  @app ||= self.class.app_klass.new
end

#bodyObject

The read String body of the response.



571
572
573
574
575
576
# File 'lib/gin/test.rb', line 571

def body
  return @body if defined?(@body) && @body
  @body = ""
  rack_response[2].each{|str| @body << str }
  @body
end

#controllerObject

The Gin::Controller instance used by the last mock request.



344
345
346
# File 'lib/gin/test.rb', line 344

def controller
  defined?(@controller) && @controller
end

#cookiesObject

Cookies assigned to the response. Will not show expired cookies, but cookies will otherwise persist across multiple requests in the same test case.

cookies['session']
#=> {:value => "foo", :expires => <#Time>}


506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'lib/gin/test.rb', line 506

def cookies
  return @cookies if defined?(@cookie_key) &&
                      @cookie_key == rack_response[1]['Set-Cookie']

  @response_cookies = {}

  Array(rack_response[1]['Set-Cookie']).each do |set_cookie_value|
    args = { }
    params=set_cookie_value.split(/;\s*/)

    first=true
    params.each do |param|
      result = COOKIE_MATCH.match param
      if !result
        raise "Invalid cookie parameter in cookie '#{set_cookie_value}'"
      end

      key = result[1].downcase.to_sym
      keyvalue = result[2]
      if first
        args[:name] = result[1]
        args[:value] = CGI.unescape(keyvalue.to_s)
        first = false
      else
        case key
        when :expires
          begin
            args[:expires_at] = Time.parse keyvalue
          rescue ArgumentError
            raise unless $!.message == "time out of range"
            args[:expires_at] = Time.at(0x7FFFFFFF)
          end
        when *[:domain, :path]
          args[key] = keyvalue
        when :secure
          args[:secure] = true
        when :httponly
          args[:http_only] = true
        else
          raise "Unknown cookie parameter '#{key}'"
        end
      end
    end

    @response_cookies[args[:name]] = args
  end

  @cookie_key = rack_response[1]['Set-Cookie']
  (@cookies ||= {}).merge!(@response_cookies)
  @cookies
end

#default_controller(ctrl_klass = nil) ⇒ Object

Sets the default controller to use when making requests. Best used in a test setup context.

def setup
  default_controller HomeController
end


636
637
638
639
# File 'lib/gin/test.rb', line 636

def default_controller ctrl_klass=nil
  @default_controller = ctrl_klass if ctrl_klass
  defined?(@default_controller) && @default_controller || self.class.controller
end

#delete(*args) ⇒ Object

Make a DELETE request. See ‘get’ method for usage.



419
420
421
# File 'lib/gin/test.rb', line 419

def delete *args
  make_request :delete, *args
end

#envObject

The Rack env for the next mock request.



328
329
330
# File 'lib/gin/test.rb', line 328

def env
  @env ||= {'rack.input' => ""}
end

#get(*args) ⇒ Object

Make a GET request.

get FooController, :show, :id => 123

# With default_controller set to FooController
get :show, :id => 123

# Default named route
get :show_foo, :id => 123

# Request with headers
get :show_foo, {:id => 123}, 'Cookie' => 'value'
get :show_foo, {}, 'Cookie' => 'value'


387
388
389
# File 'lib/gin/test.rb', line 387

def get *args
  make_request :get, *args
end

#head(*args) ⇒ Object

Make a HEAD request. See ‘get’ method for usage.



427
428
429
# File 'lib/gin/test.rb', line 427

def head *args
  make_request :head, *args
end

#make_request(verb, *args) ⇒ Object

Make a mock request to the given http verb and path, controller+action, or named route.

make_request :get, FooController, :show, :id => 123

# With default_controller set to FooController
make_request :get, :show, :id => 123

# Default named route
make_request :get, :show_foo, :id => 123

# Request with headers
make_request :get, :show_foo, {:id => 123}, 'Cookie' => 'value'
make_request :get, :show_foo, {}, 'Cookie' => 'value'


456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'lib/gin/test.rb', line 456

def make_request verb, *args
  headers = (Hash === args[-2] && Hash === args[-1]) ? args.pop : {}
  path, query = path_to(*args).split("?")

  env['HTTP_COOKIE'] = @set_cookies.map{|k,v| "#{k}=#{v}"}.join("; ") if
    defined?(@set_cookies) && @set_cookies && !@set_cookies.empty?

  env['REQUEST_METHOD'] = verb.to_s.upcase
  env['QUERY_STRING']   = query
  env['PATH_INFO']      = path

  host, port = (app.hostname || "localhost").split(":")
  env['SERVER_NAME'] = host
  env['SERVER_PORT'] = port || '80'
  env.merge! headers

  @rack_response = app.call(env)
  @controller    = env[Gin::Constants::GIN_CTRL]
  @templates     = env[Gin::Constants::GIN_TEMPLATES]

  @env         = nil
  @body        = nil
  @parsed_body = nil
  @set_cookies = nil

  cookies.each{|n, c| set_cookie(n, c[:value]) }

  @rack_response
end

#options(*args) ⇒ Object

Make a OPTIONS request. See ‘get’ method for usage.



435
436
437
# File 'lib/gin/test.rb', line 435

def options *args
  make_request :options, *args
end

#parsed_bodyObject

The data representing the parsed String body of the response, according to the Content-Type.

Supports JSON, BSON, XML, PLIST, and HTML. Returns plain Ruby objects for JSON, BSON, and PLIST. Returns a Nokogiri document object for XML and HTML.



587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
# File 'lib/gin/test.rb', line 587

def parsed_body
  return @parsed_body if defined?(@parsed_body) && @parsed_body
  ct = rack_response[1]['Content-Type']

  @parsed_body =
    case ct
    when /[\/+]json/i
      use_lib 'json'
      JSON.parse(body)

    when /[\/+]bson/i
      use_lib 'bson'
      BSON.deserialize(body)

    when /[\/+]plist/i
      use_lib 'plist'
      Plist.parse_xml(body)

    when /[\/+]xml/i
      use_lib 'nokogiri'
      Nokogiri::XML(body)

    when /[\/+]html/i
      use_lib 'nokogiri'
      Nokogiri::HTML(body)

    else
      raise "No parser available for content-type #{ct.inspect}"
    end
end

#patch(*args) ⇒ Object

Make a PATCH request. See ‘get’ method for usage.



411
412
413
# File 'lib/gin/test.rb', line 411

def patch *args
  make_request :patch, *args
end

#path_to(*args) ⇒ Object

Build a path to the given controller and action or route name, with any expected params. If no controller is specified and the default controller responds to the symbol given, uses the default controller for path lookup.

path_to FooController, :show, :id => 123
#=> "/foo/123"

# With default_controller set to FooController
path_to :show, :id => 123
#=> "/foo/123"

# Default named route
path_to :show_foo, :id => 123
#=> "/foo/123"


659
660
661
662
663
664
665
666
667
# File 'lib/gin/test.rb', line 659

def path_to *args
  return "#{args[0]}#{"?" << Gin.build_query(args[1]) if args[1]}" if String === args[0]

  args.unshift(@default_controller) if
    Symbol === args[0] && defined?(@default_controller) &&
       @default_controller && @default_controller.actions.include?(args[0])

  app.router.path_to(*args)
end

#post(*args) ⇒ Object

Make a POST request. See ‘get’ method for usage.



395
396
397
# File 'lib/gin/test.rb', line 395

def post *args
  make_request :post, *args
end

#put(*args) ⇒ Object

Make a PUT request. See ‘get’ method for usage.



403
404
405
# File 'lib/gin/test.rb', line 403

def put *args
  make_request :put, *args
end

#rack_responseObject

The standard Rack response array.



336
337
338
# File 'lib/gin/test.rb', line 336

def rack_response
  @rack_response ||= [nil,{},[]]
end

#requestObject

The Gin::Request instance on the controller used by the last mock request.



352
353
354
# File 'lib/gin/test.rb', line 352

def request
  controller && controller.request
end

#responseObject

The Gin::Response instance on the controller used by the last mock request.



360
361
362
# File 'lib/gin/test.rb', line 360

def response
  controller && controller.response
end

#response_cookiesObject

Cookies assigned by the last response.



562
563
564
565
# File 'lib/gin/test.rb', line 562

def response_cookies
  cookies unless defined?(@response_cookies)
  @response_cookies ||= {}
end

Sets a cookie for the next mock request.

set_cookie "mycookie", "FOO"


491
492
493
494
# File 'lib/gin/test.rb', line 491

def set_cookie name, value
  @set_cookies ||= {}
  @set_cookies[name] = value
end

#streamObject

The body stream as returned by the Rack response Array. Responds to #each.



623
624
625
# File 'lib/gin/test.rb', line 623

def stream
  rack_response[2]
end

#templatesObject

Array of template file paths used to render the response body.



368
369
370
# File 'lib/gin/test.rb', line 368

def templates
  @templates ||= []
end

#use_lib(lib, gemname = nil) ⇒ Object

:nodoc:



305
306
307
308
309
310
311
312
313
314
# File 'lib/gin/test.rb', line 305

def use_lib lib, gemname=nil # :nodoc:
  require lib
rescue LoadError => e
  raise unless e.message == "cannot load such file -- #{lib}"
  gemname ||= lib
  $stderr.puts "You need the `#{gemname}' gem to access some of the features \
you are trying to use.
Run the following command and try again: gem install #{gemname}"
  exit 1
end