Capybara can't find file - ruby-on-rails

I'm getting this error when running RSpec:
Failures:
1) Creating a new movie saves the movie and shows the new movie's details
Failure/Error: attach_file "Poster image", with: "#{Rails.root}/app/assets/images/interstellar.jpg"
Capybara::FileNotFound:
cannot attach file, [:with, "/Users/Ian/code/courses/ruby_on_rails_1/flix-tdd/app/assets/images/interstellar.jpg"]does not exist
However, I check and it looks like the file is there:
File.exist?("#{Rails.root}/app/assets/images/interstellar.jpg")
=> true
File.exist?("/Users/Ian/code/courses/ruby_on_rails_1/flix-tdd/app/assets/images/interstellar.jpg")
=> true
What am I missing here?

Why not?
attach_file "Poster image", "#{Rails.root}/app/assets/images/interstellar.jpg"
http://www.rubydoc.info/github/jnicklas/capybara/Capybara/Node/Actions#attach_file-instance_method

Related

Capybara/Rspec not catching ActionController::UnpermittedParameters error

I was in the processing in adding a field to an ActiveRecord model and the corresponding view. Before I started, I had a full green test run. I started with writing the following test:
scenario "with all correct info" do
create_vendor "vendor.email#example.com", "vendor_passowrd"
create_consumer "consumer.email#example.com", "password"
sign_in_with "consumer.email#example.com", "password"
click_link "New Order"
select 'vendor.email#example.com', from: "Vendor"
fill_in "Order text", with: "my normal order"
click_button "Submit"
expect(page).to have_content "my normal order"
end
I added the field to the model using the proper rails migration and the route entry.
I would have expected the test to fail with a ActionController::UnpermittedParameters because I have not yet updated the controller. However, this is the failure I am getting:
"Failure/Error: expect(page).to have_content "my normal order"
When I test in the browser, I do get the ActionController::UnpermittedParameters, but not in the automated test.
My question is should the test get the ActionController::UnpermittedParameters error?
Capybara simulates a web browser request, so it will get back an error page from Rails. The UnpermittedParameters error will not propagate up to the spec code itself.
This sounds like it's working correctly.

Capybara isn't checking a checkbox in rspec feature test

