Multiple files upload with cocoon and capybara - ruby-on-rails

I have issue with testing uploading multiple files with capybara using cocoon. How can I find all fields with id: "image" and attach to each of them file?
Here is my test code:
click_link "Add photo"
wait_for_ajax
click_link "Add photo"
wait_for_ajax
page.all(:class, '.attach_fileds').each do |el|
attach_file( el, "#{Rails.root}/spec/assets/example.jpg")
end
click_button "Add"
expect(Post.count).to eq(1)
expect(Post.last.images.size).to eq(2)
Error message:
Unable to find file field #<Capybara::Element tag="input" path="/html/body/div/div/div/form[#id='new_post']/div[#id='educations']/div[1]/input[#id='image']">

You shouldn't have multiple elements with the same id, since thats illegal html. Based on your sample code (not sure what the :class selector is so guessing) you really want every element with a class of 'attach_field'. #attach_file doesn't take an element as its first parameter, instead it takes the name, id, or label text of the element. Since you already have the elements you can just call #set on each of them
page.all(:css, '.attach_field').each do |el
el.set "path of file to upload"
end
If instead you just want every file input you could do
page.all(:css, 'input[type="file"]').each do |el|
el.set "path of file to upload")
end
Also note that you need something between click_button "Add" and expect(Post.count).to eq(1) to make the test wait for the submission to finish - something like
expect(page).to have_text('Image Uploaded') # if the page adds text when image is uploaded
or
expect(page).to have_current_path('/some_new_path') # if the page url changes after the upload is complete

Related

How do I confirm a css element attribute with Capybara?

