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'"
^
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
My Rails project's 'spec' folder contains the following:
1) a 'controllers' subfolder with:
a) a 'pages_controller' spec file (with corresponding "describe PagesController do" statement):
require 'spec_helper'
describe PagesController do
render_views
before(:each) do
#base_title = "Ruby on Rails Tutorial Sample App | "
end
describe "GET 'home'" do
it "should be successful" do
get 'home'
response.should be_success
end
it "should have the right title" do
get 'home'
response.should have_selector("title", content: #base_title+"Home")
end
end
describe "GET 'contact'" do
it "should be successful" do
get 'contact'
response.should be_success
end
it "should have the right title" do
get 'contact'
response.should have_selector("title", content: #base_title+"Contact")
end
end
describe "GET 'about'" do
it "should be successful" do
get 'about'
response.should be_success
end
it "should have the right title" do
get 'about'
response.should have_selector("title", content: #base_title+"About")
end
end
describe "GET 'help'" do
it "should be successful" do
get 'help'
response.should be_success
end
it "should contain the right title" do
get 'help'
response.should have_selector("title", content: #base_title+"Help")
end
end
end
b) a 'users_controller' spec file (with corresponding "describe UsersController do" statement):
require 'spec_helper'
describe UsersController do
render_views
describe "GET '/new'" do
it "should be successful" do
get 'new'
response.should be_success
end
it "should have the right title" do
get 'new'
response.should have_selector("title", content: "Sign up")
end
end
end
2) a 'requests' subfolder with the following 'layout_links' spec file:
require 'spec_helper'
describe "LayoutLinks" do
it "should have a Home page at '/'" do
get '/'
response.should have_selector('title', content: 'Home')
end
it "should have a Contact page at '/content'" do
get '/contact'
response.should have_selector('title', content: 'Contact')
end
it "should have an About page at '/about'" do
get '/about'
response.should have_selector('title', content: 'About')
end
it "should have a Help page at '/help'" do
get '/help'
response.should have_selector('title', content: 'Help')
end
it "should have a signup page at '/signup'" do
get '/signup'
response.should have_selector("title", content: "Sign up")
end
end
I initially added the following code to my "users_controller" file:
it "should have a signup page at '/signup'" do
get '/signup'
response.should have_selector("title", content: "Sign up")
end
The test failed when I ran it, but when I added it to the 'layout_links' spec file, it passed. This tells me that I am missing some fundamental aspect of RSpec and/or integration testing. Am happy to re-word this question to make it more universal, if necessary.
Your hunch is correct, there is some convention over configuration going on here.
Controller tests will work off the controller specified. So your PagesController test will work off...well, the PagesController. So the get 'home' line will try to get the home action in your Pages controller, the Pages controller is assume for all of those tests. Unless your Pages controller has a signup action it will error.
The requests type tests are for integration tests and don't assume a controller.
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
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.
The author, Michael Hartl, says:
Here the rule:
get "static_pages/home"
maps requests for the URI /static_pages/home to the home action in the StaticPages controller.
How? The type of request is given, the url is given, but where is the mapping to a controller and action? My tests all pass, though.
I also tried deleting all the actions in the StaticPagesController, which just looks like this:
class StaticPagesController < ApplicationController
def home
end
def about
end
def help
end
def contact
end
end
...and my tests still pass, which is puzzling. No, I deleted all my actions like this:
class StaticPagesController < ApplicationController
end
The 2nd edition of the book(online) is really frustrating. Specifically, the section about making changes to the Guardfile is impossible to follow. For instance, if I instruct you to edit this file:
blah blah blah
dog dog dog
beetle beetle beetle
jump jump jump
and make these changes:
blah blah blah
.
.
.
go go go
.
.
.
jump jump jump
...would you have any idea where the line 'go go go' should be in the code?
And the hint for exercise 3.5-1 is flat out wrong. If the author would put up a comment section at the end of every chapter, the rails community could self-edit the book.
Tests:
require 'spec_helper'
describe "StaticPages" do
let(:base_title) { "Ruby on Rails Tutorial Sample App" }
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 => "#{base_title} | 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 => "#{base_title} | Help")
end
end
describe 'About page' do
it "should have the h1 'About'" do
visit '/static_pages/about'
page.should have_selector('h1', :text => 'About')
end
it "should have the title 'About'" do
visit '/static_pages/about'
page.should have_selector(
'title',
:text => "#{base_title} | About")
end
end
describe 'Contact page' 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'" do
visit '/static_pages/contact'
page.should have_selector(
'title',
:text => "#{base_title} | Contact")
end
end
end
As you can see here:
http://guides.rubyonrails.org/routing.html#http-verb-constraints
it is just a shorthand for
match 'static_pages/home' => 'static_pages#home', :via => :get
Basically Rails infers from your url static_pages/home that you are referring to the StaticPagesController's home action.
Also, when you 'deleted' all your actions, you left the action definitions - which is what the test checks. It just checks if it can go to the home action of your staticpages controller. It doesn't matter if it does nothing, as long as it exists(at least that's what I think your tests does - care to post the tests also?)
If you delete
...
def home
end
...
from your controller, I'm pretty sure your tests will fail
I found an answer to this conundrum. First of all, this is a rails 'problem' not an rspec problem; if I add a route to routes.rb such as:
get "static_pages/dog"
...and then enter the url
http://localhost:3000/static_pages/dog
in my browser, rails complains:
Unknown action
The action 'dog' could not be found for StaticPagesController
Then if I add the dog action to the controller, then create a view,
everything works fine and dandy.
But if I then delete the dog action, and then use the same url,
http://localhost:3000/static_pages/dog
in my browser, this time I get a different result--instead of getting an error the view displays.
As it turns out, that inconsistent behavior is a rails 'feature' called default rendering, explained here:
http://guides.rubyonrails.org/layouts_and_rendering.html#rendering-by-default-convention-over-configuration-in-action
According to the docs, all that's needed to render a page is a route and a view--the action is optional.