I have this code, I am trying to click on the button to test its functionality using guard and capybara. I get an undefined method error on guard when I have it written like this. It comes back with no errors if I comment out the click_button line. It should render a response that the import was successful as well which is being displayed by an index page.
require 'rails_helper'
require 'spec_helper'
RSpec.describe "Imports", type: :request do
it "checks the import page." do
get '/imports'
click_button "submit"
end
end
how long does the it take to load the element? if > 2 seconds (capybara default wait time is 2s) then it's most likely you will get the undefined method error...
Try increasing capybara's timeout or do it for that element only:
click_button "submit", wait: 10
If that doesn't solve your issue then assure "submit" is the correct path to your element...
By default Capybara::DSL is only included in tests of type :feature, are you also including it in type :request?
Related
Im trying to set up a (basic) test for a new feature I am going to implement. I have a job controller and instead of default showing all jobs I like to hide all the ones which is archived. I tried different ways but it seems like i am missing a piece or two of this puzzle. First i tried with calling 'visit' but get the message it does not exist. Second approach is using 'render' but that also ends up in a error saying render does not exists. (can i even use these methods in a controller spec?)
Is it wrong to put this in a controller test?
2 last test are causing errors
require "rails_helper"
require "spec_helper"
describe JobsController, :type => :controller do
context 'GET index' do
it "should be successful" do
get :index
expect(response).to be_success
end
it "renders the index template" do
get :index
expect(response).to render_template("index")
end
it "should not show any archived jobs as default" do
visit jobs_path
page.should have_no_content("Archived")
end
it 'should show the headers' do
render :template => 'job/index', :layout => 'layouts/job'
rendered.should_not contain('Archived')
end
end
end
Capybara is used for feature specs, and its matchers can be used in view specs.
Controller specs, by default, don't actually render the view because they're the wrong place to be checking for page content - https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs
You should probably move some of your tests to feature tests/view tests
I am doing my hello world test application in an already completed project and am experiencing some scenarios and am puzzled by what I am seen is happening.
I am using:
Capybara
Cucumber
And selinium web driver for when we need Javascript
All of this on a Sinatra app
RSpec separately, but that is not the interest.
Problem:
When running cucumber tests as cucumber features/#{feature_name}.feature, and given that I am on a specific page. I can find elements by CSS ID but can't click on them.
When(/^I log in with email "(.*?)" and password "(.*?)"$/) do |email, password|
step %{I am on login page}
expect(page).to have_css('#login-form')
expect(page).to have_css('#login-button')
within("#login-form") do
fill_in '#username', with: email
fill_in '#password', with: password
click_button 'dfalkjsdfalsdkfja dflkjasdf alkdsjfasd lfkjsf s' # Which should fail, but odesn't :'(
end
click_button 'Sign In'
# click_button '#login-button' # This fails
end
The following test will pass even if I use a completely random non existent ID for #login-form. And as you see I have a button with some silly text. Also if I give it as an ID, no difference. The test passes.
But when I use them alone without the within block, the the elements are not found.
But above you see expect(page).to statements find them.
The above is some what similar to the example I see in the Capybara repo.
My Questions:
Can I use CSS selectors to target ex: #login-form
Should using a non existing selector in the within block fail? My case it doesn't.
Why is some thing like fill_in '#password', with: 'password' fail saying element not found while the above assertion seems to find it?
I am a newby, so a suggestion where things might have gone wrong in terms of setting up. Example link would also be great.
PS:
Forgot to ask, considering the example in the repo, what is 'Email' in the following fill_in block. Doesn't seem to be a id of the element.
fill_in 'Email', :with => 'user#example.com'
Update
After some playing around, I find the following working (finding the element and filling/clicking it). But the within block doesn't fill in the form. Can any config effect the within block as I explain.
When(/^I log in with email "(.*?)" and password "(.*?)"$/) do |email, password|
step %{I am on login page}
find('form#login-form').find('input#username').set email
find('form#login-form').find('input#password').set password
find('form#login-form').find('#login').click
within("form#login-form") do
fill_in 'input#username', with: email
fill_in 'input#password', with: password
click_button '#login'
end
end
I'm trying to write all my Capybara code to not use any CSS or funny matchers. For acceptance test purposes, I'm using Capybara to navigate only by button and link text that is visible to the user.
So I have a really simple test that asserts that an administrator can edit any user:
it 'allows an administrator to edit any user' do
user = login_admin_user
user1 = FactoryGirl.create(:user)
click_link "Users"
current_path.should eq(users_path)
click_link "Edit" # This is the problem
current_path.should eq(edit_user_path(user1))
fill_in "Last name", with: "Myxzptlk"
click_button "Update User"
page.should have_content("Myxzptlk")
end
Of course the problem line above is not specific enough; there will be 2 lines in the table (user and user1). I'm pretty new to TDD, so how do I use Capybara to select the correct link using only visible text?
I'm not sure why you're avoiding 'CSS or funny matchers'. If you don't want to put them in your test, abstract them away into helper methods.
In my specs I have a helper method like this:
module FeatureHelper
def within_row(text, &block)
within :xpath, "//table//tr[td[contains(.,\"#{text}\")]]" do
yield
end
end
end
And then in my specs I can call it like:
within_row(user1.name) do
click_link 'Edit'
end
The helper module goes inside the spec/support folder, and then gets loaded into my specs by doing:
config.include FeatureHelper, type: :feature
in my spec_helper.rb.
In Firefox, if I try to submit a post without a title, I get: 1 error prohibited this post from being saved.
But when I run my test. It's a different story.
My Post model has validates_presence_of :title. My test looks like:
require 'spec_helper'
describe 'Users' do
it 'registered users should not be able to post without a title', :js => true do
user = Factory(:user)
visit new_post_path
current_path.should eq(new_post_path)
fill_in 'post[markdown_description]', :with => 'Bar'
click_on 'Submit your post'
page.should have_content('error')
end
end
By the way, I am using Selenium (:js => true), because my submit button is actually an anchor link with some JS. Basically, when the link is clicked, JS triggers the form to be submitted.
Rspec returns:
Running: spec/requests/users_spec.rb
F
Failures:
1) Users registered users should be able to post
Failure/Error: page.should have_content('error')
expected there to be content "error" in ""
# ./spec/requests/users_spec.rb:13:in `block (2 levels) in <top (required)>'
Finished in 7.9 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/requests/users_spec.rb:4 # Users registered users should be able to post
The request may not make it to the controller action if you have before_filters. Check the log to make sure that the correct parameters are posting and that the action is not redirecting.
Another option is to include this in your spec:
click_on 'Submit your post'
save_and_open_page
which opens the current page in the browser so you can see what is actually being rendered.
I'm building a Rails 3 app using Devise, with Capybara for UI testing. The following test is failing:
class AuthenticationTest < ActionController::IntegrationTest
def setup
#user = User.create!(:email => 'test#example.com',
:password => 'testtest',
:password_confirmation => 'testtest')
#user.save!
Capybara.reset_sessions!
end
test "sign_in" do
# this proves the user exists in the database ...
assert_equal 1, User.count
assert_equal 'test#example.com', User.first.email
# ... but we still can't log in ...
visit '/users/sign_in'
assert page.has_content?('Sign in')
fill_in :user_email, :with => 'test#example.com'
fill_in :user_password, :with => 'testtest'
click_button('user_submit')
# ... because this test fails
assert page.has_content?('Signed in successfully.')
end
end
... but I have no idea why. As you can see from the code, the user is being created in the database; I'm using the same approach to create the user as I did in seeds.rb.
If I run the test through the debugger, I can see the user in the database and verify that the page is loading. But still the authentication fails; I can verify this because if I change the assertion to test for the failure case, the test passes:
# verify that the authentication actually failed
assert page.has_content?('Invalid email or password.')
I'm used to Rails 2, & using Selenium for this sort of testing, so I suspect I'm doing something daft. Could someone please point me in the right direction here?
I was having the same issue and found a thread with a solution:
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
For the DatabaseCleaner stuff to work you'll need to include the database_cleaner gem. If you haven't used it before, you may need to rake db:test:prepare before rerunning your tests. I hope this works for you, too!
I've run into a similar problem before. Setting the password directly has some weird effects because it's supposed to be encrypted and stored with a salt--sometimes it works for me and other times it doesn't. I have a hard time remembering which specific cases were problematic. I'd recommend the following, in this order (for simplicity)
Verify that the password field is getting filled in properly and passed as the right param (not necessary if you're using Devise's autogenerated view and haven't touched it)
if your site can run in development mode (i.e. no log in bugs), then just boot it up and log in manually
If not, insert debugger as the first line in your sessions_controller. Then check params and make sure the password is correct and in params[:user][:password].
If you didn't override Devise's sessions_controller, then you can find your Devise path with bundle show devise. Then look for the create action within (devise path)/app/controllers/devise/sessions_controller.rb
Change your test setup to create a user through the web interface, to ensure the password gets set properly, then try running your test again
I had the same issue with a setup fairly similar to yours. In my case, switching to ActiveRecord sessions in the initializer solved the problem.
Additionally, make sure you call #user.skip_confirmation! if you are using the "confirmable" module in devise.