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.
Related
I have Rspec testing controller actions via visiting pages.
And when I'm declaring new object through let() for create and edit actions - it's all fine. But for delete it doesn't work and I have to declare instance variable to make it pass.
My goal is to get rid of instance variable declaration in delete action.
It stops me from finishing re-factoring and I want to know why this happen?
Maybe it's somehow related to Capybara scope.
Failed tests looks like:
Failure/Error: it {should have_content('delete')}
expected #has_content?("delete") to return true, got false
and
Failure/Error: expect{click_link('delete')}.to change(Crew, :count).by(-1)
Capybara::ElementNotFound:
Unable to find link "delete"
My whole test
require 'spec_helper'
describe 'CrewPage' do
subject {page}
let(:user) {FactoryGirl.create(:user)}
let(:crew) {Crew.create(name: name, secondname: secondname, rate: rate)}
let(:name) {'Name'}
let(:secondname) {'First'}
let(:rate) {1000}
before {sign_in(user)}
#==============================New page===========>>
describe 'new crew member page' do
before {visit new_crew_path}
it {should have_title('New member')}
let(:submit) {"Create"}
context 'invalid creation' do
it 'should not create crew member' do
expect{click_button submit}.not_to change(Crew, :count)
end
end
context 'valid crew member creation' do
before do
fill_in 'Name', with: name
fill_in 'Secondname', with: secondname
fill_in 'Rate', with: rate
end
it 'should create crew member' do
expect{click_button submit}.to change(Crew, :count).by(1)
end
end
end
#==============================Show page===========>>
describe 'show page' do
before {visit crew_path(crew)}
it {should have_title("#{crew.combine_names} profile")}
end
#==============================Edit page===========>>
describe 'edit page' do
let(:reload_n) {name*2}
let(:reload_sn) {secondname*2}
let(:reload_r) {rate*2}
before {visit edit_crew_path(crew)}
it {should have_title('Edit panel')}
context 'successfull edit' do
before do
fill_in 'Name', with: reload_n
fill_in 'Secondname', with: reload_sn
fill_in 'Rate', with: reload_r
click_button('Save')
end
it {should have_content(reload_n)}
it {should have_content(reload_sn)}
it {should have_content(reload_r)}
end
end
#==============================Delete action===========>>
describe 'delete action from index page' do
before do
#crew = Crew.create(name: name, secondname: secondname, rate: rate)
visit root_path
end
it {should have_content('delete')}
it 'should delete crew member' do
expect{click_link('delete')}.to change(Crew, :count).by(-1)
end
end
end
let block is not executed unless it is called in the test itself. Because you are not using this variable prior to visit_page, crew model is not created and hence it is not displayed on the page capybara is playing with. If you want it to execute before each test, you have to call let! instead:
let!(:crew) { Crew.create(name: name, secondname: secondname, rate: rate)}
I'm very new to rspec testing. I've tried the following test:
require 'spec_helper'
describe "CategoriesController" do
describe "#index" do
context "when signed in" do
it "should have the content 'Sign in'" do
visit categories_path
expect(page).to have_content('Sign in')
end
end
context "when signed in" do
it "should not have the content 'Sign in'" do
visit categories_path
expect(page).not_to have_content('Sign in')
end
end
end
end
Now, I will add some authentication but for not I just want one test to pass and the other to fail. At the moment both are failing, even though they are identical other than .to and .not_to
Any ideas what I'm doing wrong?
Your test looks like it ought to be in a Capybara feature spec, where the test imitates how a user interacts with a browser. But the describe "CategoriesController" do makes it look like you actually wrote a controller spec.
Try rewriting as such, after adding capybara to your Gemfile.
# in spec/features/sessions_spec.rb
require 'spec_helper'
feature "Sessions" do
scenario "when not signed in" do
visit categories_path
expect(page).to have_content('Sign in')
end
scenario "when signed in" do
visit categories_path
expect(page).not_to have_content('Sign in')
end
end
To debug the test once you have made it a feature spec, you can also add save_and_open_page like this:
scenario "when signed in" do
visit categories_path
save_and_open_page
expect(page).not_to have_content('Sign in')
end
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'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.
What am I doing wrong? I think all my ends are right. I am getting this error for
describe "visiting the edit page" do
describe "submitting to the update action" do
describe "visiting the user index" do
describe "as wrong user" do
FactoryGirl.create(:user, email: "wrong#example.com")}
and
describe "visiting Users#edit page" do
This is the error I am getting when I run rspec
syntax error, unexpected tIDENTIFIER, expecting keyword_end
describe "authorization" do
describe "for non-signed-in users" do
let(:user) {FactoryGirl.create(:user)}
describe "when attempting to visit a protected page" do
before do
visit edit_user_path(user)
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
describe "after signing in" do
it "should render the desired protected page" do
page.should have_selector('title', text: 'Edit user')
end
describe "when signing in again" do
before do
click_link "Sign out"
click_link "Sign in"
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
it "should render the default (profile) do
page.should have_selector('title', text: user.name)
end
end
end
end
describe "in the Users controller" do
describe "visiting the edit page" do
before {visit edit_user_path(user)}
it { should have_selector('title', text: 'Sign in') }
it {should have_selector('div.alert.alert-notice')}
end
describe "submitting to the update action" do
before { put user_path(user)}
specify {response.should redirect_to(signin_path)}
end
describe "visiting the user index" do
before {visit users_path}
it {should have_selector{'title', text: 'Sign in'}}
end
end
end
describe "as wrong user" do
let(:user) {FactoryGirl.create(:user)}
let(:wrong_user) {FactoryGirl.create(:user, email: "wrong#example.com")}
before { sign_in user}
describe "visiting Users#edit page" do
before {visit edit_user_path(wrong_user)}
it {should_not have_selector('title', text: 'Edit user')}
end
describe "submitting a PUT request to the Users#update action" do
before {put user_path(wrong_user)}
specify {response.should redirect_to(root_path)}
end
end
end
end
You are missing a " at the end of it "should render the default (profile) do.
Right off the bat
it "should render the default (profile) do
Is missing the end quote and be should be
it "should render the default (profile)" do
I had in the podspec this character ” instead of this ".