Question

I am trying to write RSpec tests to test the templates I have constructed using jbuilder which ultimately serves up JSON data for my API. I have many tests in spec/controllers which test my controller functionality, but I am looking to also test that I am rendering the correct JSON fields in my jbuilder views. Here is an example of what I have setup:

# app/views/api/v1/users/create.json.jbuilder
json.first_name user.first_name

# spec/views/api/v1/users/create.json.jbuilder_spec.rb
require 'spec_helper'
describe "api/v1/users/create.json.jbuilder" do
  it "renders first_name" do
    assign( :user, User.create( :first_name => "Bob" ) )
    render
    hash = JSON.parse( rendered )
    hash.has_json_node( :first_name ).with( "Bob" )
  end
end

What I get when I run rspec spec/views/api/v1/users/create.json.jbuilder_spec.rb is the following error

Failures:

  1) api/v1/users/create.json.jbuilder render a user
     Failure/Error: render
     ActionView::Template::Error:
       undefined local variable or method `user' for #<#<Class:0x007fa2911c3118>:0x007fa29105f2b8>
     # ./app/views/api/v1/users/create.json.jbuilder:1:in `_app_views_api_v__users_create_json_jbuilder___3806288263594986646_70168098229960'
     # ./spec/views/api/v1/users/create.json.jbulder_spec.rb:6:in `block (2 levels) in <top (required)>'

No matter how I have tried to assign/create/pass a user object to the template, it fails. Any idea what I might be doing wrong?

Was it helpful?

Solution

After much reading and iteration, this is what works:

require 'spec_helper'
describe "api/v1/users/create.json.jbuilder" do

    let( :user )    { User.create( :not_strict => true ) }

    it "renders first_name" do
        render :template => "api/v1/users/create", :locals => { :user => user }, :formats => :json, :handler => :jbuilder
        rendered.should have_json_node( :first_name ).with( user.first_name )
    end
end

note: the have_json_node comes from the api_matchers gem.

OTHER TIPS

assigns method sets instance variables, your view should be @user.first_name instead of user.first_name, or is that a partial? if it's a partial you should do render :partial => ..., if it's a template you should use @user

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top