Search code examples
ruby-on-railsrubyruby-on-rails-3ruby-on-rails-3.1rspec

rspec testing for order of json response


So my code is returning json like this:

    "offenses": [
    {
    "name": "Speeding",
    "penalties": [
    {
    "name": "Ticket",
    "severity": "Medium"
    }

}
]

I have the following fatcory girl:

FactoryGirl.define do
  factory :person_offense_penalty do
    person_offense
    name 'Ticket'
    severity 'Medium'
  end
end



FactoryGirl.define do
  factory :person_offense do
    name 'Speeding'
    person
  end
end

Here my testing for the response and it works fine

  person_offenses = person.person_offenses
  expect(response_body['offenses'].size).to eq(person_offenses.size)



   person_offenses.each_with_index do |offense, offense_index|
        expect(response_body['offenses'][offense_index]['name']).to eq(offense.name)
        offense.person_offense_penaltys.each_with_index do |penalty, penalty_index|
          expect(response_body['offenses'][offense_index]['penaltys'][penalty_index]['name']).to eq(penalty.name)
          expect(response_body['offenses'][offense_index]['penaltys'][penalty_index]['severity']).to eq(penalty.severity)
        end
      end

I need to write another test that makes sure the offense names are sorted in ascending order. Can someone help me with that


Solution

  • First, let's get your JSON into a valid string:

    [1] pry(main)> x = "{\"offenses\": [{ \"name\": \"Speeding\", \"penalties\": [ { \"name\": \"Ticket\", \"severity\": \"Medium\" } ] }] }"
    

    Now we can parse it ActiveSupport::JSON.decode

    [2] pry(main)> offenses = ActiveSupport::JSON.decode(x)["offenses"]
    => [{"name"=>"Speeding", "penalties"=>[{"name"=>"Ticket", "severity"=>"Medium"}]}]
    

    You can get a list of the offense names with map

    [3] pry(main)> names = offenses.map { |o| o["name"] }
    => ["Speeding"]
    

    Now you can simply sort the names and compare

    expect(names).to eq(names.sort)
    

    This will pass if the original JSON has each "offense" in place ordered by it's "name" property.