Class: AssertResponse

Inherits:
Object
  • Object
show all
Defined in:
lib/assert-response.rb

Defined Under Namespace

Modules: Methods Classes: AssertJSON, HttpError, Status404

Constant Summary collapse

HTTP_STATUS_CODES =

Hash with names for the http 1.1 status codes

{
  :ok => 200,
  :not_found => 404,
  :created => 201,
  :bad_request => 400,
  :unauthorized => 401,
  :forbidden => 403,
  :timeout => 408,
  :gateway_timeout => 504,
  :bad_gateway => 502,
  :conflict => 409,
  :gone => 410,
  :too_many_requests => 429,
  :upgrade_required => 426,
  :teapot => 418,
  :no_response  => 444,
  :bandwidth_limit_exceeded => 509,
  :maintenance => 503,
  :insufficient_storage => 507,
  :http_version_not_supported => 505,
  :payment_required  => 402,
  :not_modified => 304,
  :see_other => 303,
  :found => 302,
  :moved => 301,
  :reset => 205,
  :reload => 205,
  :no_content => 204,
  :too_large => 413,
  :uri_too_long => 414,
  :unsupported_media_type => 415,
  :not_implemented => 501,
  :error => 500
}
CONTENT_TYPES =

Hash to collection available content-types (prefilled with the Rack::Mime::MIME_TYPES)

See Also:

{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(delegate_to, response, request, &code) ⇒ AssertResponse

Creates a new AssertResponse Object. Usually you will want to instance_exec some code on it.

Parameters:

  • delegate_to (Object)

    the test object that has all the assert_equal, assert_match and assert methods that we need

  • response (MockResponse, Response)

    the response object that is checked



105
106
107
108
109
110
111
# File 'lib/assert-response.rb', line 105

def initialize(delegate_to, response, request, &code)
  @delegate_to = delegate_to
  @response = response
  @request = request
  @error = nil
  check_for_error()
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &code) ⇒ Object

for each content-type in CONTENT_TYPES these methods are served by method_missing

  • is_[content_type] that checks if the response has the content-type

  • [content_type] that checks the content-type and matches the body against the given pattern and checks for status 200

  • not_found_[content_type] that checks the content-type, matches the body against the pattern and checks for status 404

further unknown methods are delegated to @delegate_to



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/assert-response.rb', line 118

def method_missing(meth, *args, &code)
  case meth.to_s
  when /^(is|found)_(.+)$/ # is_[content_type] methods
    if ctype = CONTENT_TYPES[$2.to_sym]
      ok()
      return content_type(ctype)
    end
  when /^not_found_(.+)$/ # not_found_[content_type] methods
    if ctype = CONTENT_TYPES[$1.to_sym]
      body(args.first, :not_found)
      return content_type ctype
    end
  else
    if ctype = CONTENT_TYPES[meth] # [content_type] methods        
      body(*args)
      return content_type ctype
    elsif HTTP_STATUS_CODES[meth]
      return status HTTP_STATUS_CODES[meth]
    end
  end
  @delegate_to.send meth, *args, &code
end

Class Method Details

.add_content_type(name, content_type) ⇒ Object

Adds custom content_types to CONTENT_TYPES. We would then have all the test methods for the content-type

Parameters:

  • name (Symbol)

    name of the content_type

  • content_type (String)

    content_type (mime type, eg. “text/html”)



80
81
82
# File 'lib/assert-response.rb', line 80

def AssertResponse.add_content_type(name, content_type)
  CONTENT_TYPES.update(name => content_type)
end

.add_http_status_code(name, code) ⇒ Object

Adds custom http code to HTTP_STATUS_CODES. We would then have all the test methods for the status code

Parameters:

  • name (Symbol)

    name of the http status code

  • code (Integer)

    code number (eg. 404)



96
97
98
99
# File 'lib/assert-response.rb', line 96

def AssertResponse.add_http_status_code(name, code)
  raise "invalid code" unless code =~ /^[1-9][0-9]{2}$/
  HTTP_STATUS_CODES.update(name => code)
end

Instance Method Details

#body(pattern, status = nil) ⇒ Object

Check if body matches pattern and status is status.

Parameters:

  • pattern (String, Regexp)

    the pattern to match against.



255
256
257
258
# File 'lib/assert-response.rb', line 255

def body(pattern, status=nil)
  status(status)
  assert_match normalize_pattern(pattern), @response.body
end

#content_type(pattern) ⇒ Object

