I'm on the chapter 5 exercises for Michael Hartl's Rails Tutorial and am trying to wrap my head around how Rails/Rspec is testing a helper method full_title in app/helpers/application_helper.rb. All of my tests are in spec/requests/static_pages_spec.rb and within them, I'm calling full_title to cut down on code bloat.
So, in order to test the original full_title I create a test in spec/helpers/application_helpers_spec.rb and include it via spec/support/utilities.rb. The code is passing, but I want to understand the process (order to operations) to what is going on. Thank you.
Can I think of it like this?
Rspec begins to run static_pages_spec.rb (including utilities.rb)
Rspec sees the full_title method in static_pages_spec.rb
Rspec begins to run application_helper_spec.rb
Rspec sees describe "full_title" do in application_helper_spec.rb
Rspec looks up original full_title method and finishes test for application_helper_spec.rb
Rspec finishes tests in static_pages_spec.rb, iterating through above process whenfull_title` is called.
static_pages_spec.rb
require 'spec_helper'
describe "Static pages" do
subject { page }
shared_examples_for "all static pages" do
it { should have_selector('h1', text: heading) }
it { should have_selector('title', text: full_title(page_title)) }
end
describe "Home page" do
before { visit root_path }
let(:heading) { 'Sample App' }
let(:page_title) { '' }
it_should_behave_like "all static pages"
it { should_not have_selector 'title', text: '| Home' }
end
describe "Help page" do
before { visit help_path }
let(:heading) { 'Help' }
let(:page_title) { 'Help' }
it_should_behave_like "all static pages"
end
describe "About page" do
before { visit about_path }
let(:heading) { 'About' }
let(:page_title) { 'About Us' }
it_should_behave_like "all static pages"
end
describe "Contact page" do
before { visit contact_path }
let(:heading) { 'Contact' }
let(:page_title) { 'Contact' }
it_should_behave_like "all static pages"
end
it "should have the right links on the layout" do
visit root_path
click_link "About"
page.should have_selector 'title', text: full_title('About Us')
click_link "Help"
page.should have_selector 'title', text: full_title('Help')
click_link "Contact"
page.should have_selector 'title', text: full_title('Contact')
click_link "Home"
page.should have_selector 'title', text: full_title('')
click_link "Sign up now!"
page.should have_selector 'title', text: full_title('Sign up')
click_link "sample app"
page.should_not have_selector 'title', text: full_title('| Home')
end
end
application_helper_spec.rb
require 'spec_helper'
describe ApplicationHelper do
describe "full_title" do
it "should include the page title" do
full_title("foo").should =~ /foo/
end
it "should include the base title" do
full_title("foo").should =~ /^Ruby on Rails Tutorial Sample App/
end
it "should not include a bar for the home page" do
full_title("").should_not =~ /\|/
end
end
end
application_helper.rb
module ApplicationHelper
#Returns the full title on a per-page basis.
def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
else
"#{base_title} | #{page_title}"
end
end
end
Think about it this way:
The 'full_title' called in static_pages_spec.rb (including utilities.rb) is running the 'full_title' method described in application_helper.rb.
The application_helper_spec.rb is validating the string/value (page_title) passed through full_title.
If I'm not mistaken, it does this each time the full_title method is called in your tests.
Related
I have set up guard following Michael's RoR Tutorials and intentionally wrote a test (on contact page title) so it fails. But Guard/RSpec tells me it passed and I am confused what's going on. This is my static_pages_spec.rb file:
require 'spec_helper'
describe "Static pages" do
describe "Home page" do
it "should have the content 'Welcome to the PWr App'" do
visit '/static_pages/home'
expect(page).to have_content('Welcome to the PWr App')
end
it "should have the title 'Home'" do
visit '/static_pages/home'
expect(page).to have_title("PWr | Home")
end
end
describe "Help page" do
it "should have the content 'Help'" do
visit '/static_pages/help'
expect(page).to have_content('Help')
end
it "should have title 'Help'" do
visit '/static_pages/help'
expect(page).to have_title("PWr | Help")
end
end
describe "About page" do
it "should have the content 'About me'" do
visit '/static_pages/about'
expect(page).to have_content('About Me')
end
it "should have title 'About Me'" do
visit '/static_pages/about'
expect(page).to have_title("PWr | About")
end
end
describe "Contact page" do
it "should have the content 'Contact'" do
visit '/static_pages/contact'
expect(page).to have_content('Contact')
end
it "should have title 'Contact'" do
visit '/static_pages/contact' do
expect(page).to have_title("FAIL")
end
end
end
end
And this is my contact.html.erb:
<% provide(:title, 'Contact') %>
<h1>Contact</h1>
<p1>
If you need to contact me just call the number below: </br>
+48 737823884
</p>
And results from my terminal:
18:43:57 - INFO - Running: spec/requests/static_pages_spec.rb
........
Finished in 0.08689 seconds
8 examples, 0 failures
Randomized with seed 55897
[1] guard(main)>
As you can see, in the spec file close to the end I have expect(page).to have_title("FAIL") and in the contact page html/erb I clearly have <% provide(:title, 'Contact') %> but the test passes. Why is this? What am I doing wrong?
The problem is that you are passing your expectation as a block to the visit method - ie notice the extra do-end. I do not believe that visit uses blocks, so basically that bit of code gets ignored.
it "should have title 'Contact'" do
visit '/static_pages/contact' do
expect(page).to have_title("FAIL")
end
end
Your spec should behave as expected if you remove the block.
it "should have title 'Contact'" do
visit '/static_pages/contact'
expect(page).to have_title("FAIL")
end
I have problem with my rspec code. I write some tests. I use syntax like: subject {page} and then i want to write test's in this style: it {should have_content()} but when I run rspec it show's error:
Failure/Error: it{ should have_content("Post associated with #{category.name}") }
NoMethodError:
undefined method `it' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_1:0x00000007c86ea8>
This is my all file:
require 'spec_helper'
describe "Categories Pages" do
subject {page}
let(:user) {FactoryGirl.create(:user)}
before {sign_in user}
let(:category) {FactoryGirl.create(:category)}
let(:p3 ) {FactoryGirl.create(:post, user: user, content: "Foo", title: "Bar", category: category)}
describe "Categories show page" do
before do
visit post_path(p3)
click_link 'Test Category'
end
it "should has elements" do
current_path.should == category_path(category)
it{ should have_content("Post associated with #{category.name}") }
expect(page).to have_content(p3.content)
expect(page).to have_link(p3.title, href: post_path(p3))
expect(page).to have_content(p3.comments.count)
expect(page).to have_link(p3.category.name, href: category_path(p3.category))
expect(page).to have_link(p3.user.name, href: user_path(user))
expect(page).to have_link('All Categories', href: categories_path)
expect(page).to have_title(full_title('Test Category'))
end
end
describe "Categories index page" do
before do
visit post_path(p3)
click_link 'Test Category'
click_link "All Categories"
end
it "should have elements" do
expect(page).to have_link('Test Category', href: category_path(category))
expect(page).to have_selector('h1', text: 'All Categories')
expect(page).to have_title(full_title('All Categories'))
end
end
end
Please help.
You can't have an it inside another it.
The problem is in this line:
it{ should have_content("Post associated with #{category.name}") }
Simply remove the it, or move it to outside of the other it block.
page.should have_content("Post associated with #{category.name}")
It is a good idea have one assertion per test. Check better specs
I don't think you can nest it blocks. Pull this line
it{ should have_content("Post associated with #{category.name}") }
out of the surrounding it block and make it a stand-alone test in the describe block.
I'm having trouble getting one of my Rspec tests to pass using Capybara 2.1.0
This works:
require 'spec_helper'
describe "Static pages" do
describe "Home page" do
it "should have the title 'Home'" do
visit '/static_pages/home'
page.should have_title("MyApp | Home")
end
end
end
This does not
require 'spec_helper'
describe "Static pages" do
let(:site_title) {"MyApp"}
describe "Home page" do
it "should have the title 'Home'" do
visit '/static_pages/home'
page.should have_title("#{site_title} | Home")
end
end
end
Any thoughts? I've been working on it for quite a while. Here is the error message that I receive.
1) Static pages Home page should haven the title
Failure/Error: page.should have_title("#{site_title} | Home")
expected #has_title?("MyApp | Home") to return true, got false
# ./spec/requests/static_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
It seems you are missing the curly braces for #{site_title} or you need to use double quotes for your string to allow interpolation of variables. You have:
page.should have_title('#site_title | Home')
where it should be
page.should have_title("#{site_title} | Home")
Try this:
require 'spec_helper'
describe "Static pages" do
let(:site_title) {"MyApp"}
describe "Home page" do
it "should have the title 'Home'" do
visit '/static_pages/home'
page.should have_selector('title', text: "#{site_title} | Home")
end
end
end
http://ruby.railstutorial.org/chapters/static-pages#code:pages_controller_spec_title
My code is as follows. When uncommented the test wont run. Below is the commented version of the code that allows the defined test to initiate. I don't know how to format this question with ruby syntax color. Dont yell at me.
require 'spec_helper'
describe "Static Pages" do
describe "Home page" do
it "should have the h1 'Sample App'" do
visit '/static_pages/home'
page.should have_selector('h1', :text =>'Sample App')
end
it "should have the title 'Home'" do
visit '/static_pages/home'
page.should have_selector('title',
:text => "Ruby on Rails Tutorial Sample App | Home")
end
end
describe "Help Page" do
it "should have the h1 'Help'" do
visit '/static_pages/help'
page.should have_selector('h1', :text =>'Help')
end
it "should have the title 'Help'" do
visit '/static_pages/help'
page.should have_selector('title',
:text => "Ruby on Rails Tutorial Sample App | Help")
end
end
describe "About Page" do
it "should have the h1 'About us'" do
visit '/static_pages/about'
page.should have_selector('h1', :text => 'About us')
end
it "should have the title 'About us'" do
visit '/static_pages/about'
page.should have_selector('title',
:text => "Ruby on Rails Tutorial Sample App | About us")
end
end
# describe 'Contact' do
# it "Should have the h1 'Contact'" do
# visit "static_pages/contact"
# page.should have_selector('h1', :text => 'Contact')
# end
# it "should have the title 'Contact'"
# visit "static_pages/contact"
# page.should have_selector('title',
# :text => "Ruby on Rails Tutorial Sample App | Contact")
# end
# end
end
I guess you forgot do at the end of this line:
it "should have the title 'Contact'"
^
I'm currently working through Hartl. In Chapter 5 i'm adding Hartl's code from listing 5.27 (below) to my spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "Static pages" do
subject { page }
describe "Home page" do
before { visit root_path }
it { should have_selector('h1', text: 'Sample App') }
it { should have_selector('title', text: full_title('')) }
it { should_not have_selector 'title', text: '| Home' }
end
describe "Help page" do
before { visit help_path }
it { should have_selector('h1', text: 'Help') }
it { should have_selector('title', text: full_title('Help')) }
end
describe "About page" do
before { visit about_path }
it { should have_selector('h1', text: 'About') }
it { should have_selector('title', text: full_title('About Us')) }
end
describe "Contact page" do
before { visit contact_path }
it { should have_selector('h1', text: 'Contact') }
it { should have_selector('title', text: full_title('Contact')) }
end
end
Whe I run the $ bundle exec rspec spec/requests/static_pages_spec.rb test, Terminal returns this error:
Failures:
1) Static pages Home page
Failure/Error: it { should have_selector('title', text: full_title('')) }
NoMethodError:
undefined method `full_title' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_1:0x007fb4b44504c8>
# ./spec/requests/static_pages_spec.rb:11:in `block (3 levels) in <top (required)>'
2) Static pages Help page
Failure/Error: it { should have_selector('title', text: full_title('Help')) }
NoMethodError:
undefined method `full_title' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2:0x007fb4b46a9008>
# ./spec/requests/static_pages_spec.rb:19:in `block (3 levels) in <top (required)>'
3) Static pages About page
Failure/Error: it { should have_selector('title', text: full_title('About Us')) }
NoMethodError:
undefined method `full_title' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_3:0x007fb4b4430290>
# ./spec/requests/static_pages_spec.rb:26:in `block (3 levels) in <top (required)>'
4) Static pages Contact page
Failure/Error: it { should have_selector('title', text: full_title('Contact')) }
NoMethodError:
undefined method `full_title' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_4:0x007fb4b40e57e8>
# ./spec/requests/static_pages_spec.rb:33:in `block (3 levels) in <top (required)>'
Finished in 0.21306 seconds
9 examples, 4 failures
Failed examples:
rspec ./spec/requests/static_pages_spec.rb:11 # Static pages Home page
rspec ./spec/requests/static_pages_spec.rb:19 # Static pages Help page
rspec ./spec/requests/static_pages_spec.rb:26 # Static pages About page
rspec ./spec/requests/static_pages_spec.rb:33 # Static pages Contact page
Any ideas?
Do you have this line in your spec_helper.rb file?
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
Do you have a spec/support/utilities.rb file that looks like this?
include ApplicationHelper
def sign_in(user)
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
# Sign in when not using Capybara as well.
cookies[:remember_token] = user.remember_token
end
Do you have a app/helpers/application_helper.rb file that looks like this?
module ApplicationHelper
# Returns the full title on a per-page basis.
def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
else
"#{base_title} | #{page_title}"
end
end
end
If so, I think your error should go away.
Hi there I also following Michael's tutorial for Rails 3.2 version and get the same error... try this with your current version of capybara
I changed the :text to :content and got it works, so it looks like this:
it { should have_selector('title', content: full_title('')) }
Hope it helps, cheers!
The exercise in Chapter 5 reads
"eliminate the need for the full_title test helper in Listing 5.26 by
writing tests for the original helper method, as shown in Listing
5.37. (You will have to create both the spec/helpers directory and the application_helper_spec.rb file.) Then include it into the test using
the code in Listing 5.38."
http://ruby.railstutorial.org/chapters/filling-in-the-layout.html#sec-layout_exercises
Does that mean I only need "include ApplicationHelper" my utilites.rb file since spec/helpers/application_helper_spec.rb now contains
require 'spec_helper'
describe ApplicationHelper do
describe "full_title" do
it "should include the page title" do
full_title("foo").should =~ /foo/
end
Having this setup I am still getting an error when I run my RSpec test. They only way I can get it to pass is having full_title defined in utilites.rb
The current formatting should look like this for your tests to pass:
it { should have_title(full_title('Help')) }
it { should have_title(full_title('About')) }
it { should have_title(full_title('Contact')) }
Considering this post is two years old, I assume you have figured this out. Nevertheless, try adding
RSpec.configure do |config|
...
config.include ApplicationHelper
...
end
within spec\requests\spec_helper.rb