I am attempting to create a feature test where a checkbox needs to be checked and for whatever reason Capybara is not checking the box.
I am using:
rspec: 3.0.4 and capybara: 2.4.1
When I print out a snapshot of the view, the checkbox isn't checked.
When I run the checkbox code in pry it returns the string "checked" but when I print a snapshot the checkbox still is not checked and my test does not pass. I'm curious if there is another way to get this checkbox to check.
Here is my current code so far:
Feature Test:
background do
discussion_group
#user2 = FactoryGirl.create(:user)
add_user_to_user_role_for_group(group, #user2)
admin_login
add_user_to_admin_role_for_group(group, #user)
visit groups_path
click_on 'Email Group'
end
scenario 'sending a valid email' do
valid_form
expect(page).to have_content group_email_success_notification
expect_count_of_deliveries_to_be 1
end
Macro:
def valid_form
fill_in 'group_email_subject', with: new_text
fill_in 'group_email_body', with: Faker::Lorem.words(200).join("\s")
check "group_email_#{#user2.id}_"
click_on "Send Email"
end
The output of my test is that I must have 1 user selected meaning that I don't have a user checked. When I run the check line in console here is what I get:
[10] check('group_email_10_')
=> "checked"
Any help is greatly appreciated.
I'd use:
page.check('insert #id, .class, or value')\
for example:
input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes"
page.check('puppy_gooddog') or page.check('puppy[gooddog]')

having trouble testing upload file with Capybara attach_file method

I'm having trouble trying to test whether image upload works with paperclip using Capybara's attach_file method.
rspec returns these errors below:
Failures:
1) Upload Background Image cannot upload a background image
Failure/Error: page.attach_file('#artist_background_image', Rails.root + 'spec/Fixtures/Snow.jpg')
Capybara::ElementNotFound:
Unable to find file field "#artist_background_image"
# ./spec/models/artist_spec.rb:65:in `block (2 levels) in <top (required)>'
my test is listed below. I assumed the choose file button is the selector for attach_file so I used the id of the selector '#artist_background_page'.
describe 'Upload Background Image', js: true do
before :each do
p '================='
pp Artist.all
#artist = Artist.first || Artist.create(artist_name:'Double Stuff Oreos', email:'i#love.oreos', password:'letmein')
visit "/artists/" + #artist.id.to_s
pp #artist.id
pp #artist.artist_name
p #artist.errors.full_messages
click_button 'Log in'
fill_in 'Email', with: 'i#love.oreos'
fill_in 'Password', with: 'letmein'
page.find('#loginButtonModal').click
page.find('#addBackgroundImagePrompt').click
page.attach_file('#artist_background_image', Rails.root + 'spec/Fixtures/Snow.jpg')
p Rails.root + 'spec/Fixtures/Snow.jpg'
click_button 'upload'
end
it "cannot upload a background image", js: true do
backgroundURL = #artist.background_image.url.include?('Snow.jpg')
p #artist.background_image.url
expect(backgroundURL).to be_truthy
end
end
However when I change the selector to just 'artist_background_page' without the id '#' symbol. rspec gives me different error:
...."================="
[]
"is_active_session is called"
#<Artist id: 1, artist_name: "Double Stuff Oreos", route_name: "double-stuff-oreos", created_at: "2014-07-20 17:20:48", updated_at: "2014-07-20 17:20:48", password_digest: "$2a$04$vgozdgieklXPjJ9Ri4Cv1e1d/hme0ybNnSEGXrmob5z...", remember_token: nil, email: "i#love.oreos", description: nil, youtube: nil, twitter: nil, facebook: nil, instagram: nil, hometown: nil, confirmation_code: nil, is_confirmed: nil, background_image_file_name: nil, background_image_content_type: nil, background_image_file_size: nil, background_image_updated_at: nil>
1
"Double Stuff Oreos"
[]
"is_active_session is called"
#<Pathname:/Users/bob/rails_projects/audience/spec/Fixtures/Snow.jpg>
"/background_images/original/missing.png"
"Hello from update"
"Logged in!"
An error occurred in an after hook
ActiveRecord::RecordNotFound: Couldn't find Artist with 'id'=1
occurred at /Users/shuo/.rvm/gems/ruby-2.1.2/gems/activerecord- 4.1.4/lib/active_record/relation/finder_methods.rb:320:in `raise_record_not_found_exception!'
F....
Failures:
1) Upload Background Image cannot upload a background image
Failure/Error: expect(backgroundURL).to be_truthy
expected: truthy value
got: false
# ./spec/models/artist_spec.rb:74:in `block (2 levels) in <top (required)>'
In this case, the model was created but the errors says that it cannot find it for some reason...
Is there any other method I can use to attach files in capybara and test successfully uploads?
Possibilities for failure:
Wrong path for file upload
Wrong method to use or invalid use of method
something wrong with server
This error:
Capybara::ElementNotFound:
Unable to find file field "#artist_background_image"
shows that capybara can't find a field named #artist_background_image. What you need to do is to reference the file upload field by its name.
Suppose you have
<input id="artist_background_image" name="file_upload" type="file">
Then you can reference the field like:
page.attach_file('file_upload', Rails.root + 'spec/Fixtures/Snow.jpg')
With that, capybara will know what field to upload through.
I know this is a late response but I think it will help other people facing this issue.
This might be the case if you're using simple_form gem.
Note that it does automatically generate ids for your form elements, hence manually id-ing elements yourself is futile!
You can make sure of this by manually id-ing a form element then view the source on you browser. You'll defiantly see that your manually-assigned ids aren't anywhere in the page source.
There is; however, a naming convention that simple_form follows to id form elements.
object_attribute
The example bellow might clarify this even more (HAML exmaple):
= simple_form_for #user do |f|
= f.input :image, as: :file
simple_form will then automatically generate an id for the form element image as so (object_attribute):
id="user_image"
Now you can simply make use of this naming convention to target ids in your test. Hope this helps.

Capybara::ElementNotFound - How to click on specific button with id using Capybara

Trying to access this button on root url:
here is html
with this test:
feature "New comment button" do
scenario "User can add new comment on root page", :js => true do
visit root_path
id = 152
click_button("#button_#{id}")
within("#comment_row_#{id}") do
fill_in('content', :with => 'this is a comment')
click_button('create comment')
page.must_have_flash_message('Successfully created')
end
end
and geting this:
Capybara::ElementNotFound: Unable to find button "#button_152"
How to get this element using id ?
I am using selenium-web-driver
EDIT
WHAT I TRIED
# page.driver.browser.switch_to.frame 'top-frame' # Selenium::WebDriver::Error::NoSuchFrameError: Unable to locate frame: top-frame
# page.find('#button_152').click # not working
# click_button("#button_152") # not working
# first(:xpath, '//button[#id="button_152"]').click
2.This is an overview of frames :
all iframes are just google chrome addons
4.link to full html
You can read about switching windows and frames here: http://docs.seleniumhq.org/docs/03_webdriver.jsp#moving-between-windows-and-frames
Ruby specific bindings here: https://code.google.com/p/selenium/wiki/RubyBindings
Capybara handling iframes: handling iframe with capybara ruby
As for your problem, here's an example you can edit:
within_frame 'evernoteFilingTools' do
click_button("#button_#{id}")
#button_#{id} # not working
#page.find("#button_#{id}",:visible => true).click # does not work as well
within("#comment_row_#{id}") do
fill_in('content', :with => 'this is a comment')
click_button('create comment')
page.must_have_flash_message('Successfully created')
end
end
You should replace evernoteFilingTools with the iframe ID that contains the content you want to manipulate
Sometimes, it can be thrown off by invalid markup. This HTML has a div (<div class="icons">) inside a table, which is not valid. Try running the markup through a validator such as http://validator.w3.org/ and fix any errors it reports. That might fix your Capybara problem as well.

created data did not appear when testing

hye, I'm new to BDD testing and testing particularly. I'm using rspec, factory_girl_rails, selenium and capybara gem. I want to test for editing a data and save it like so :
it "edit consultant" do
# c = FactoryGirl.create(:consultant)
c = Consultant.create(
orgorcom: "xyz",
year_id: 8,
bidang: "IT & Networking",
project: "E-Sw",
professional_fee: "1000000",
role: "Database Architect",
user_id: 19,
nopkj: "075899 "
)
visit "/consultants?year=#{Time.now.year}"
string = "#consultant#{c.id}"
page.find(string).click_link('Edit')
fill_in "Organization / Company" , :with => c.orgorcom + "aaa"
fill_in "Field", :with => c.bidang + "aaa"
fill_in "Project" , :with => c.project + "aaa"
fill_in "Role", :with => c.role + "aaa"
fill_in "Professional fee", :with => c.professional_fee + 111
click_button "Save"
expect(page).to have_content "Data updated."
sleep 10
# c.destroy
# find('a[href="/consultants/6144/edit?year=2013"]').click
end
But the data I created did not appear & I get this message
1) the consultation edit consultant
Failure/Error: page.find(string).click_link('Edit')
Capybara::ElementNotFound:
Unable to find css "#consultant6157"
when I tried click on existing data like below, it passed.
page.find("#consultant6144").click_link('Edit')
I am able to print out the consultant id but still the record mysteriously did not appear before the test ends (which the db will rollback).
This is a known issue if you're using Selenium for browser testing, with transactional fixtures configured in your spec_helper. Selenium will run in a different thread and with a different database connection than the one being used by Rspec to create your database objects inside transactions, therefore the Selenium thread won't be able to see them.
For these kind of specs, you will need to not use transactional fixtures and use something like database_cleaner to create objects at the start of your specs and truncate/delete them afterwards.
Your problem doesn't seem related to FactoryGirl. The error message thrown by Capybara indicates that the object's id was properly concatenated into the string, but the corresponding CSS wasn't found in the page.
I would recommend you install the launchy gem by inserting this into your Gemfile:
group :development, :test do
gem 'launchy'
end
That will enable you to use the save_and_open_page method in your feature specs. Then insert this method right before the line that's provoking the error, like so:
# ...
save_and_open_page
page.find(string).click_link('Edit')
# ...
When save_and_open_page is called, your default browser will open at the same page. Then you can manually inspect the page's HTML and find out if it does, in fact, have the element you're looking for and, if it doesn't, why that happens.

Resources