Testing filling in the contact form without filling in one of the required fields in one test and then filling in the honey_pot field in another test. The tests when valid info is filled in are passing, but the two other specs are failing.
Update I've been running the test a couple of times and sometimes all the tests pass. Other times, the same specs fail.
Terminal output
3) Pages Home page it should behave like all static pages Footer Contact Form when honeypot is filled does not send an email
Failure/Error: expect(ActionMailer::Base.deliveries).to be_empty
expected empty? to return true, got false
Shared Example Group: "all static pages" called from ./spec/requests/pages_spec.rb:69
# ./spec/requests/pages_spec.rb:46:in `block (6 levels) in <top (required)>'
4) Pages Home page it should behave like all static pages Footer Contact Form when fields are not filled does not send an email
Failure/Error: expect(ActionMailer::Base.deliveries).to be_empty
expected empty? to return true, got false
Shared Example Group: "all static pages" called from ./spec/requests/pages_spec.rb:69
# ./spec/requests/pages_spec.rb:38:in `block (6 levels) in <top (required)>'
pages_spec.rb
require 'spec_helper'
describe "Pages" do
subject { page }
shared_examples_for "all static pages" do |path_name|
before { visit send(path_name) }
describe "Footer" do
describe "Contact Form" do
it { should have_selector('h7', text: 'Contact Us') }
context "when a valid message" do
it "sends an email" do
post contact_create_path, message: attributes_for(:message)
expect(ActionMailer::Base.deliveries.last.to).to eq(["#{ENV["MVP_USERNAME"]}"])
ActionMailer::Base.deliveries.clear
end
end
context "when fields are not filled" do
it "does not send an email" do
post contact_create_path, message: attributes_for(:message, name: '', body: '')
expect(ActionMailer::Base.deliveries).to be_empty
ActionMailer::Base.deliveries.clear
end
end
end
context "when honeypot is filled" do
it "does not send an email" do
post contact_create_path, message: attributes_for(:message, sweet_honey: 'bot')
expect(ActionMailer::Base.deliveries).to be_empty
ActionMailer::Base.deliveries.clear
end
end
end
end
end
describe "Home page" do
before { visit root_path }
it_should_behave_like "all static pages", :root_path
it { should have_text('Quality Cars') }
it { should have_title('Misawa Used Cars - Misawa Auto Sales') }
describe "Send a message" do
before do
fill_in "Name", with: 'name'
fill_in "Email", with: 'email#example.com'
fill_in "Phone", with: '999-9999-9999'
fill_in "Body", with: 'Hello'
click_button "Send"
end
describe "after the message is sent" do
it "should render the desired page with a flash" do
expect(page).to have_text('Quality Cars')
expect(page).to have_title('Misawa Used Cars - Misawa Auto Sales')
expect(page).to have_selector('.alert-box.success')
end
end
end
end
end
I was able to get the specs passing by clearing the ActionMailer::Base.deliveries before and after each of the specs where I tested the deliveries. I also rewrote the tests to make it DRYer using the before(:each) and after(:each) methods describe in Rspec's documentation. Update Even better, around(:each)
Improved Specs
describe "Contact Form" do
it { should have_selector('h7', text: 'Contact Us') }
describe "send a message" do
around(:each) { ActionMailer::Base.deliveries.clear }
context "when a valid message" do
it "sends an email" do
post contact_create_path, message: attributes_for(:message)
expect(ActionMailer::Base.deliveries.last.to).to eq(["#{ENV["MVP_USERNAME"]}"])
end
end
context "when fields are not filled" do
it "does not send an email" do
post contact_create_path, message: attributes_for(:message, name: '', body: '')
expect(ActionMailer::Base.deliveries).to be_empty
end
end
context "when honeypot is filled" do
it "does not send an email" do
post contact_create_path, message: attributes_for(:message, sweet_honey: 'bot')
expect(ActionMailer::Base.deliveries).to be_empty
end
end
end
end
Related
I am trying to write a rspec for sessions controller. But i am not able to do so.
I wanted to test controller for valid and invalid valid attributes. Tests should pass if valid attributes are passed for a particular user and should fail if invalid attributes are passed for a given user.
require 'rails_helper'
RSpec.describe SessionsController, type: :controller do
let(:user) { User.create(name: "some",email: 'other#example.com', password: 'rous',password_confirmation: "some") }
describe "get login path" do
it "login page" do
get :new
expect(response).to render_template('sessions/new')
end
end
describe "valid attributes" do
it "create a session" do
post :create, session: { email: user.email, password: user.password }
expect(response.status).to render_template('/users/#user.id')
end
end
describe "invalid attributes" do
it "does not create a session" do
post :create, session: { email: user.email, password: "12345" }
expect(response.status).to render_template('sessions/new')
end
end
describe "does not create a session" do
it "if email is empty" do
post :create, session: {password: "some"}
expect(response.status).to render_template('sessions/new')
end
it "if password is empty" do
post :create, session: {email: "some#gmail.com"}
expect(response.status).to render_template('sessions/new')
end
end
end
Describe "invalid attributes" and "valid attributes" are not working fine.
If email/password are wrong, user redirected to session#new page.
If email & password are correct, user should to redirected to user_path i.e., users show page.
You should really use a request or feature spec instead here as they drive the full stack. You not only want to test that your controller redirects somewhere - you really want to test that redirects somewhere and signs a user in. Preferably without poking inside the internals or mocking the actual authentication process that you're supposed to be testing in the first place.
Both the RSpec and Rails teams disencourage writing controller tests/specs for new applications. Test the behaviour of your application. Not how it does its job.
require "rails_helper"
RSpec.feature "User sign in", type: :feature do
let!(:user) { FactoryBot.create(:user) }
scenario "User signs in with valid crentials" do
visit "/sessions/new"
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign In"
expect(page).to have_text "You have been signed in"
end
scenario "User signs in with invalid crentials" do
visit "/sessions/new"
fill_in "Email", with: user.email
fill_in "Password", with: "nottherightpassword"
click_button "Sign In"
expect(page).to_not have_text "You have been signed in"
expect(page).to have_text "Invalid email or password"
end
end
Or as a lower level request spec:
require "rails_helper"
RSpec.describe "Sessions", type: :request do
let!(:user) { FactoryBot.create(:user) }
describe "POST /sessions" do
context "with valid credentials" do
it "redirects the user" do
post '/sessions',
params: { session: { email: user.email, password: user.password } }
expect(response).to redirect_to user_path(user)
follow_redirect!
expect(response.body).to include("You have been signed in")
end
end
context "with invalid credentials" do
it "does not redirect the user" do
post '/sessions',
params: { session: { email: user.email, password: "nottherightpassword" } }
expect(response).to_not redirect_to user_path(user)
expect(response.body).to include("Invalid email or password")
end
end
end
end
I have 'controllers/users_controller.rb'
def create
user = User.new(person_params)
if user.save
EmailSendJob.perform_later(user.email, 'random_password')
end
end
I have 'mailers/user_mailer.rb'
def user_new(user_to, password)
#password = password
mail to: user_to, subject: "Password for you"
end
I have 'jobs/email_send_job.rb'
def perform(email, password)
UserMailer.user_new(email, password).deliver_now
end
How do I do testing? Thank you
I saw 'email-spec', but can't understand it for my code
I have 'spec/controllers/users_controller_spec.rb'
require "spec_helper"
require "rails_helper"
require "email_spec"
describe UsersController do
User.delete_all
before(:all) do
#email_for_test = "222#222#mail.ru"
#user = User.new
#user.email = "2#2.ru"
#user.name = "test"
#user.save
end
it "create" do
post :create, params: {user: {email: #email_for_test,
name:"test",
description: "test"}}
user = User.last
expect(user.email).to eq(#email_for_test)
last_delivery = ActionMailer::Base.deliveries.last
last_delivery.body.raw_source.should include "This is the text of the email"
end
end
ActionMailer::Base.deliveries.last don't work
Maybe you have example. I would be very grateful
Try using ActionMailer::Base.deliveries.count
So for example:
it "sends an email" do
expect { UserMailer.user_new(email, password).deliver }.to change { ActionMailer::Base.deliveries.count }.by(1)
end
I tend to use email-spec in feature specs. A test will look something like this:
require 'rails_helper'
feature 'Admin creates purchase' do
include ActionView::Helpers::NumberHelper
given(:purchase) { build(:purchase) }
given(:new_purchase) { Purchase.last }
scenario 'with valid input' do
click_link 'Purchases'
click_link 'New Purchase'
fill_in 'Name', with: purchase.name
fill_in 'Email', with: purchase.email
fill_in 'Quantity', with: purchase.quantity
perform_enqueued_jobs do
click_button 'Create Purchase'
expect(page).to have_content 'The purchase was completed successfully'
open_email(purchase.email)
expect(current_email).to have_subject 'Receipt from My Super Awesome Company'
expect(current_email).to have_content "Name #{purchase.name}"
expect(current_email).to have_content "Total Charge #{number_to_currency(new_purchase.total)}"
end
end
end
You could probably do similar sorts of content checking in a controller spec.
ok, I think it is answer good.. I found also something -
it "sends an email" do
email = UserMailer.password_new(#email_for_test, "password_test").deliver
m = ActionMailer::Base.deliveries
expect(m.count).to eq(1)
expect(email.html_part.body).to include("Hello, your new password")
end
email = ActionMailer::Base.deliveries.last
(email.text_part || email.html_part || email).body
I'm writing the RSpec tests for the index action for Project. A project belongs_to a client, which belongs_to a user.
What I'm trying to do is create 30 instances of project to be used in pagination. All belonging to the same user.
When I run the tests, I'm giving the following error (I've tried rake db test:prepare):
Failure/Error: before(:all) { #projects = FactoryGirl.create_list(:project, 30, user: user) }
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken
factories.rb
FactoryGirl.define do
factory :user do
name "John Nana"
email "john#nana.com"
password "woopwoop1"
password_confirmation "woopwoop1"
end
factory :client do
name "Widget inc."
user
end
factory :user1 do
name "Bob Inc"
email "lol#catz.com"
password "nayy1"
password_confirmation "nayy1"
end
factory :project do
sequence(:name) { |n| "Project #{n}" }
fee "250"
client
end
end
project_pages_spec.rb
require 'spec_helper'
describe "create" do
let(:user) { FactoryGirl.create(:user) }
let(:submit) { "Create project" }
describe "when signed in" do
before do
capybara_sign_in(user)
#client = user.clients.create(name: "Widget inc.")
visit new_project_path
end
describe "with valid information" do
describe "from /projects" do
before do
visit projects_path
click_link "Add project"
fill_in "Project name", with: "Brochure"
fill_in "Fee", with: "1000"
select(#client.name, from: 'project_client_id')
end
it "should create a project and redirect to /projects" do
expect { click_button submit }.to change(Project, :count).by(1)
current_path.should == '/projects'
end
end
before do
fill_in "Project name", with: "Brochure"
fill_in "Fee", with: "1000"
select(#client.name, from: 'project_client_id')
end
it "should create a project" do
expect { click_button submit }.to change(Project, :count).by(1)
end
end
describe "with invalid information" do
before do
too_long_project = "a" * 50
fill_in "Project name", with: too_long_project
fill_in "Fee", with: "1000000000"
select(#client.name, from: 'project_client_id')
end
it "should not create a project" do
expect { click_button submit }.not_to change(Project, :count)
end
end
end
describe "when not signed in" do
before { visit new_project_path(user) }
it "should redirect to signin path" do
current_path.should == '/signin'
end
end
end
describe "index" do
let(:user) { FactoryGirl.create(:user) }
before do
capybara_sign_in(user)
visit projects_path
end
describe "pagination" do
before(:all) { #projects = FactoryGirl.create_list(:project, 30, user: user) }
after(:all) { Project.delete_all }
it { should have_selector('div.pagination') }
it "should list each user" do
Project.paginate(page: 1).each do |project|
expect(page).to have_selector('li', text: project.name)
end
end
it "should list all projects" do
#projects.each do |p|
expect(page).to have_selector('li', p.name)
end
end
end
end
You can use FactoryGirl's Sequences to generate unique email addresses:
factory :user do
name "John Nana"
sequence(:email) { |n| "person#{n}#example.com" }
password "woopwoop1"
password_confirmation "woopwoop1"
end
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 try to pass this friendship features specs using Capybara, Rspec and FactoryGirls on Rails.
For some reason I can't understand why, I'm always getting failing at this error. Looks like the session is not being destroyed after running a test.
1) Friendships user requests friendship signed in POST /:username/friendships requests friendship
Failure/Error: page.should have_content 'Successfully requested friendship.'
expected there to be text "Successfully requested friendship." in "× You are already signed in. meeter Messages Notifications Settings Settings Logout Explore Dates nearby Suggestions You Messages Notifications Friends Publish Help No ideas found with your criteria."
# ./spec/features/friendships_spec.rb:32:in `block (5 levels) in <top (required)>'
Complete spec
require 'spec_helper'
include Warden::Test::Helpers
Warden.test_mode!
describe "Friendships" do
before(:each) do
#user = FactoryGirl.create(:user, :male)
#friend = FactoryGirl.create(:user, :female)
end
describe "GET /:username/friendships" do
pending "display friendships"
end
context "user requests friendship" do
context "signed in" do
after(:each) do
Warden.test_reset!
end
describe "POST /:username/friendships" do
it "requests friendship" do
login_as(#user, scope: :user)
visit user_path(#friend)
click_button 'Request Friendship'
page.should have_content 'Successfully requested friendship.'
logout(#user)
end
pending "friend receives confirmation notification"
end
describe "POST /:username/friendships/cancels" do
pending "cancels a friendship request sent"
end
end
context "not signed in" do
describe "POST /:username/friendships" do
it "requests friendship" do
visit user_path(#friend)
click_button 'Request Friendship'
page.should have_content 'You need to sign in first to continue.'
end
end
end
end
Any idea how to pass this?