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



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

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



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

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]
      content_type ctype
      return body(args.first, :not_found)
    end
  else
    if ctype = CONTENT_TYPES[meth] # [content_type] methods        
      content_type ctype
      return body(*args)
    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”)



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

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)



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

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.



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

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.



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

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

#found(pattern) ⇒ Object

temporary move



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

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.



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

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



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

def json(arg1=nil, arg2=nil, &code)
  content_type CONTENT_TYPES[:json]
  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
end

#moved(pattern) ⇒ Object

permanent move



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

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

#okObject

Checks if status is some of the ok-codes.



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

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

#path_infoObject

shortcut to the path of the last request



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

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

#query_stringObject

shortcut to the query string of the last request



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

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



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

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.



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

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

#see_other(pattern) ⇒ Object

redirect to get



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

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



182
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
# File 'lib/assert-response.rb', line 182

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



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

def url
  @request.url
end