0

I am trying to do some acceptance testing and confirm the presence of a model's various attributes being rendered on a Quote#show page. I am using code an expectation as below;

expect(page).to have_content("#{quote.industry}")

I am using FactoryGirl to Quote.create with required object attrs. Quote.industry is an enum created on the quote model with a range of options, all works and renders just fine. However wven when I comment out the diaplay of this attribute on the template the test still passes. There is no other element on the page that matches quote.industry. I cannot work out what's going on?

Secondary to actually understanding what's going on with the above, perhaps it' bad form to be interpolating a value into a Capybara matcher argument? Should one stick to giving strings to the have_content matcher? But perhaps the argument given to have_content should just be a string, as opposed to an interpolated FactoryGirl object. Is this acceptable practice?

Thanks

quote_page_spec.rb

require 'rails_helper'

feature 'quote page' do
    scenario 'renders all quote attributes' do
        quote = FactoryGirl.create(:quote)
        visit("/quotes/#{quote.id}")

        expect(page).to have_content("#{quote.industry}")
    end
end

factories/quotes.rb

FactoryGirl.define do
  factory :quote do
    sequence(:co_name) { |n| "Acme Co #{n}" }
    industry Quote.industries[:financial_services]
  end
end

models/quote.rb

class Quote < ApplicationRecord
    enum industry:          [ :financial_services, :architect, :business_consultancy ]
    enum payment_frequency: [ :annually, :monthly ]
end

show.html.erb

<div class="container">
    <div class="row">
    <div class="col-md-6">
        <table class="table table-bordered table-responsive">
          <thead>
            <tr>
              <th>Property</th>
              <th>Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Company name</td>
              <td><%= @quote.co_name %></td>
            </tr>
            <tr>
              <td>Company number</td>
              <td><%= @quote.co_number %></td>
            </tr>
            <tr>
              <td>Office postcode</td>
              <td><%= @quote.postcode %></td>
            </tr>
            <!-- <tr>
              <td>Industry</td>
              <td><%= @quote.industry %></td>
            </tr> -->
          </tbody>
        </table>
        </div>
    </div>
</div>
jbk
  • 1,911
  • 19
  • 36
  • It shouldn't be passing, are you sure you actually saved the template when adding the comment? You can output `page.html` before the expectation to see what the actual page source is. Also check the string value of `quote.industry` since if it happens to be an empty string for some reason it would match everything. – Thomas Walpole May 31 '17 at 19:43
  • aha, I now find that for some reason the actual attr is not saving to the db, see my question here; https://stackoverflow.com/questions/44293291/why-some-model-attributes-not-saved-in-the-db. But that still doesn't solve why this test is passing. Indeed `quote.industry` is completely empty, so that test should not pass, yet is still does. – jbk May 31 '17 at 20:01
  • 1
    If it's completely empty it will pass -- have_content by default does substring matching and a completely empty string is a substring of anything. – Thomas Walpole May 31 '17 at 21:12
  • Thanks Thomas, object was nil, so test was still passing, submit your comment as the answer and I will accept it as so. – jbk May 31 '17 at 21:50

2 Answers2

1

have_content matching (by default) does substring matching. If quote.industry is nil it will get interpolated to an empty string which is a substring of any content on the page so the test will pass.

Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
-1

The test still passes because the content is still there (check your page source). If you want to comment out the erb output you have to use the proper syntax which is:

<% =begin %>  
  <% my_code %>
<%=end %>

for multiline comments and

<%# my_code %>

for single lines.

This topic (I'm meaning comments, not tests) was discussed here and here again.

yorodm
  • 4,359
  • 24
  • 32
  • The whole `tr` is being commented out with an HTML comment, the fact that the string is in the source should be irrelevant – Thomas Walpole May 31 '17 at 19:42
  • It should not, `have_content` checks your page for generated content and the content is being generated. BTW, wich version of capybara are you working with? – yorodm May 31 '17 at 19:49
  • 1
    Actually, `have_content` checks for visible text on the page (it's just an alias for `have_text). HTML comments are not visible on the page, nor are the contents of them parsed as elements into the DOM, so when something is inside an HTML comment it should be irrelevant to Capybara. That should be in all versions of Capybara (I develop Capybara) – Thomas Walpole May 31 '17 at 19:54
  • @ThomasWalpole: You're absolutely right, it filters everything not visible by the browser, even nodes with `display:none`, the tests should not be passing – yorodm May 31 '17 at 20:01
  • Im using capybara (2.14.0) – jbk May 31 '17 at 20:12