1
votes

Final Edit: Thanks to @PeterAlfvin's suggestion that I focus on the application layout and the header, I was able to fix it. I haven't been able to figure out exactly what the problem was, but something in the header was causing capybara to not 'see' the rest of the page. I removed <%= render 'layouts/header' %>, re-built the header inside application.html.erb, and once it was working, pulled it out into a partial and replaced the render statement. I fiddled with both the old and new header files to try to figure out the problem, but no success with that yet. That makes my tests seem a bit brittle, but if the problem arises again, at least I'll know where to look.

Edit: If you feel inclined to downvote, please go ahead, but let me know what I have overlooked or failed to research, because your comment might help me figure this out.

I've searched for HOURS trying to fix this, but I can't figure out what's going on. I'm sure I'm missing something simple that will be obvious to anyone who hasn't been staring at it for the last day. That's my hope, anyway.

All of my Rspec/capybara request specs are failing, but when I view the pages in my browser, all the elements that the specs fail to find are plainly there. As far as I can tell, Capybara isn't seeing the entire page- save_and_open_page returns a nearly-blank page. The failure I see with the spec below is universal- the specs can see the page title, but not anything in the page body. I'm fairly confident that all my routes are good, because all the title tests pass when they should.

spec/requests/static_pages_spec.rb

require 'spec_helper'

describe "StaticPages" do

  subject { page }    

  describe "About page" do 
    before { visit about_path } 
    it { save_and_open_page; 
         should have_selector('title', text: 'Company Name | About') }    
    it { should have_selector('h1', text: 'About stuff') }
    it { should have_content('About paragraph') }
  end

  #more specs...

end

results:

5) StaticPages About page 
   Failure/Error: it { should have_selector('h1', text: 'About stuff') }
     expected css "h1" with text "About stuff" to return something
   # ./spec/requests/static_pages_spec.rb:28:in `block (3 levels) in <top (required)>'

6) StaticPages About page 
   Failure/Error: it { should have_content('About paragraph') }
     expected there to be content "About paragraph" in "Company Name | About\n\t\n\t\t"
   # ./spec/requests/static_pages_spec.rb:29:in `block (3 levels) in <top (required)>'

Here's the "view source" output of the page opened in my browser by save_and_open_page:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Company Name | About</title>
<link href="/assets/application.css" media="all" rel="stylesheet" type="text/css">
<script src="/assets/application.js" type="text/javascript"></script><!--[if lt IE 9]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
</head>
<body>
<header class="navbar navbar-fixed-top navbar-inverse"><div class="navbar-inner">
    </div></header>
</body>
</html>

So, based on the source, and the response message for spec #6, it looks like it isn't searching any content besides the page title, which would be supported by the fact that my title tests always pass, but nothing else does. I have tests that look for form elements, buttons, etc, and I've tried identifying them different ways (label, id, name), but capybara can't find any of them. Again, when I view these pages in my browser, everything is plainly visible, and labelled correctly.

When I visit the About page in my browser, this is the page source for the body, in contrast to the body content shown above:

<body>
    <header class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
    <a class="brand" href='/'>Company Name</a>
    <ul class="nav pull-left">
        <li><a href="/products">Products</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="/contact">Contact</a></li>
    </ul>
    <ul class="nav pull-right">
        <li><a href="/users/sign_in">Sign in</a></li>
    </ul>
</div>
    </header>
<div class="container-fluid">
    <div class="row-fluid">
        <div class="span10 offset2"></div>      
            <h1>About stuff</h1>
            <p>About paragraph</p>      
    </div>
</div>
</body>

Gemfile:

source 'https://rubygems.org'

gem 'rails', '3.2.13'
gem 'bootstrap-sass', '2.1'
gem 'faker', '1.1.2'
gem 'will_paginate', '3.0.4'
gem 'bootstrap-will_paginate', '0.0.9'
gem 'jquery-rails'
gem 'devise'
gem 'foreigner'
gem 'paper_trail'

