I am getting errors while doing integration tests with rspec and the problem here lies with the fill_in , can anyone explain me why this is happening??
require 'rails_helper'
describe 'navigate' do
describe "index" do
before do
#user = User.create(email:"test#test.com", password:"test123", password_confirmation:"test123", first_name:"Umair", last_name:"Ahmed")
end
it "can be reached successfully" do
visit posts_path
expect(page.status_code).to eq(200)
end
end
describe "new and create" do
before do
user = User.create(email:"test#test.com", password:"test123", password_confirmation:"test123", first_name:"Umair", last_name:"Ahmed")
login_as(user, scope: user)
visit new_post_path
end
it "has a new form" do
expect(page.status_code).to eq(200)
end
it "will fill in details of form" do
fill_in "post[date]", with: Date.today
fill_in "post[rationale]", with: "something rationale"
click_on "Save"
expect(page).to have_content("something rationale")
end
it "will have a user associated with it" do
fill_in "post[date]", with: Date.today
fill_in "post[rationale]", with: "User Association"
click_on "Save"
expect(User.first.posts.first.rationale).to eq("User Association")
end
end
end
post.rb (model)
class Post < ApplicationRecord
belongs_to :user, optional: true
validates_presence_of :date, :rationale
end
views/posts/new.html.erb
<%= form_for #post do |f| %>
<%= f.date_field :date %>
<%= f.text_area :rationale %>
<%= f.submit "Save" %>
<% end %>
I can't seem to understand what is wrong here, can anyone point out what rubbish I am doing here?
UPDATE: I fixed the issue by just changing login_as(user, scope: user) to
login_as(user, scope: :user) , or we can type like this if you like this type of syntax
login_as(user, :scope => :user)
Related
I have this integration test that is giving me errors that seem to have to do with fill_in
require 'rails_helper'
describe 'navigate' do
let(:user) {FactoryGirl.create(:user)}
let(:post) do
Post.create(date: Date.today, rationale: "Rationale", user_id: user.id)
end
before do
login_as(#user, :scope => :user)
end
describe 'index' do
before do
visit posts_path
end
it 'can be reached successfully' do
expect(page.status_code).to eq(200)
end
it 'has a title of Posts' do
expect(page).to have_content(/Posts/)
end
it 'has a list of posts' do
post1 = FactoryGirl.build_stubbed(:post)
post2 = FactoryGirl.build_stubbed(:second_post)
visit posts_path
expect(page).to have_content(/Rationale|content/)
end
it 'has a scope so that only post creators can see their posts' do
other_user = User.create(first_name: 'Non', last_name: 'Authorized', email: 'nonauth#example.com',
password: "password", password_confirmation: "password")
post_from_other_user = Post.create(date: Date.today, rationale: "This post shouldn't be seen",
user_id: other_user.id)
visit posts_path
expect(page).to_not have_content(/This post shouldn't be seen/)
end
end
describe 'new' do
it "has a link from the homepage" do
visit root_path
click_link("new_post_from_nav")
expect(page.status_code).to eq(200)
end
end
describe 'delete' do
it 'can be deleted' do
logout(:user)
delete_user = FactoryGirl.create(:user)
login_as(delete_user, :scope => :user)
post_to_delete = Post.create(date: Date.today, rationale: 'rationale', user_id: delete_user.id)
visit posts_path
click_link("delete_post_#{post_to_delete.id}_from_index")
expect(page.status_code).to eq(200)
end
end
describe 'creation' do
before do
visit new_post_path
end
it 'has a new form that can be reached' do
expect(page.status_code).to eq(200)
end
it 'can be created from a new form page' do
fill_in 'post[date]', with: Date.today
fill_in 'post[rationale]', with: "Some rationale"
click_on "Save"
expect(page).to have_content("Some rationale")
end
it 'will have a user associated with it' do
fill_in 'post[date]', with: Date.today
fill_in 'post[rationale]', with: "User Association"
click_on "Save"
expect(User.last.posts.last.rationale).to eq("User Association")
end
end
describe 'edit' do
it "can be edited" do
visit edit_post_path(post)
fill_in 'post[date]', with: Date.today
fill_in 'post[rationale]', with: "Edited content"
click_on "Save"
expect(page).to have_content("Edited content")
end
it "cannot be edited by a non authorized user" do
logout(:user)
non_authorized_user = FactoryGirl.create(:non_authorized_user)
login_as(non_authorized_user, :scope => :user)
visit edit_post_path(post)
expect(current_path).to eq(root_path)
end
end
end
I review the views/post/_form.html.erb file:
<%= form_for #post, class: "form-horizontal" do |f| %>
<% if #post.errors.any? %>
<% #post.errors.full_messages.each do |error| %>
<%= js add_gritter(error, title: "Overtime App Notification", sticky: false, image: :notice) %>
<% end %>
<% end %>
<div class="form-group">
<%= f.label :date, class: "col-sm-2 control-label" %>
<%= f.date_field :date, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :rationale, class: "col-sm-2 control-label" %>
<%= f.text_area :rationale, class: "form-control" %>
</div>
<%= render partial: 'status', locals: {f: f} if current_user.type == 'AdminUser' %>
<%= f.submit 'Save', class: 'btn btn-primary btn-block' %>
<% end %>
I can't tell what is going wrong here. If I inspect element, it's there:
This is my post.rb model file:
class Post < ActiveRecord::Base
enum status: {submitted: 0, approved: 1, rejected: 2}
belongs_to :user
validates_presence_of :date, :rationale
scope :posts_by, ->(user) {where(user_id: user.id)}
end
The tests were passing yesterday, not sure what happened.
You're calling login_as with #user, but #user is never defined, you probably want login_as(user).
Always try to retrace your steps, if something was working before, think about what code you introduced between the last time it worked and when it began failing.
Checking status codes is generally a bad smell for feature tests, just check for things the user can see.
Don't use the eq matcher with current_path instead use the have_current_path matcher provided by Capybara.
I am facing this error when running an rspec test. I have tried click_link "Title 1" and assigning Article.create to a variable but the same error appears.
Failure/Error: click_link article.title
Capybara::ElementNotFound:
Unable to find link "Title 1"
comment_spec.rb
require "rails_helper"
describe 'navigate' do
let(:user) { FactoryGirl.create(:user) }
let(:article) do
Article.create(title: "Title 1", description: "Some description", user_id: user.id)
end
before do
login_as(user, :scope => :user)
end
describe 'create' do
before do
visit articles_path
end
it"permits a signed in user to write a review" do
click_link article.title
fill_in "Content", with: "An awesome article"
click_button "Post"
expect(page).to have_content("An awesome article")
expect(current_path).to eq(article_path(article.id))
end
end
end
spec/factories/user.rb
FactoryGirl.define do
sequence :email do |n|
"test#{n}#example.com"
end
factory :user do
name 'Tester'
email { generate :email }
password "asdfasdf"
password_confirmation "asdfasdf"
end
EDIT:
article/index.html.erb
<div class="tab-pane active" id="tab1">
<% #articles.each do |article| %>
<%= render 'article', article: article %>
<% end %>
</div>
_article.html.erb
<%= link_to article.title, article_path(article) %>
let is lazy loading which means that the block is not evaluated until you call it.
before do
article # calls the block
visit articles_path
end
An alternative is to use let! which is not lazy loading:
require "rails_helper"
describe 'navigate' do
let(:user) { FactoryGirl.create(:user) }
let!(:article) do
Article.create(title: "Title 1", description: "Some description", user_id: user.id)
end
before do
login_as(user, :scope => :user)
end
describe 'create' do
before do
visit articles_path
end
it"permits a signed in user to write a review" do
click_link article.title
fill_in "Content", with: "An awesome article"
click_button "Post"
expect(page).to have_content("An awesome article")
expect(current_path).to eq(article_path(article.id))
end
end
end
I`ve got these strange issues I dont know how to fix it. Please help me if you can.
Here is a testing result:
1) Admin can edit a hotel
Failure/Error: visit edit_admin_hotel_path(hotel)
URI::InvalidURIError:
bad URI(is not URI?):
# ./spec/requests/admin_spec.rb:32:in `block (2 levels) in <top (required)>'
2) Admin can edit a user
Failure/Error: visit edit_admin_user_path(admin)
URI::InvalidURIError:
bad URI(is not URI?):
# ./spec/requests/admin_spec.rb:54:in `block (2 levels) in <top (required)>'
rake routes shows me nice edit routes for users and hotels:
edit_admin_hotel GET /admin/hotels/:id/edit(.:format) admin/hotels#edit
edit_admin_user GET /admin/users/:id/edit(.:format) admin/users#edit
And everything works just fine if I start server and check it manually. So I have no idea where these issues comes from. Thanks for any help!
And my admin_spec.rb file:
require 'spec_helper'
describe "Admin" do
let(:admin) { FactoryGirl.create(:user) }
let(:hotel) { FactoryGirl.create(:hotel) }
before(:each) do
sign_up_as_admin admin
visit admin_hotels_path
end
subject { page }
it { expect(page).to have_content("Manage Hotels") }
it { expect(page).to have_content("Manage Users") }
it { expect(page).to have_link("Sign out") }
it { expect(page).to have_content("List of hotels") }
it { expect(page).to have_content("Hello, Admin") }
it "can add a hotel" do
click_link "Add Hotel"
expect(current_path).to eq(new_admin_hotel_path)
fill_in 'name', with: "TestHotel"
fill_in 'price', with: "666"
fill_in 'star_rating', with: "5"
expect { click_button "Submit" }.to change(Hotel,:count).by(1)
expect(current_path).to eq(admin_hotel_path(1))
end
it "can edit a hotel" do
visit edit_admin_hotel_path(hotel)
end
it "can delete a hotel" do
visit admin_hotel_path(hotel)
expect { click_link "Delete hotel" }.to change(Hotel,:count).by(-1)
#expect { click_link "Delete hotel" }.to redirect_to(admin_hotels_path)
end
it "can create a new user" do
click_link "Add User"
expect(current_path).to eq(new_admin_user_path)
expect(page).to have_content("Create New User")
fill_in "Name", :with => "user"
fill_in "Email", :with => "user#auser.com"
fill_in "Password", :with => "user.password"
fill_in "password_confirmation", :with => "user.password"
expect { click_button "Create User" }.to change(User,:count).by(1)
expect(current_path).to eq(admin_users_path)
end
it "can edit a user" do
visit edit_admin_user_path(admin)
end
end
Edit/update actions in users_controller.rb:
# GET admin/users/1/edit
def edit
#user = User.find(params[:id])
render "edit", status: 302
end
# PATCH/PUT admin/users/1
def update
#user = User.find(params[:id])
if #user.try(:update_attributes, user_params)
render "edit", notice: 'User was successfully updated.'
else
render action: 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation, :admin)
end
And user/edit.html.erb:
<% provide(:title, "Edit user") %>
<h1>Update profile</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for([:admin, #user]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Save changes" %>
<% end %>
<%= button_to 'Delete User', [:admin, #user], :data => { confirm: 'Are you sure?' }, method: :delete %>
</div>
</div>
Update 1:
I found out that these bad URI(is not URI?) errors also in hotel_controller and comment_controller while testing edit action. These errors in all of my controllers in edit actions and I dont know what cousing them :(
Your edit action is wrong:
def edit
#user = User.find(params[:id])
render "edit", status: 302
end
A 302 status means that the response is a redirect and that the Location header in the response contains the URI (relative or absolute) to redirect to. Capybara will be looking for this header and probably winds up trying to do URI.parse(nil).
It's not clear to me why you are setting the status here at all
In your spec_helper have you included the url_helpers?
config.include Rails.application.routes.url_helpers
I'm working through Michael Hartl's Rails tutorial, and I'm running into an issue in section 7.3.3. I receive this error message:
ArgumentError in Users#new
Showing /Users/Anuraag/rails_projects/sample_app/app/views/users/new.html.erb where line #6 raised:
First argument in form cannot contain nil or be empty
when I run the following rspec:
bundle exec rspec spec/requests/user_pages_spec.rb -e "signup with invalid information"
at the following line:
<%= form_for(#user) do |f| %>
Here is my code. Please also let me know how I should improve this question if I'm not framing it well: I'm pretty new to StackOverflow as well
app/views/users/new.html.erb:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
app/assets/controllers/users_controller.rb:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
if #user.save
# Handle a successful save.
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
spec/requests/user_pages_spec.rb
require 'spec_helper'
describe "User pages" do
subject { page }
describe "signup page" do
before { visit signup_path }
it { should have_content('Sign up') }
it { should have_title(full_title('Sign up')) }
end
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before { visit user_path(user) }
it { should have_content(user.name) }
it { should have_title(user.name) }
end
describe "signup" do
before { visit signup_path }
let(:submit) { "Create my account" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
end
describe "with valid information" do
before do
fill_in "Name", with: "Example User"
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "foobar"
fill_in "Confirmation", with: "foobar"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
end
In your new.html.erb you have specified form_for(#user) that means you need to have some value in instance variable #user before calling the new action.
You can do it in two ways :
one way is define an action new in your controller which would be called before rendering your new.html.erb layout. For eg:
def new
#user = User.new
end
other way is that in your form itself you could specify something like
<%= form_for(User.new) do |f| %>
Defining it in your new action is more standard way of doing it.
The order of actions in controller file matters. I had the same error until I figure out the problem on order of action methods.
Example.
Controller file
def edit
#post = Post.find(params[:id])
end
def update
end
private
def post_params
params.require(:post).permit(:title, :body)
end
I was working on edit action and was getting same error as you. The problem was I have written the edit action under private action. once I changed the order of this actions. It worked like a charm.
What I was trying to achieve ?
I was trying to take the values of post instance variable and use it into html form.
I dont see a new action on you controller.
def new
#user = User.new
end
I maybe made indirectly, but it couldn't hurt defining it yourself.
From you title that may be why the #user variable is nil, it wasn't defined.
In my Rails app, if a user wants to delete his own account he will first have to enter his password in my terminate view:
<%= form_for #user, :method => :delete do |f| %>
<%= f.label :password %><br/>
<%= f.password_field :password %>
<%= f.submit %>
<% end %>
This is my UsersController:
def terminate
#user = User.find(params[:id])
#title = "Terminate your account"
end
def destroy
if #user.authenticate(params[:user][:password])
#user.destroy
flash[:success] = "Your account was terminated."
redirect_to root_path
else
flash.now[:alert] = "Wrong password."
render :terminate
end
end
The problem is that I can't seem to find a way to test this with RSpec.
What I have is this:
describe 'DELETE #destroy' do
before :each do
#user = FactoryGirl.create(:user)
end
context "success" do
it "deletes the user" do
expect{
delete :destroy, :id => #user, :password => "password"
}.to change(User, :count).by(-1)
end
end
end
However, this gives me an error:
ActionView::MissingTemplate:
Missing template users/destroy, application/destroy with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder]}. Searched in:
* "#<RSpec::Rails::ViewRendering::EmptyTemplatePathSetDecorator:0x007fa7f51310d8>"
Can anybody tell me what I'm missing here or suggest a better way to test this action?
Thanks for any help.
OK, this is my solution:
describe 'DELETE #destroy' do
context "success" do
it "deletes the user" do
expect{
delete :destroy, :id => #user, :user => {:password => #user.password}
}.to change(User, :count).by(-1)
end
end
end
The before :each call I had before was useless (this is not an integration test after all). The password has to be passed in like this: :user => {:password => #user.password} which I didn't know until reading this thread.