0

I'm getting a very weird error, because it's all working perfectly in the browser i.e. the posts are displayed and the author's name is displayed. No errors.

However, the feature test is breaking, and I have no idea why. It's very strange.

posts_features_spec.rb:

require 'spec_helper'
require_relative '../support/spec_helper_methods'

feature "Post Features" do
  include SpecHelperMethods
  let(:user){ User.create(name: "Andy", email: "user@email.com", password: "password", password_confirmation: "password") }

  describe "Creating Posts" do
    it "Can create a post" do
      visit '/'
      click_on "Sign Up"
      fill_in 'user[name]', with: "Bob"
      fill_in 'user[email]', with: "bob@email.com"
      fill_in 'user[password]', with: "password"
      fill_in 'user[password_confirmation]', with: "password"
      click_on 'Sign Up'
      click_on 'Login'
      fill_in 'email', with: "bob@email.com"
      fill_in 'password', with: "password"
      click_on 'Login'
      expect(page).to have_content "Successfully signed in!"
      click_on "Create Post"
      fill_in 'post[title]', with: "Title99"
      fill_in 'post[body]', with: "Body99"
      click_on "Post"
      expect(current_path).to eq '/posts'
      expect(page).to have_content "Title99"
      expect(page).to have_content "Body99"
      expect(page).to have_content "Bob"
      expect(page).to have_content "Post Posted!"
    end
  end

  describe 'Post Show page' do
    let(:post){ Post.create title: 'Lazy-loaded Post', body: 'Body', user: user }
    before(:each){ visit "/posts/show/#{post.id}" }

    it "Post's title, body, and author are displayed" do
      expect(page).to have_content "#{post.title}"
      expect(page).to have_content "#{post.body}"
      expect(page).to have_content "#{post.user.name}"
    end
  end
end

controller:

PadrinoBlog::App.controllers :posts do

  get :new do
    @post = Post.new
    render 'posts/new'
  end

  post :create do
    post = Post.new(params[:post])
    post.user = current_user
    if post.save
      puts Post.all.count
      puts Post.last.inspect
      redirect('/posts', notice: "Post Posted!")
    end
  end

  get :index do
    @posts = Post.order('created_at DESC').all
    render 'posts/index'
  end

  get :show, with: :id do
    @post = Post.find_by_id(params[:id])
    render 'posts/show'
  end

end

index.html.erb:

<%= link_to "Sign Up", 'users/new' %>

<% unless signed_in? %>
  <%= link_to "Login", 'sessions/new' %>
<% end %>

<% if signed_in? %>
  <%= link_to "Logout", 'sessions/destroy' %>
<% end %>

<% if flash[:notice] %>
  <p><%= flash[:notice] %></p>
<% end %>

<% if signed_in? %>
  <%= link_to "Create Post", 'posts/new' %>
<% end %>

<% if @posts %>
  <%= partial 'posts/post', collection: @posts %>
<% end %>

_posts.html.erb:

<div class='post'>
  <h4><%= post.title %></h4>
  <p><%= post.body %></p>
  <p><%= post.user.name %></p>
</div>

When running the tests, the 'Show Page' test passes, but the first one (the long one) breaks when it clicks 'Create Post', with this:

Failure/Error: <p><%= post.user.name %></p>

     NoMethodError:
       undefined method `name' for nil:NilClass
     # ./app/views/posts/_post.html.erb:4:in `block in singleton class'
     # ./app/views/posts/_post.html.erb:-7:in `instance_eval'
     # ./app/views/posts/_post.html.erb:-7:in `singleton class'
     # ./app/views/posts/_post.html.erb:-9:in `__tilt_5665000'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `evaluate'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:103:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering/erb_template.rb:18:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:822:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering.rb:212:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino-helpers/render_helpers.rb:55:in `block in partial'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `each'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `each_with_object'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `public_send'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:132:in `method_missing'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:99:in `method_missing'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino-helpers/render_helpers.rb:48:in `partial'
     # ./app/views/posts/index.html.erb:20:in `block in singleton class'
     # ./app/views/posts/index.html.erb:-6:in `instance_eval'
     # ./app/views/posts/index.html.erb:-6:in `singleton class'
     # ./app/views/posts/index.html.erb:-8:in `__tilt_5665000'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:170:in `evaluate'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/tilt-1.4.1/lib/tilt/template.rb:103:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering/erb_template.rb:18:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:822:in `render'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-helpers-0.13.1/lib/padrino/rendering.rb:212:in `render'
     # ./app/controllers/posts.rb:20:in `block (2 levels) in <top (required)>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:517:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:517:in `block in route'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:992:in `block in invoke_route'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:987:in `catch'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:987:in `invoke_route'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:952:in `block in route!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:53:in `block in call_by_request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:84:in `block in rotation'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:83:in `loop'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:83:in `with_object'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:83:in `rotation'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router/compiler.rb:49:in `call_by_request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/path_router.rb:43:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:949:in `route!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:932:in `block in dispatch!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `block in invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `catch'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/application/routing.rb:930:in `dispatch!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:906:in `block in call!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `block in invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `catch'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `invoke'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:906:in `call!'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rspec-padrino-0.2.2/lib/rspec/padrino/initializers/last_application.rb:12:in `block (2 levels) in <top (required)>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:894:in `call'
     # ./lib/connection_pool_management_middleware.rb:7:in `block in call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/abstract/connection_pool.rb:292:in `with_connection'
     # ./lib/connection_pool_management_middleware.rb:7:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sass-3.4.21/lib/sass/plugin/rack.rb:54:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb:18:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb:18:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb:31:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/head.rb:13:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:225:in `context'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:220:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:2021:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1486:in `block in call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1795:in `synchronize'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1486:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/router.rb:84:in `block in call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/router.rb:75:in `each'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/padrino-core-0.13.1/lib/padrino-core/router.rb:75:in `call'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-test-0.6.3/lib/rack/mock_session.rb:30:in `request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rspec-padrino-0.2.2/lib/rspec/padrino/initializers/last_application.rb:34:in `block (2 levels) in <top (required)>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-test-0.6.3/lib/rack/test.rb:244:in `process_request'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/rack-test-0.6.3/lib/rack/test.rb:58:in `get'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:60:in `process'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:38:in `block in process_and_follow_redirects'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:37:in `times'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:37:in `process_and_follow_redirects'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/browser.rb:26:in `submit'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/form.rb:77:in `submit'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/rack_test/node.rb:61:in `click'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/element.rb:134:in `block in click'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/base.rb:84:in `synchronize'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/element.rb:134:in `click'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/node/actions.rb:13:in `click_link_or_button'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/session.rb:686:in `block (2 levels) in <class:Session>'
     # /home/andrew/.rvm/gems/ruby-2.3.0/gems/capybara-2.6.0/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
     # ./spec/features/posts_features_spec.rb:25:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:17:in `block (2 levels) in <top (required)>'