group :development, :test do
  gem 'sqlite3', '1.3.7'
  gem 'rspec-rails', '2.11.0'
  gem 'letter_opener'
  gem 'factory_girl_rails', '4.1.0'
end

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '3.2.5'
  gem 'coffee-rails', '3.2.2'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  # gem 'therubyracer', :platforms => :ruby

  gem 'uglifier', '1.2.3'
end 

group :test do
  gem 'capybara', '1.1.2'
# gem 'rb-inotify', '0.8.8'
# gem 'libnotify, '0.5.9'
  gem 'shoulda-matchers'
  gem 'accept_values_for'
end

group :production do
  gem 'pg', '0.12.2'
end

Any help towards sorting this out will be greatly appreciated. Please let me know if I should include any additional info.

Edit to add erb files

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
  <%= stylesheet_link_tag    "application", :media => "all" %>
  <%= javascript_include_tag "application" %> 
  <%= csrf_meta_tags %>
    <!--[if lt IE 9]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
</head>
<body>

  <%= render 'layouts/header' %>  

  <div class="container-fluid">
    <div class="row-fluid">
      <div class="span10 offset2">

        <% flash.each do |key, value| %>
          <div class="alert alert-<%= key %>"><%= value%></div>
        <% end %>

      </div>  

    <%= yield %>

    <%= render 'layouts/footer' %>
    <%= debug(params) if Rails.env.development? %>    

    </div>
  </div>   
</body>
</html>

app/views/layouts/_header.html.erb

<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="navbar-inner">
    <a class="brand" href='/'>Company Name</a>
      <ul class="nav pull-left">
        <li><%= link_to "Products", products_path %></li>
        <li><%= link_to "About",    about_path    %></li>
        <li><%= link_to "Contact",  contact_path  %></li>
      </ul> 

    <% if user_signed_in? %>
      <ul class="nav pull-right"> 
        <li><strong><%= current_user.email %></strong></li>
        <li><%= link_to 'Account', account_path %></li>
        <li><%= link_to "Sign out", destroy_user_session_path, method: :delete %></li>
      </ul> 
    <% else %>
      <ul class="nav pull-right">
        <li><%= link_to "Sign in", new_user_session_path %></li>
      </ul>
    <% end %>
  </div>
</header>

app/views/layouts/_footer.html.erb

<footer class="footer">
  <small>Company Name Price Management</small>
</footer>

app/views/static_pages/about.html.erb

<% provide(:title, 'About') %>
<h1>About stuff</h1>
<p>About paragraph</p>
1
I'm confused by the inclusion of save_and_open_page in your spec and a source file of the same name. How are these two related? What does the save_and_open_page method do?Peter Alfvin
I'm groping, but have you tried running it without the save_and_open_page and instead just doing a puts page at that point to see if the content is the same?Peter Alfvin
Oh, I just noticed that you're not setting subject anywhere for rspec. Have you tried subject {page}?Peter Alfvin
Still groping, but have you restarted your web server (to make sure you're not seeing a false positive based on old code with your browser)? you could share the relavent .erb files?Peter Alfvin
Ok, this is crazy. ;-) Assuming you've confirmed that about_path is valid, I'd start modifying your _layout.html.erb file to see if you can establish the correlation of that file to what your test produces. Right now, it's not showing any of the content of the navbar-inner div. You could add something to that div tag (e.g. an id) and see if it shows up in your test. I'm assuming there's no timing issue here since capybara should "wait" until the page refreshes, but you could try a delay as well, just to rule that out.Peter Alfvin

1 Answers

4
votes

Today (over a month later) I realized what was causing the problem- an incorrect HTML comment. When I experiment with things, I usually comment out the experiments instead of deleting them, so it was bound to happen again, but this time it was easier to spot.

Correct comment:
<!-- commented-out HTML -->

Incorrect comment:
<!-- commented-out HTML --!>

That second ! at the end of the incorrect comment was causing the comment to not be closed properly. My text editor didn't care, and my browser seemed to be rendering everything the same, but in my case, capybara wasn't reading past it.

Kind of embarrassing, but at least I know now.