This may seem unusually basic but how do I confirm the presence of a pop up confirmation?
<a data-confirm="delete this video?" rel="nofollow" data-method="delete" href="/videos/21">Delete</a>
<a is the "tag"/"element" and data-confirm is an attribute. I want to test for the existence of the "data-confirm" attribute within the <a> element/tag
I have tried
expect(page).to have_css("a.data-confirm.delete this video?")
from
capybara assert attributes of an element
but no joy.
Edit:
I've tried the expectation from Arup's comment below
expect(page).to have_content "Content"
click_link "Delete"
expect(page).to have_css('a[data-confirm="delete this video?"]')
But it raises the following (same) error
Failures:
1) Visiting the video index page should search and save movies
Failure/Error: expect(page).to have_css('a[data-confirm="delete this video?"]')
expected #has_css?("a[data-confirm=\"delete this video?\"]") to return true, got false
but the page source shows it there and it is clearly working for the user
Any assistance would be very appreciated
You can write this expectation as:
expect(page).to have_css('a[data-confirm="delete this video?"]')
The answer by Arup is correct for the title of the question (and as he stated in the comments it's just valid CSS - https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors), however it's not actually testing the more detailed part of the question "how do I confirm the presence of a pop up confirmation". All it is doing is confirming the correct data attribute is on the link element to trigger the rails provided JS that should show a confirm.
If you wanted to actually test the confirm box is shown you would need to swap to using a JS capable driver - https://github.com/teamcapybara/capybara/tree/2.17_stable#drivers - and then use something like the following in your test
expect(page).to have_content "Content"
accept_confirm "delete this video?" do
click_link "Delete" # The action that will make the system modal confirm box appear
end
See - http://www.rubydoc.info/gems/capybara/Capybara/Session#accept_confirm-instance_method

Capybara and remote links

I have this link in records_path page:
link_to "CLICK HERE", edit_record_path(record), remote: true
The controller:
def edit
puts request.format # Just to show you part of the issue
end
And when clicked, it executes the edit.js.coffee and renders a modal for editing the record.
It works great. The problem I have is with Capybara.
context 'when on records list page' do
before { visit records_path }
context 'when clicking on "CLICK HERE"', js: true do
before { click_link('CLICK HERE') }
it 'shows the record name' do
expect(page).to have_content record.name
end
end
end
When I run the test, it raise an error:
Capybara::ElementNotFound: Unable to find link "CLICK HERE"
But if I remove the js: true from the context, it works (It executes the edit method on the RecordsController) but the printed format is html instead of js. I don't even have an edit.html, I just have the edit.js.coffee and that is the one that should be rendered in the test.
What am I doing wrong? If the link has the remote: true prop, and the test has the js: true shouldn't be enough for make it work?
In your setup you don't actually create a record. I am assuming this is the cause of your problem. The edit_record link will not show up if you do not have records to edit. I could be wrong but from what you pasted I think this could be the cause.

Testing ruby with rails, Element not found

I get the error:
Capybara::ElementNotFound:
Unable to find field "user_email"
And this is the test code:
feature 'User' do
given!(:user) { User.new(email: 'testuserid#example.com', encrypted_password: 'test') }
scenario 'opens sign_up page' do
visit new_user_session_path
expect(page).to have_content 'unique text on the page'
end
scenario 'signs in with invalid email' do
visit new_user_session_path
fill_in('user_email',with: 'ssd')
expect(page).to have_content 'unique text on the page'
end
end
My HTML file consists of this code literally:
unique text on the page
<br>
<input type="text" id="user_email">
So this proves that the path is correct because my first scenario runs correctly. It is visiting the right page. But still I get this error for second scenario in fill_in.
I have also tried element = page.find("user_email"), it gives same error.
What am I possibly doing wrong?
I have been scratching my head like hell.
Usually the reason for this is that the input isn't actually visible on the page. You can verify this by doing
fill_in('user_email', with: 'ssd', visible: false)
If that succeeds in finding the element, then you need to change your test to first perform whatever actions make the field visible before attempting to fill it in.
Your code seems right. Maybe you are visiting wrong url or you have used user_email id once more. But you can give a try with alternative syntax like following :
find("input[id$='user_email']").set "ssd"

How do I simulate an "Edit" or "Destroy" button click in Rails 3.2 w/ MiniTest?

How can I write an integration test for editing an item? My "create" test looks like this:
it "lets a user create a product" do
login_user
click_link("Products")
click_link("New")
fill_in "Identifier", :with => "MyString"
click_button "Create"
assert page.has_content?("Product was successfully created")
end
And that works great. What I am confused about is how to do the Edit and Destroy tests. My index page provides a list of all products. So first I use a factory to create a couple of products. Now I am in the situation where there are multiple "Edit" and "Destroy" buttons. I can't just say:
click_button "Destroy"
because there are two of them. How do I tell it which one to click?
And if I do get the correct "Destroy" button clicked, how do I hit the "OK" button in the Javascript window that pops up?
Assuming that you're using Webrat, you can use the "within" selector.
The Webrat "within" method takes a CSS selector as an argument. Supposing your "Destroy" button is in a div with an id like "#product-2", you can isolate that button with:
within "#product-2" do |scope|
scope.click_button "Destroy"
end
If you need to / would rather use XPath, you can do something like:
response.should have_xpath(xpath) do |button|
click_button(button)
end
Alternatively, if you are using Capybara, then you can use the "find" method:
find("#product-2").find("button").click
find(:xpath, "//div/div/button").click

Capybara + Webkit: How to test client side validations - "required" input elements?

Using Rspec and Capybara, I'm trying to test a failing validation for a form, where a "required" input is not filled in, so it fails. New navigators understanding HTML5 provide built-in validations, and I understand Capybara is using that as well. Before, I was using
page.should have_error
which doesn't work for me anymore.
Someone knows how to test this now?
Many thanks!
David
HTML5 client side validations are tricky to find. I found this post with a great answer.
The code is:
describe "when I leave required field empty" do
it "I get an the correct html5 validation error" do
#Leave the field empty
click_on "Save" # or whichever button triggers the submit
message = page.find("#field_id_attr").native.attribute("validationMessage")
expect(message).to eq "Please fill out this field."
end
end
Basically the way it works is that the field element has an attribute called "validationMessage" and the process is:
Click submit - this triggers the error message
Get a reference to the native(html) attribute(as opposed to the Capybara page object attribute) called "validationMessage". This will give you the value or the message itself.
Assert that the value is as expected.
I am not familiar with RSpec so I am not sure about what does have_error.
You should think about what you want to test exactly.
You surely don't want to test the exact behavior (what message is displayed, and how) as it is specific to each browser. What you want to test, because this is not specific to the browser, is the fact that the form is not submitted.
For instance, for a basic html form at root, with a required radio button "My value".
# Check form can not be submitted without the radio button
visit '/'
click_button 'Submit'
assert_equal '/', current_path
# Check form can be submitted with the radio button
visit '/'
choose 'My value'
click_button 'Submit'
assert_equal '/next', current_path
You should also consider to test only the presence of required in your html code, as the browser is supposed to work as expected (test only your code, not other's code)
If there is an error message, you can something along the lines of
page.should have_content("error")
This depends on how you handle the errors, and whether you use javascript or not.
This is an old post, however I will try to answer it
have_error is a method provided by webkit, to check e.g. if ajax requests or javascript in general running fine
I use to test my validations in my model specs:
describe 'validations' do
it { is_expected.to validate_presence_of :competitor_name }
it { is_expected.to validate_presence_of :chassi }
it { is_expected.to validate_presence_of :auction }
it { is_expected.to validate_presence_of :car_template_id }
end
or like
expect(FactoryGirl.create(:customer)).to be_valid
to check if my Factory is valid.
If you need to check your notices by targeting invalid inputs, you could test the html of your notice by capybara with the following:
it 'searches for specific order_car by chassi and model' do
visit order_cars_search_detailed_path
fill_in 'order_car_chassi', with: '123456'
select 'Octavia', from: 'order_car_car_template_car_template_id'
click_button 'Search Order'
expect(page).to have_content('THIS IS MY NOTICE')
expect(page).to have_content('123456')
end
Hope I could help some others running into this question.

Resources