Capybara fill_in isn't working - capybara

I'm working in Rails 4.2.1 and doing testing using Capybara 2.4. I have an issue with some input fields not getting filled in using the capybara fill_in method.
I'm not getting an ElementNotFound error, I'm getting this:
expected: "2018-01-10"
got: ""
(compared using ==)
Here's the test code:
Note: fill_in works for the email, password and program name fields but not for the primary_training_start, primary_comp_start and primary_comp_end.
it 'create program' do
visit '/'
fill_in 'Email', with: 'john#doe.com'
fill_in 'Enter Your Password', with: 'test123'
click_on 'Log In'
fill_in 'Program Name', with: 'My Training'
find('.exclusive').click
click_on 'Next Step'
all('.creator-wayfinder li')[1].click
expect(page).to have_content('SET THE SCHEDULE')
fill_in 'primary_training_start', with: '2018-01-10'
fill_in 'primary_comp_start', with: '2018-02-10'
fill_in 'primary_comp_end', with: '2018-03-10'
expect(find_field('primary_training_start').value).to eq('2018-01-10')
expect(find_field('primary_comp_start').value).to eq('2018-02-10')
expect(find_field('primary_comp_end').value).to eq('2018-03-10')
click_on 'Show Program Schedule'
end
And here's the HTML for the primary_training_start field:
<div>
<mark>Start Training</mark>
<span class="datepicker" date-format="M/d/yyyy" date-set="{{program.training_calendar_details.primary_training_start}}">
<input required
ng-model="program.training_calendar_details.primary_training_start"
name="primary_training_start"
type="text" tabbable tabindex="0" />
</span>
<errors for="primary_training_start" model="program.training_calendar_details.primary_training_start"></errors>
</div>
I tried this: Capybara won't fill in form fields (although it finds them) but didn't have any luck.

Try having an id for input
<input required
ng-model="program.training_calendar_details.primary_training_start"
name="program[training_calendar_details][primary_training_start]"
id="primary_training_start"
type="text" tabbable tabindex="0" />
fill_in use first parameter as id

Related

Capybara cannot find a link on a modal which changes on button press

I have a rails project using rspec 3.4.0 capybara 2.6.2 and capybara-webkit 1.8.0.
I am writing a feature test for a flow on my site which looks like the following:
scenario "Buyer creates a seller profile", :js => true do
click_link("SELL ON MYSITE",match: :first)
expect(page).to have_text("Reach thousands of customers in your area")
click_link("Create an Activity",match: :first)
expect(current_path).to eql (new_seller_profile_path)
fill_in "seller_profile[business_name]", :with => "Test company"
fill_in "seller_profile[business_email]", :with => "test#email.com"
fill_in "seller_profile[business_phone_number]", :with => "07771330510"
fill_in "seller_profile[business_description]", :with => "This is a test company"
find('label[for="social"]').click
find("#facebook-placeholder").click
fill_in "seller_profile[business_facebook_url]", :with => "https://www.facebook.com/test"
click_button("CREATE AN ACTIVITY")
------this button opens a modal after the page changes --------
fill_in "seller_profile[requested_postcode]", :with => "EH21 8PB"
click_button("Submit")
save_and_open_screenshot
------this is where it goes wrong-------
click_link("Continue")
expect(page).to have_text("Choose the type of activity that you want to create")
end
The click_link continue fails with error:
Failure/Error: click_link("Continue")
Capybara::ElementNotFound:
Unable to find link "Continue"
The link actually does exist - when you click on the submit button some javascript executes which changes the contents of the modal to display some new text and a new button. However for some reason click_link does not wait or look in the modal, it fails straight away.
Having added a save_and_open_screenshot call we can see this situation as the modal javascript has yet to execute as we can still see the submit button :
Interestingly the mouse seems to not be on the Submit button as it should have just clicked it?
How can I make the click_link wait until the continue button appears?!
This is the javascript which executes on press of 'submit' added to the modal which changes it:
$('#gate .modal-body .intro').text('Congratulations, we are available in your location, please continue to create your activity.');
$('#gate .modal-footer').append('<a class="btn btn-lg btn-primary" href="/events/new/">Continue</a>');
Seemingly adding a couple of sleeps in has fixed it. I don't know if this is 'right' solution. If somebody has a better way or potentially a better way I would love you to help me find it :
fill_in "seller_profile[requested_postcode]", :with => "EH21 8PB"
sleep 2
click_button("Submit")
sleep 2
click_link("Continue")

Capybara: Test current path to page created object

