class Strelka::Testing::HaveJSONBodyMatcher

RSpec matcher for matching Strelka::HTTPResponse body

Expect that the response consists of JSON of some sort:

expect( response ).to have_json_body

Expect that it's a JSON body that deserializes as an Object:

expect( response ).to have_json_body( Object )
# -or-
expect( response ).to have_json_body( Hash )

Expect that it's a JSON body that deserializes as an Array:

expect( response ).to have_json_body( Array )

Expect that it's a JSON body that deserializes as an Object that has expected keys:

expect( response ).to have_json_body( Object ).
    that_includes( :id, :first_name, :last_name )

Expect that it's a JSON body that deserializes as an Object that has expected keys and values:

expect( response ).to have_json_body( Object ).
    that_includes(
        id: 118,
        first_name: 'Princess',
        last_name: 'Buttercup'
    )

Expect that it's a JSON body that has other expected stuff:

expect( response ).to have_json_body( Object ).
    that_includes(
        last_name: a_string_matching(/humperdink/i),
        profile: a_hash_including(:age, :eyecolor, :tracking_ability)
    )

Expect a JSON Array with objects that all match the criteria:

expect( response ).to have_json_body( Array ).
    of_lenth( 20 ).
    and( all( be_an(Integer) ) )

Attributes

additional_expectations[R]
expected_type[R]
failure_description[R]
response[R]

Public Class Methods

new( expected_type=nil ) click to toggle source

Create a new matcher that expects a response with a JSON body. If expected_type is not specified, any JSON body will be sufficient for a match.

# File lib/strelka/testing.rb, line 248
def initialize( expected_type=nil )
        @expected_type = expected_type
        @additional_expectations = []
        @response = nil
        @failure_description = nil
end

Public Instance Methods

and( *matchers ) click to toggle source

Add the specified matchers as expectations of the Hash or Array that's parsed from the JSON body.

# File lib/strelka/testing.rb, line 337
def and( *matchers )
        @additional_expectations.concat( matchers )
        return self
end
failure_message() click to toggle source

RSpec matcher API – return a message describing an expectation failure.

# File lib/strelka/testing.rb, line 276
def failure_message
        return "\n---\n%s\n---\n\nReason: %s\n" % [
                self.pretty_print_response,
                self.failure_description
        ]
end
failure_message_when_negated() click to toggle source

RSpec matcher API – return a message describing an expectation being met when the matcher was used in a negated context.

# File lib/strelka/testing.rb, line 286
def failure_message_when_negated
        msg = "expected response not to have a %s" % [ self.describe_type_expectation ]
        msg << " and " << self.describe_additional_expectations.join( ', ' ) unless
                self.additional_expectations.emtpy?
        msg << ", but it did."

        return "\n---\n%s\n---\n\nReason: %s\n" % [
                self.pretty_print_response,
                msg
        ]
end
matches?( response ) click to toggle source

RSpec matcher API – returns true if all expectations of the specified response are met.

# File lib/strelka/testing.rb, line 264
def matches?( response )
        @response = response

        return self.correct_content_type? &&
                self.correct_json_type? &&
                self.matches_additional_expectations?
rescue Yajl::ParseError => err
        return self.fail_with "Response has invalid JSON body: %s" % [ err.message ]
end
of_length( number ) click to toggle source

Add an additional expectation that the JSON body contain the specified number of members.

# File lib/strelka/testing.rb, line 328
def of_length( number )
        @additional_expectations << have_attributes( length: number )
        return self
end
Also aliased as: of_size
of_size( number )
Alias for: of_length
parsed_response_body() click to toggle source

Return the response's body parsed as JSON.

# File lib/strelka/testing.rb, line 300
def parsed_response_body
        return @parsed_response_body ||=
                Yajl::Parser.parse( self.response.body, check_utf8: true, symbolize_keys: true )
end
that_excludes( *memberset ) click to toggle source

Add an additional expectation that the JSON body does not contain the specified members.

# File lib/strelka/testing.rb, line 320
def that_excludes( *memberset )
        @additional_expectations << exclude( *memberset )
        return self
end
that_includes( *memberset ) click to toggle source

Add an additional expectation that the JSON body contains the specified members.

# File lib/strelka/testing.rb, line 311
def that_includes( *memberset )
        @additional_expectations << include( *memberset )
        return self
end
Also aliased as: which_includes
which_includes( *memberset )
Alias for: that_includes

Protected Instance Methods

correct_content_type?() click to toggle source

Returns true if the response has a JSON content-type header.

# File lib/strelka/testing.rb, line 362
def correct_content_type?
        content_type = self.response.headers[:content_type] or
                return self.fail_with "response doesn't have a Content-type header"

        return fail_with "response's Content-type is %p" % [ content_type ] unless
                content_type.start_with?( 'application/json' ) ||
                content_type.match?( %r|\Aapplication/(vnd\.)?\w+\+json\b| )

        return true
end
correct_json_type?() click to toggle source

Check that the JSON body of the response has the correct type, if a type was specified.

# File lib/strelka/testing.rb, line 391
def correct_json_type?
        return self.parsed_response_body unless self.expected_type

        if self.expected_type == Array
                return self.fail_with( "response body isn't a JSON Array" ) unless
                        self.parsed_response_body.is_a?( Array )
        elsif self.expected_type == Object || self.expected_type == Hash
                return self.fail_with( "response body isn't a JSON Object" ) unless
                        self.parsed_response_body.is_a?( Hash )
        else
                warn "A valid JSON response can't be a %p!" % [ self.expected_type ]
        end

        return true
end
describe_additional_expectations() click to toggle source

Return an Array of descriptions of the members that were expected to be included in the response body, if any were specified. If none were specified, returns an empty Array.

# File lib/strelka/testing.rb, line 411
def describe_additional_expectations
        return self.additional_expectations.map( &:description )
end
describe_type_expectation() click to toggle source

Return an Array of text describing the expectation that the body be an Object or an Array, if a type was expected. If no type was expected, returns an empty Array.

# File lib/strelka/testing.rb, line 377
def describe_type_expectation
        return case self.expected_type
                when Object, Hash
                        "a JSON Object/Hash body"
                when Array
                        "a JSON Array body"
                else
                        "a JSON body"
                end
end
fail_with( message ) click to toggle source

Return false after setting the failure message to message.

# File lib/strelka/testing.rb, line 354
def fail_with( message )
        @failure_description = message
        self.log.error "Failing with: %s" % [ message ]
        return false
end
matches_additional_expectations?() click to toggle source

Check that any additional matchers registered via the `.and` mutator also match the parsed response body.

# File lib/strelka/testing.rb, line 418
def matches_additional_expectations?
        return self.additional_expectations.all? do |matcher|
                matcher.matches?( self.parsed_response_body ) or
                        fail_with( matcher.failure_message )
        end
end
pretty_print_response() click to toggle source

Return a String that contains a pretty-printed version of the response object.

# File lib/strelka/testing.rb, line 348
def pretty_print_response
        return self.response.to_s
end