How do you use Capybara to test elements with contenteditable="true"?
With this spec...
scenario "Using valid input" do
fill_in "name", with: "Zinn"
click_button "Update"
expect(page).to have_content("Update successful!")
end
... and this eco file...
<td id="name" contenteditable="true"><%= #name %></td>
<td><button id="update" class="btn btn-sm btn-default">Update</button></td>
I get this failing spec...
Capybara::ElementNotFound:
Unable to find field "name"
Here's how I ended up solving the problem.
feature "Editing", js: true do
scenario "with valid input" do
el = find(:xpath, "//div[#contenteditable='true' and #name='name']")
el.set("Zinn")
el.native.send_keys(:return)
expect(page).to have_content("Update successful!")
expect(page).to have_content("Zinn")
end
end
According to this thread it looks like you should be able to use the fill_in helper on contenteditable divs, but I couldn't get that to work.
In 2020 I can do this
find('.selector').send_keys 'this text gets filled in'
Related
I'm running an acceptance test that includes logging in via /users/sign_in.
How do I set up the test so I can "click" the submit button within a Rspec Capybara test?
Seems that Devise disables the Login submit button and runs javascript to make things work.
<%= f.submit "Log in" %>
produces:
<input type="submit" name="commit" value="Log In" tabindex="4" data-disable-with="Log In" />
The data-disable-with, which devise needs, seems to be breaking capybara testing. I would just like to click the button as per my acceptance test below.
it "logs in and shows success message" do
visit '/users/sign_in'
login_as(user, :scope => :user)
within(".login-details") do
fill_in 'Email', with: user.email
fill_in 'Password', with: 'fakepassword'
end
click_button 'Log in'
expect(page).to have_content 'Success'
end
Is producing:
Capybara::ElementNotFound: Unable to find button "Log in" that is not disabled
Note: I have multiple pages that logging in can send a user to, this example is the simplest test that reveals this bug. So no my goal is not to 'make sure devise works', incase you were wondering 'why do they need this?'
The data-disable-with attribute is used by Rails UJS to change the buttons text after it's been clicked so wouldn't be affecting this test. Looking at the HTML element you posted the value of the button is 'Log In' so, since case matters, you'd need to do
click_button 'Log In'
rather than 'Log in'
I do wonder why you have login_as(user, :scope => :user) in the same code where you're filling in the username and password though, you'd normally only use login_as when you wanted to bypass actually filling in the form and logging in.
Tell me please,why does it happen?
I can't understand, if I write:
feature "Article Creation" do
#here i write (:all)
before(:all) do
sign_up_helper
end
I get the error:
Article Creation allows user to visit to creating article page
Failure/Error: fill_in :article_title, :with => 'test_title'
Capybara::ElementNotFound:
Unable to find field :article_title
or
1) Article Creation allows user to visit to article page
Failure/Error: expect(page).to have_content I18n.t('articles.articles_new')
expected to find text "New Article:" in "Toggle navigation Blog Rails New Contacts Sign in --- !ruby/hash:ActionController::Parameters controller: devise/sessions action: new {\"controller\"=>\"devise/sessions\", \"action\"=>\"new\"} nil You need to sign in or sign up before continuing. Sign in: Email Password Remember me Sign up Forgot your password?"
but, if I write:
feature "Article Creation" do
#here i write(:each)
before(:each) do
sign_up_helper
end
It's Ok. All tests works. My question -WHY?
This is my test:
*#before all test visitor signs up
#here I've changed :all and :each*
feature "Article Creation" do
before(:all) do
sign_up_helper
end
scenario "allows user to visit to article page" do
visit new_article_path
expect(page).to have_content I18n.t('articles.articles_new')
end
scenario "allows user to visit to created article page" do
visit new_article_path
fill_in :article_title, :with => 'test_title'
fill_in :article_text, :with => 'example_text'
click_button 'Save Article'
expect(page).to have_content 'example_text'
end
This is sign_up_helper method:
#spec/support/session_helper.rb
def sign_up_helper
visit new_user_registration_path
fill_in :user_email, :with => 'user#example.com'
fill_in :user_username, :with => 'mike'
fill_in :user_password, :with => 'secure123!##'
fill_in :user_password_confirmation, :with => 'secure123!##'
click_button 'Sign up'
end
This is html form:
<p>
<label for="article_title">Title</label><br/>
<input type="text" name="article[title]" id="article_title" />
</p>
<p>
<label for="article_text">Text</label><br/>
<textarea name="article[text]" id="article_text">
</textarea>
</p>
Environment for each test is set anew, I think. New session, cookies, etc. In many cases, even brand new users are generated. So one "global" login is not possible.
Even if it were possible, it would still be a problem, as it introduces spec order dependency which is bad. Imagine that one of your specs logs user out. Then each subsequent spec would fail, because user is not logged in anymore.
To prevent this, make sure that each spec sets its own environment as it needs it (user logins, method stubs, etc.), without relying on side-effects from previously executed specs (which may or may not persist).
Hello dear Stackoverflowers.
I'm having some seriously insanely annoying trouble with my capybara test. It seems to have a mind of its own and will sometimes decide to run with zero issue and sometimes decide to not find elements, click anything and generally just suck. I have no idea why this is.
I've been researching for days trying to find sure up my logic, find the 'best' ways of finding and clicking elements or filling in fields and haven't gotten any further. Please help, if I still had hair I would be pulling it out.
Also I'm using the Selenium Web Driver. All gems are up to date.
Thanks in advance.
It will randomly decide to not click on 'Amtrak 1234' and sometimes entirely miss the find('#atedrop4').click or will decide to click elements not even close being specified in my test. I'm very confused, and in desperate need of some help.
it 'can view the itinerary print and export', js: true do
visit '/admin/login'
fill_in 'Email', with: "evan#tripwing.com"
fill_in 'Password', with: "guest"
click_button 'Login'
click_link 'Trips'
expect(page).to have_content 'Trips'
click_link('View Trip Page', match: :first)
new_window=windows.last
page.within_window new_window do
expect(page).to have_content 'A Test To Forget'
find('.showItinerary').click
expect(page).to have_content "DAY 1, AMSTERDAM"
find(:xpath, "//a[#href='#flight1day1']").click
expect(page).to have_content "SINGAPORE AIRLINES FLIGHT 326"
click_link 'Add to Calendar'
find('.ategoogle').click
new_window=page.driver.browser.window_handles.last
page.driver.browser.switch_to.window(new_window) do
fill_in "Email", with: "evan#tripwing.com"
fill_in "Password", with: "boarder1"
find("#signIn").click
expect(page).to have_content "evan#tripwing.com"
page.driver.browser.close
end
find(:xpath, "//a[#href='#flight1day1']").click
find(:xpath, "//a[#href='#train1Day1']").click
click_link('Export to Calendar', match: :first)
find('.ategoogle').click
new_window=page.driver.browser.window_handles.last
page.driver.browser.switch_to.window(new_window) do
expect(page).to have_content "evan#tripwing.com"
page.driver.browser.close
end
find(:xpath, "//a[#href='#train1Day1']").click
find(:xpath, "//a[#href='#carRentalDay1']").click
click_link('Export to Calendar', match: :first)
find('.ategoogle').click
new_window=page.driver.browser.window_handles.last
page.driver.browser.switch_to.window(new_window) do
expect(page).to have_content "evan#tripwing.com"
page.driver.browser.close
end
find(:xpath, "//a[#href='#carRentalDay1']").click
find(:xpath, "//a[#href='#hotelDay1']").click
click_link('Export to Calendar', match: :first)
find('.ategoogle').click
new_window=page.driver.browser.window_handles.last
page.driver.browser.switch_to.window(new_window) do
expect(page).to have_content "evan#tripwing.com"
page.driver.browser.close
end
find(:xpath, "//a[#href='#hotelDay1']").click
find(:xpath, "//a[#href='#carTransfer1Day1']").click
click_link('Export to Calendar', match: :first)
find('.ategoogle').click
new_window=page.driver.browser.window_handles.last
page.driver.browser.switch_to.window(new_window) do
expect(page).to have_content "evan#tripwing.com"
page.driver.browser.close
end
find(:xpath, "//a[#href='#carTransfer1Day1']").click
One thing that helps is to use the save_and_open_page in your capybara tests. This way you can open up the html source of the test page and verify if your html id's and classes actually exist / are rendering the way you think they are. This has especially been the case for me when I'm doing nested forms and adding html to the page dynamically.
Using capybara+rspec how can i compile a form with empty fields?
I'm testing an edit resource page, so i have a compiled form and want to clean its text fields. This is a partial of test:
context "when submitting" do
before { visit edit_post_path(post) }
it {should have_content('Editing')}
it {current_path.should == edit_post_path(post)}
describe "whit invalid information" do
before do
fill_in "post[title]", :with => "" #not working
fill_in "post[body]", :with => "" #not working
click_button "update"
end
it {current_path.should == edit_post_path(post)}
end
describe "whit valid information" do
before do
fill_in "post[title]", with: "some"
fill_in "post[body]", with: "some"
click_button "update"
end
it {should have_content('some')}
it {should have_content('some')}
it {current_path.should == post_path(post)}
end
end
Check manually actual ID/name/label of relevant field in generated HTML of Edit-page via Chrome:InspectElement of Firefox:Firebug. High chances they are different to "post[title]".
UPD. Try to fill in empty strings manually on the page. Does it work fine? I mean error displayed and the route is correct. Firing "Update"-button and getting an error you're not on the edit_post_path anymore. It happens bc in case of unsuccessful #post.update you're rendering Post#edit-view from Post#update action.
Likely problem is that post[title] and post[body] are the names of the fields, and not the IDs.
Also, something you might want to look into to make your tests a little more rigorous: capybara has a builtin within function that yields a block in which you can perform more actions. Check out the documentation on the front page of the gem page: https://github.com/jnicklas/capybara. It would probably look something like:
describe "whit invalid information" do
before do
within("#post") do
fill_in "title", :with => ""
fill_in "body", :with => ""
click_button "update"
end
end
it {current_path.should == edit_post_path(post)}
end
In my rspec request I did:
puts page.html
and I can see:
<label for="account_account_name">Account name</label>
<input id="account_name" name="account[name]" size="30" type="text" />
My rspec request:
require 'spec_helper'
describe "Account pages" do
subject { page }
describe "new" do
before { visit account_new_path }
describe "with valid information" do
before do
#puts page.html
fill_in "Account name", with: "acme inc."
fill_in "Company name", with: "acme inc."
..
end
it "should create a account" do
expect { click_button "Create Account"}.to change(Account, :count).by(1)
end
end
end
end
Running:
rspec spec/requests/account_pages_spec.rb
I get the error:
1) Account pages new with valid information should create a account
Failure/Error: fill_in "Account name", with: "account name1"
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'Account name' found
# (eval):2:in `fill_in'
# ./spec/requests/account_pages_spec.rb:14:in `block (4 levels) in <top (required)>'
Why can't the element be found?
Again did output the page.html in the before block and it did output the correct html that I pasted above.
The label's for attribute doesn't correctly identify the input field.
Please try this:
fill_in "account[name]", :with => "acme inc."