I'm trying to set up cucumber tests in docker so I found out that I need to use xvfb in order to at least run tests without GUI. After hours of struggling I've finally run tests, but now:
I'm testing sending data through the form. I'm filling necessary fields and I'm clicking the button, but it doesn't do anything. It works fine when I'm browsing through the page; it is okay when I run cucumber locally without docker (with or without headless Firefox), but it fails in that one case. When I'm debugging it sees the button, click returning 'ok', but it does nothing. Also, current_url doesn't change, and Product is not saved to DB (so I assume button does not get clicked).
Could it be a problem with not compiled scripts files, maybe JavaScript doesn't work properly in headless Firefox or something else?
I've updated capybara to latest version. Code for testing:
step 'I click on Products link'
expect(page).to have_content "You don't have any products yet!"
click_link('ADD YOUR FIRST PRODUCT')
expect(page).to have_content 'Add new product'
fill_in('Product Name', with: 'Product')
fill_in('Price', with: 19.99)
fill_in('Description', with: 'This is test product')
find(:xpath, "//input[#type='submit'][#value='SAVE PRODUCT']").click
expect(page).to have_content 'Your product is LIVE' # it fails HERE
click_link('BACK TO PRODUCTS')
expect(page).to have_content 'Product'
click_link('Edit')
expect(page).to have_content 'This is test product'
find_all(:xpath, "//a[#href='#productVariants']").first.click
expect(page).to have_content 'CREATE VARIANTS'
find_all(:xpath, "//a[#href='#customizeWidget']").first.click
expect(page).to have_content 'Button background'
find_all(:xpath, "//a[#href='#flashSales']").first.click
expect(page).to have_content 'Enable Sales Boosters'
And the error message is:
expected to find text "Your product is LIVE" (...) (RSpec::Expectations::ExpectationNotMetError) (should I post page content also?)
It works that way - after save the same page for editing product is shown but modal is revealed and there should have this text. I've saved a screenshot, a page was not reloaded and the modal was not shown (modal is shown if a product is saved properly).
Try precompiling your assets/javascripts in test environment. Problem might be with your javascript not running.
Turns out the problem was I had wrong version of Firefox installed in my container and I guess my version of selenium (2.53.0) was not working properly with FF 52.
Related
I know other people have asked about this before, but I cannot find similar case to this issue.
I have two simple tests:
# Helper function
def select_file(fixture = 'basic.csv')
visit '/import-contacts'
fixture_path = "#{Rails.root}/spec/fixtures"
attach_file('file', "#{fixture_path}/#{fixture}")
end
it 'first test example' do
select_file
click_button 'Import'
['Name', 'Date of Birth', 'Phone', 'Address', 'Credit Card', 'Email'].each do |file_column|
expect(page).to have_content(file_column)
end
end
it 'second test example same instructions as above' do
select_file
click_button 'Import'
['Name', 'Date of Birth', 'Phone', 'Address', 'Credit Card', 'Email'].each do |file_column|
expect(page).to have_content(file_column)
end
end
Im just attaching a file to a file field and sending an ajax request to then check if some data got populated on a table. However Im not manipulating Databse data, Im not storing or trying to get any records from the data base, just a basic Ajax workflow that renders some data based on the file attached.
When I run all the test suite the first test passes, but the second one fails, please check that both tests have the same code, so I cannot find an explanation.
When I run the second test isolated it passes. Any idea what could be happening?
UPDATE
Here are some extra details, the above is just an example, but the tests were different, I had to remove the second test and add the removed part to the first test and it passed.
The second test was replicating steps of first test, however at the end it was clicking a button that makes another AJAX call that renders a js.erb view file.
This was the error I was having at the beginning:
Failure/Error:
respond_to do |format|
format.js
end
ActionController::UnknownFormat:
ActionController::UnknownFormat
However when I moved the asertions and steps of second test to the first test everything passed.
By the way not sure if has something to do with this issue but I set the webdriver at the beginning of the tests file
Capybara.current_driver = :apparition
if I remove the above line the tests fails due to they need to wait the resonse of the ajax request in order to pass.
Since your error is about the format of the request, I'm guessing you're expecting all of your tests to run with the js enabled driver (selenium) but are only setting current_driver to that at the beginning of your tests. In the default Capybara setup, for system/feature specs, Capybara.current_driver gets reset to Capybara.default_driver at the end of every test and then if the test is tagged with js it gets set to the value of Capybara.javascript_driver. If you want all your system/feature specs to run with the same driver you can set Capybara.default_driver = :chrome (or whatever driver you're using) otherwise you need to tag the tests you want to run with that driver with the js metadata
it 'second test example same instructions as above', js: true do
...
end
I have an test written with RSpec and Capybara that should not be passing, however it is:
it 'should have the given text' do
visit root_path
expect(page).to have_text("This is not here")
end
I then included this in the test to look for the issue:
puts page.text
It returns a lot more text than is on the page, and included in that is:
Extracted source (around line #12):
10 11 12 13
})
visit root_path
expect(page).to have_text("This is not here")
It looks like whatever I put in my test will come up when it calls has_text?. Why does it contain all this text that is not on the page?
This is because you have an error in your app/code and a gem rendering the error, and surrounding code, to the returned page enabled in test mode. You want to disable all those types of gems (better_errors, etc) when in test mode (so it's closer to production mode). You can do that by moving them to a development only group in your Gemfile. You can also look in test.log to see what error is being thrown.
How are people handling the following situation:
I have a form that takes an image. How do I verify whether or not the image was accepted? Or is this not something you should verify at this level of testing?
scenario "add facebook like gate and save as draft" do
path = "#{Rails.root}/app/assets/images/like_gate.jpg"
visit root_url
click_link I18n.t(:create_a_new_promotion)
fill_in I18n.t(:title), with: "My promotion"
click_button I18n.t(:continue)
expect(page).to have_text(I18n.t(:promotion_details))
expect(page).to have_text("My promotion")
fill_in I18n.t(:like_gate_copy), with: "Like our page to enter the contest!"
attach_file I18n.t(:upload_lg_image), path
click_button I18n.t(:save_as_draft)
expect(page).to have_text(I18n.t(:promotion_successfully_saved))
end
Is there a particular way to verify that attach_file was actually successful?
Also, how are people testing file uploads in general? In your request specs, controller specs and model specs? I'd like to stick to RSpec and Capybara for all my testing.
Thanks
Since attach_file is a capybara method, don't test it.
Instead consider how valid/invalid uploads change your system state. If uploading a user avatar, for example, verify the user model has a pointer to the ID of the image you just uploaded. If you're doing an even higher level test, verify that a user sees the uploaded image (the url) where they'd expect to see it on the page.
In short, don't test image uploading, test the results of it.
expect(page).to have_selector("img[src=#{path}]")
I'm starting to explore BDD and Cucumber.
So I want to check if my page displays the content of 2 articles I have.
This is the step I'm using the check if the content is there:
Then /^I should see "([^"]*)"$/ do |desc|
page.should have_content desc
expected = Article.find_by_description(desc)
page.should have_content(expected.navision_code)
page.should have_content(expected.category.name)
end
Normally this should do the trick I guess but when I run the test I got this error message:
expected there to be content "---\n- tenetur\n" in "Alfa Paints Order System\n\n\n\nAlfa Paints\n\n\n\nSeth abernathy, admin\n\n\nVerander paswoord\n\nLogout\n\n\n\n\n\n\n\n\n\n\n\nAlfa Paints\nordering system\n\n\n\n\n\nOverzicht van alle artikelen\n\n\n\nBack\n\n\n\n\n\n\nProduct ID\nBeschrijving\nCategorie\n3001\nPaint\n---\n- tenetur\n\n3002\nBrush\n---\n- tenetur\n\n\n\n\n\n\n\n\n\n\n
(RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/admin_articles_steps.rb:41:in `/^I should see "([^"]*)"$/'
features/admin_articles.feature:10:in `Then I should see "Paint"'
As you can see I expect paint and the error message shows the content has paint inside.
But somehow cucumber isn't recognizing it.
I'm new to cucumber and I'm probably missing something but maybe somebody could help me on my way.
You are testing for three things at once, so it is difficult to tell which of the expectations is failing. As a first step, try commenting out everything but the first expectation just to make sure its failing where you think.
Then /^I should see "([^"]*)"$/ do |desc|
page.should have_content desc
// expected = Article.find_by_description(desc)
// page.should have_content(expected.navision_code)
// page.should have_content(expected.category.name)
end
If you still have the same problem, add debugger so that you can experiment and see what is going on from inside your test environment. This is a skill worth developing if you plan to do much cucumber testing.
Then /^I should see "([^"]*)"$/ do |desc|
debugger
page.should have_content desc
end
From debug console, see what the desc variable and page look like:
p desc
p page.content
Soo, if Capybara can interface with the DOM and my app makes a form submit via AJAX and returns some JSON, can Capybara see that at all? I'm not finding any way to get to the AJAX response in the Capybara API.
Here's an example of kinda what I'm doing:
# Cucumber step_definition
Then(/^I should be able to create a household$/) do
click_link 'Next'
page.should have_selector 'form#household-form'
fill_in 'Name', with: name = Faker::Name.last_name
click_button 'Create'
page.wait_until do
page.evaluate_script('$.active') == 0 # really awesome hack to wait for ajax
end
#user.reload.households.first.name.should eq name
end
I'd rather not hit the database again to test the result, but instead do something like:
xhr.response_data.should be_json
Verifying that my json response is what I thought it should be.
I'm just experimenting here, trying to get used to Cucumber and Capybara.
You should mark your scenario / feature to run as a JavaScript feature by tagging it with #javascript:
#javascript
Scenario: Title goes here
What this will do is to tell Cucumber to run the selenium-webdriver gem which will launch a real browser (Firefox) and run the test inside that browser. The browser will of course evaluate the JavaScript and then Capybara will be able to see what it outputs.