After creating new object should redirect to action show. How me check current path?
feature 'add lost pet' do
given(:data) {attributes_for(:lost_pet)}
background do
visit root_path
click_on 'Register new lost pet'
end
scenario 'add new lost pet with valid data' do
within '#new_lost_pet' do
fill_in 'Name', with: data[:name]
fill_in 'Type', with: data[:type]
fill_in 'Breed', with: data[:breed]
fill_in 'Gender', with: data[:gender]
fill_in 'Size', with: data[:size]
fill_in 'Colour', with: data[:colour]
fill_in 'Age', with: data[:age]
fill_in 'Age unit', with: data[:age_unit]
fill_in 'Description', with: data[:description]
fill_in 'Collar description', with: data[:collar_description]
check 'Desexed', :checked
check 'Microchipped', :checked
fill_in 'Microchip number', with: data[:microchipped_number]
select '2015', from: "lost_pet[date_missing(1i)]"
select 'October', from: 'lost_pet[date_missing(2i)]'
select '10', from: 'lost_pet[date_missing(3i)]'
fill_in 'Rewald', with: data[:rewald]
fill_in 'Image', with: data[:image]
fill_in 'Adress lost', with: data[:adress_lost]
click_on 'Create'
end
expect(current_path).to eq lost_pet_path(????)
end
For lost_pet_path i need id, but how me create id? Or how better check path in Capybara?
expect(current_path).to eq ...
doesn't use Capybara's waiting behavior - which means since click_on is asynchronous (isn't waiting for anything on screen, or for the submit to complete) your test may be very flaky. You're much better off using
expect(page).to have_current_path(expected_path)
since that will use Capybara's waiting behavior while checking for the expected path.
On top of that you have the issue that the LostPet object isn't yet created right after the click_on executes (asynchronous) so calling LostPet.last then will most likely return nil. You have a couple of options here
Wait for some text thats going to appear on the page
expect(page).to have_text('Lost Pet created') # shows in a flash message, or header on the show page, etc
# since you know the show page is visible now you can query for the last LostPet created
expect(page).to have_current_path(lost_pet_path(LostPet.last))
or, use the regex option with have_current_path and don't worry about verifying the actual id of the url
expect(page).to have_current_path(/lost_pet\/[0-9]+/) # match the regex to whatever your urls actually are
or something like that
Since the created record is the most recent one in the database, MyActiveRecordModel.last can be used.
lost_pet = LostPet.last
expect(current_path).to eq lost_pet_path(lost_pet)

Capybara finds textfield but does not fill it

I have this textfield:
<p>
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" type="text" value="user4#example.com" />
</p>
And in my test I'm trying to fill it like this:
fill_in "Email", with: "bla"
save_and_open_page
Capybara seems to find it, yet does not fill it... I also tried this:
fill_in "user_email", with: "bla"
and:
fill_in "user[email]", with: "bla"
But didn't work either, this is weird since I have 46 examples running and I'm only getting trouble with this particular textfield and I can't see what's wrong with it.
Am I missing something obvious? Any help would be appreciated.

Capybara/Poltergeist causing unexpected results in request spec in Rails 3.2 app

Is there an alternative I can use to Capybara's save_and_open_page? I have written a request spec that test the user signup form. Upon successful signup, which this test should yield, this test should be passing, but it's not.
Yet when I do save_and_open_page at the end, all the form fields are blank. I can mirror this in the development environment doing the data entry myself and everything passes, so I am struggling to understand what's wrong. I can't afford to let this go because obviously this is a critical test.
I've only been doing TDD for a little while, so any tips or tricks about this stack (Capybara and Poltergeist) would be helpful. I am not having similar difficulties in other request specs using the same stack.
Here is the request spec:
it 'allows a user to subscribe', js: true do
visit root_url
click_link "Pricing"
click_button "Subscribe", match: :first
fill_in "First name", with: "Marky"
fill_in "Last name", with: "Mark"
fill_in "Company", with: "The Funky Bunch"
fill_in "subscription_email", with: "marky.mark#thefunkybunch.com"
fill_in "Password", with: "MyString"
fill_in "Password confirmation", with: "MyString"
fill_in "Credit Card Number", with: "4242424242424242"
fill_in "Security Code on Card (CVV)", with: "123"
select "July", from: "Card Expiration"
select "2014", from: "card_year"
check "chkACCEPT"
click_button "Subscribe to myapp"
# The line below fails, but a save_and_open page just shows a blank form
current_path.should_not eq(new_subscription_path)
page.should have_content("Thank You")
end
Poltergeist provides screenshots which can be used instead of save_and_open_page:
save_screenshot('/path/to/file.png', :full => true)
However your comment "# The line below fails" seems very consistent to "save_and_open page just shows a blank form".

Rails Capybara not seeing fields

I feel like I'm going insane here. Doing a routine capybara test of my Post model. Specifically, making sure the new page redirects to the newly created post after a valid submission. So in my spec/requests folder, I've got this:
describe "Valid post submission --" do
it "should log in a user and redirect to new post" do
# Sign in works find, so I won't reproduce it
# Make a blogpost
Post.destroy_all
fill_in :name_here, with: "Post Name Here"
fill_in :content_here, with: "This is the content of a really short post."
screenshot_and_open_image
click_on "Post It"
screenshot_and_open_image
puts current_path
page.should have_selector 'h2', text: "prohibited this post"
page.should have_selector 'h1', text: "Post Name Here"
page.should have_selector '.alert', text: "Post was successfully created."
page.should have_selector 'title', text: full_title('Post Name Here')
end
The screenshots and puts are there to clarify what's going on. There are basically two different cases. In
I just leave the fields be and test for the default IDs ("post_name"
and "post_content"); obviously the above test is for case two:
I change the field ids to "name_here" and "content_here" to test if
the label names or anything else is interfering. That's the one the spec of which is
above.
In case 2 the post is getting rejected because Capybara can't find either field.
In case 1, only the content would be empty, but the name field would be filled with the content.
The precise error in case 1 is:
2) Posts Invalid post - should refresh with error if content empty
Screenshot: /Users/myusername/rails/appname/tmp/capybara/screenshot_2013-03-14-22-37-36.634.png
Failure/Error: fill_in :post_name, with: "Post Name Here"
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'post_name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:43:in `block (3 levels) in <top (required)>'
Case 2 doesn't throw an error about not finding the appropriate content, I believe because the label has that id as well.
This is ridiculous, because I took a snapshot of the HTML durin the test, just before it errors. Here's case 2 -- both cases look 90% the same here, apart from that ID difference:
<form accept-charset="UTF-8" action="/posts" class="new_post" id="new_post" method="post">
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
<div class="field">
<label for="post_name">Name</label>
<br><input id="name_here" name="post[name]" size="30" type="text">
</div>
<div class="field text-area">
<label for="post_content">Content</label>
<br><textarea cols="50" id="content_here" name="post[content]" rows="20"></textarea>
</div>
<div class="actions btn-group">
<input class="btn" name="commit" type="submit" value="Post It">
</div>
</form>
Note the clear existence of the post_content field. In cases where both fail (Case 1), there are both content_here and name_here fields. So the fields are there. And capybara is generally working (this sort of thing works find in other parts of my app). And the problem isn't a conflict with the label name, because putting a different id on the input fields doesn't help capybara find them.
By the way, this all works perfectly in reality.
Any idea at all what's going on here? I'm super frustrated/clueless.
UPDATE -- Following user2172816's advice, I changed my HAML so the HTML looks like this:
<form accept-charset="UTF-8" action="/posts" class="new_post" id="new_post" method="post">
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"></div>
<div class="field">
<label for="post_name">Name</label>
<br><input id="name" name="post[name]" size="30" type="text">
</div>
<div class="field text-area">
<label for="post_content">Content</label>
<br><textarea cols="50" id="content" name="post[content]" rows="20"></textarea>
</div>
<div class="actions btn-group">
<input class="btn" name="commit" type="submit" value="Post It">
</div>
</form>
The test now looks like this:
# Make a blogpost
Post.destroy_all
fill_in "Name", with: "Post Name Here"
fill_in "Content", with: "This is the content of a really short post."
page.should have_selector 'h2', text: "prohibited this post"
page.should have_selector 'h1', text: "Post Name Here"
page.should have_selector '.alert', text: "Post was successfully created."
page.should have_selector 'title', text: full_title('Post Name Here')
But it's still erroring (in new parts of the same spec, too!):
1) Posts Invalid post - should refresh with error if content empty
Screenshot: /Users/username/rails/appname/tmp/capybara/screenshot_2013-03-14-23-54-38.072.png
Failure/Error: fill_in :name, with: "Post Name Here"
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:43:in `block (3 levels) in <top (required)>'
2) Posts Invalid post - should refresh with error if name empty
Screenshot: /Users/username/rails/appname/tmp/capybara/screenshot_2013-03-14-23-54-38.274.png
Failure/Error: fill_in :name, with: ""
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:33:in `block (3 levels) in <top (required)>'
3) Posts Valid post submission -- should log in a user and redirect to new post
Screenshot: /Users/username/rails/appname/tmp/capybara/screenshot_2013-03-14-23-54-38.459.png
Failure/Error: fill_in :name, with: "Post Name Here"
Capybara::ElementNotFound:
cannot fill in, no text field, text area or password field with id, name, or label 'name' found
# (eval):2:in `fill_in'
# ./spec/requests/posts_spec.rb:67:in `block (3 levels) in <top (required)>'
The attribute "for" of label should be the "id" of the input element, i.e.
<label for="name_here">Name</label>
<br><input id="name_here" name="post[name]" size="30" type="text">
And in the spec you should call:
fill_in 'Name', with: "Post Name Here"

Resources