Check if the Content-Type matches pattern. Checks also if request is ok (see #ok).

Parameters:

  • pattern (String, Regexp)

    the pattern to match against.



247
248
249
# File 'lib/assert-response.rb', line 247

def content_type(pattern)
  header 'Content-Type', normalize_pattern(pattern)
end

#found(pattern) ⇒ Object

temporary move



277
278
279
280
# File 'lib/assert-response.rb', line 277

def found(pattern)
  status 302
  header 'Location', pattern
end

#header(key, pattern = :exists) ⇒ Object

Checks if the header key exists and / or if it matches pattern.

Parameters:

  • key (String)

    the key to look for

  • pattern (String, Regexp, :exists) (defaults to: :exists)

    the pattern to match against. :exists just checks for existance of key.



234
235
236
237
238
239
240
241
242
# File 'lib/assert-response.rb', line 234

def header(key, pattern=:exists)
  if pattern == :exists
    assert !@response.headers[key].to_s.empty?, "Header '#{key}' not found"
  elsif pattern.is_a? Regexp
    assert_match normalize_pattern(pattern), @response.headers[key].to_s
  else
    assert_equal pattern.to_s, @response.headers[key].to_s
  end
end

#json(arg1 = nil, arg2 = nil, &code) ⇒ Object

this method checks for content_type json and then it has 2 modes if no code block is given, it acts as “body” if a code block is given, arg1 is the status and arg2 is ignored the code is executed in the context of a AssertJSON object, where you can use the usual assert- methods (even without assert prefix) and the json method gives you the parsed json object to test against



167
168
169
170
171
172
173
174
175
176
# File 'lib/assert-response.rb', line 167

def json(arg1=nil, arg2=nil, &code)
  if code
    status arg1
    file, line, rest = caller[0].split(':', 3)
    AssertJSON.new(@delegate_to, @response.body).instance_exec(file, line.to_i, &code)
  elsif arg1      
    body arg1, arg2
  end
  content_type CONTENT_TYPES[:json] # we need to check the content type after status to get the errors
end

#moved(pattern) ⇒ Object

permanent move



283
284
285
286
# File 'lib/assert-response.rb', line 283

def moved(pattern)
  status 301
  header 'Location', pattern
end

#okObject

Checks if status is some of the ok-codes.



142
143
144
# File 'lib/assert-response.rb', line 142

def ok()
  status /^20[0-9]$/
end

#path_infoObject

shortcut to the path of the last request



147
148
149
# File 'lib/assert-response.rb', line 147

def path_info
  @request.env['PATH_INFO']
end

#query_stringObject

shortcut to the query string of the last request



157
158
159
# File 'lib/assert-response.rb', line 157

def query_string
  @request.env['QUERY_STRING']
end

#raises(exception_class = nil, pattern = nil) ⇒ Object

Check if an error was raised.

Parameters:

  • exception_class (Class) (defaults to: nil)

    also check if error is_a? exception_class

  • pattern (String, Regexp) (defaults to: nil)

    also check if the error message matches pattern



264
265
266
267
268
# File 'lib/assert-response.rb', line 264

def raises(exception_class=nil, pattern=nil)
  assert_equal exception_class, @error.class if exception_class
  assert_match normalize_pattern(pattern), @error.message if pattern
  assert !@error.nil?
end

#redirect(pattern) ⇒ Object

Checks if the status is 302, and the header “Location” matches the pattern

Parameters:

  • pattern (String, Regexp)

    the pattern to match against.



225
226
227
228
# File 'lib/assert-response.rb', line 225

def redirect(pattern)
  status /^30(2|3|7)$/
  header 'Location', pattern
end

#see_other(pattern) ⇒ Object

redirect to get



271
272
273
274
# File 'lib/assert-response.rb', line 271

def see_other(pattern)
  status 303
  header 'Location', pattern
end

#status(status) ⇒ Object

Checks if the status is status. For status other then 5xx and error is raised if the response has an error. For status other than 404 an error Status404 is thrown if response status is 404 If we do not check for a 4xx or 5xx code an StatusError is raised if such a code is found and the body is given as error message



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/assert-response.rb', line 183

def status(status)
  return ok() if status.nil?
  if status.is_a?(Symbol)
    raise "unknown status #{status}" unless HTTP_STATUS_CODES[status]
    status = HTTP_STATUS_CODES[status]
  end
  look_for_5xx = case status
  when Regexp
    ((50.to_s =~ status) || (51.to_s =~ status))? true : false
  else
    (status.to_s =~ /^5/) ? true : false
  end
  look_for_404 = case status
  when Regexp
    (404.to_s =~ status) ? true : false
  else
    (status.to_s == "404") ? true : false
  end
  look_for_4xx = case status
  when Regexp
    ((40.to_s =~ status) || (41.to_s =~ status))? true : false
  else
    (status.to_s =~ /^4/) ? true : false
  end
  raise_error() unless look_for_5xx or @response.errors.empty?
  Kernel.raise(Status404, "(#{url}) not found") unless look_for_404 or @response.status != 404    
  
  case status
  when Regexp
    raise_http_error() if @response.status.to_s =~ /^5/ and !look_for_5xx
    raise_http_error() if @response.status.to_s =~ /^4/ and !look_for_4xx
    assert_match(status, @response.status.to_s)
  else
    raise_http_error() if @response.status.to_s =~ /^5/ and status.to_s !~ /^5/
    raise_http_error() if @response.status.to_s =~ /^4/ and status.to_s !~ /^4/
    assert_equal(status, @response.status)
  end
end

#urlObject

shortcut to the url of the last request



152
153
154
# File 'lib/assert-response.rb', line 152

def url
  @request.url
end