Like I said, no problems running locally in the browser, nothing breaks, but this test breaks, which is really strange, especially since the show view (which doesn't break) is:

<h4><%= @post.title %></h4>
<p><%= @post.body %></p>
<p><%= @post.user.name %></p>

I've even tried doing things without the partial in the index view, with:

<% @posts.each do |post| %>
  <h4><%= post.title %></h4>
  <p><%= post.body %></p>
  <p><%= post.user.name %></p>
<% end %>

...but I get exactly the same error. Wtf is going on?

I've pushed this present state to a commit here

Yorkshireman
  • 2,194
  • 1
  • 21
  • 36
  • 1
    Check if `post.user` is nil – sbs Jan 30 '16 at 02:35
  • Checking for nil will help to avoid an error. I'd recommend taking a [Screenshot](https://github.com/mattheworiordan/capybara-screenshot) before the 'create' click and seeing what state your application is in. It is possible the data has not loaded (IE `user` is nil for a split second before data is sent back). – dannypaz Jan 30 '16 at 03:13
  • doing puts post.user in the controller returns a user. – Yorkshireman Jan 30 '16 at 03:49
  • I expect the screenshot would be the same as doing save_and_open_page, which I've already done just before clicking 'Post', and it looks normal. Putting it just after 'Post' doesn't work because the test errors out before hitting save_and_open_page. – Yorkshireman Jan 30 '16 at 03:56
  • I've answered below on what I'm 90% sure is the solution, as another issue though you should get used to using `expect(page).to have_current_path(expected path)` rather than expect(current_path).to eq(expected) - the former will use capybaras waiting behavior, which you will need when you move to using a driver that supports JS. – Thomas Walpole Jan 30 '16 at 04:11

1 Answers1

1

Checking out your code and running the test I don't get the error, so I took a quick look at your migrations, and the last migration adds the user to the post. I'm guessing you have an issue with the DB in the test environment

padrino rake ar:migrate:reset -e test

should reset the DB and fix the issue

Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • I think Tom is probably right, but want to add that should add pry-debugger or byebug to your Gemfile and not hesitate to throw in a debugger line close to the source of the error. If it's indeed a missing column, checking Post.column_names from the debugger while the spec was executing would have tipped you off. – johncip Jan 30 '16 at 06:52
  • I was already pretty sure I had run the migrations for the test database, but I ran your line, with no change, and also ran `padrino rake ar:migrate -e test`, just to make doubly sure, and still no change. I also ran byebug and the `Post` seems to be getting persisted to the database with a `user_id`. Also, `Post.column_names` in byebug during the test also shows a `user_id` column. Absolutely bizarre that it runs on your machine with no error! What the hell is going on? – Yorkshireman Jan 30 '16 at 13:56
  • FIXED. The fact it was running on your machine was the clue. I RESET the test database and that cured the problem. Thanks everyone. Tom, if you edit your answer to include running `padrino rake ar:migrate:reset -e test` (which solved my problem), I'll give you best answer. Seems a shame to deprive you of those points when you were so close to the solution ;-) – Yorkshireman Jan 30 '16 at 14:06
  • @Andy update the answer to use reset instead of just migrating – Thomas Walpole Jan 30 '16 at 16:16