I still have difficulty in some situations of not avoiding xpath. For this problem below how to avoid it ?. Someone has a website that teaches many ways to do this .. Thank you very much.
this class is repeated more than once on the page.
'//*[#id="gatsby-focus-wrapper"]/div/div/div/main/div/div/div[2]/form/div1/span[2]'
See the picture please.
You don't state what you're trying to do with that element, but there's most likely no need to check the full page structure since the element has text in it. Also using XPaths with the full page structure are going to make your tests very brittle.
If you want to find the element you could do
find('span', text: 'E-mail inválido')
or if you wanted to verify that it was within the gatsby-focus-wrapper you could do
find('#gatsby-focus-wrapper span', text: 'E-mail inválido')
If you were trying to verify it exists you could do
expect(page).to have_css('span', text: 'E-mail inválido') # using RSpec
or
asset_css('span', text: 'E-mail inválido') # using Minitest
If you needed/wanted to test for the class base too you could use a regex with the class filter like
expect(page).to have_css(
'span',
text: 'E-mail inválido',
class: /signUpFormFields__InputError\-/
)
Related
I'm dealing with a bug from a spec file, specifically in a test which is related to an action of update a field value, this is the code I'm trying to use:
it "is possible to update your city destination page" do
click_link another_city.name
expect(page).to have_content(country.name)
expect(page).to have_content(country.state)
expect(page).to have_content(city.name)
end
After run the test I get the message:
Failure/Error: expect(page).to have_content(city.name) expected to find text "Melbourne" in "..."
So, I'm trying to fix it with this new line of code:
expect(page).to have_field(another_dealer.name, with: 'Voonte')
But I got a different kind of error related to another field.
So, my questions are:
is it a good approach trying to add a specific value in the spec?
what else should I try to fix the error?
Thanks a lot for your comments.
So I have setup a Capybara, Cucumber project with SitePrism for POM and for the most part it works. When I use:
Then('Find object name') do
expect(#page).to have_object_name
end
it works just fine but when I come to use:
Then('Assign object names text to a variable') do
expect(#page).to have_object_name
valueA = #page.find('object_name').text
end
this doesnt work and throws an error
Unable to find css "object_name" (Capybara::ElementNotFound)
However, if I use:
Then('Assign object names text to a variable') do
expect(#page).to have_object_name
valueA = #page.find(:xpath, 'object_name_XPath').text
end
this works out just fine as well, but this sort of defeats the point of POM as it would greatly increase maintenance.
I assume I must be missing something to get the page.find locate the object_name from my page but I have danced around it and searched high and low but can't seem to figure the problem out.
Help? :)
#page.find takes a CSS selector (by default - it's actually just the Capybara find method), not the name of a SitePrism element.
If #page is a SitePrism::Page or SitePrism::Section object and you have defined elements on it, then you just access that element as a method on #page - See https://github.com/natritmeyer/site_prism#accessing-the-individual-element
#page.object_name
In this crud test I create a log entry with #notes and will try to update the log by replacing #notes with #updated_notes.
#notes = Faker::Crypto.md5
#updated_notes = Faker::Crypto.sha256
This block of code to create the log entry works. I used within and the id's of divs in the source code with inspect.
it 'User can update manpower log entry' do
# create a new entry
within '#manpower_log_div' do
find('#manpower_log_notes').send_keys(#notes)
click_button "+ Add"
expect(page.has_css?('td', #notes)).to be true
end
Here I try to click the already existing notes on the page, which lets me edit them.
# click the already existing notes to be able to edit them
within '#manpower_log_div' do
find('#inline_edit').click
end
The error received is
Capybara::ElementNotFound:
Unable to find css "#inline_edit"
Inspecting the element gives us this, but notice the id of the object is too specific: data-object_id="11747753". What element can I place in find that I can use every time I run this test?
<span textarea_cols="50" class="inline_textarea_edit inline_editable" data-object_field="notes" data-object_id="11747753" data-object_class="ManpowerLog" data-custom_callback="" id="ManpowerLog-11747753-notes" data-value_required="false">a5c3e556f108fd29b00150ca736c82d6</span>
You can find the element by any valid CSS selector that would match it. In your example you could use class or data attribute - or a combination of both.
find('span.inline_textarea_edit[data-object_field="notes"]').click()
In your code find('#inline_edit') is looking for an element with id inline_edit. As Thomas Walpole mentioned you can find your button using css selector for example by class:
find('.inline_textarea_edit')
or
find('.inline_editable')
or
find('.inline_textarea_edit.inline_editable')
Make sure that class is uniq for that element. If not, you'll need to use something else then class or something else together with class, you need to look for uniq attribute of that element.
Also make sure that your element is within element with ID manpower_log_div as you are using within '#manpower_log_div'
You can find more info about css selectors here: http://www.w3schools.com/cssref/css_selectors.asp
Recently we upgraded our selenium web driver from 2.47.1 to 2.48.0.
With this upgrade I need to add sleep for a few seconds in rspec to pass. Spec was working properly without sleep with the older version.
sleep(inspection_time=5) // why do I need this?
my_form_page.save_button.click
// some assertion here
Edit
I tried using implicit wait instead of sleep.But it's not working. Is there any specific reason behind it?
Capybara.current_session.driver.browser.manage.timeouts.implicit_wait = 50
Generally speaking, rspec selenium tests are known to be "flakey". Sometimes rspec tries to search for an element before it appears on page due to many reasons (ie: element appears upon ajax response).
Here's a tip that may help you solve this, if you will wrap your capybara finders inside of a within block, your tests will wait until it finds that within selector FIRST before trying to run the code inside of it.
This more-often-than-not will help solve a test running too fast on a page that takes a while to load and your button or selector or whatever isn't actually on the page yet (which is why it fails).
So take a look at these 2 examples and try the within method...
# spec/features/home_page_spec.rb
require "spec_helper"
describe "the home page", type: :feature do
context "form" do
# THIS MIGHT FAIL!!!!
it "submits the form", js: true, driver: :selenium do
visit "/"
find("#submit_button").click
end
# THIS PROBABLY WILL PASS!!!
it "submits the form", js: true, driver: :selenium do
visit "/"
within "form" do
find("#submit_button").click
end
end
end
end
The following test would sometimes fail:
it 'can create a new item' do
visit 'items/new'
within 'form#item-form' do
fill_in 'Name', with: 'Item'
click_button 'Create'
end
current_path.must_equal('/items')
assert page.has_content?('Item')
end
I put a puts page.html before the within block and found out that sometimes the page would be a clear 'Not found' page. I'm using Capybara's default web driver Rack::Test.
Is there any difference between visit 'route' and visit '/route' in Capybara?
Yes there can be a difference in a number of cases depending on things like whether you've specified Capybara.app_host, already visited a url in the current test, etc. Basically if you want to go to /items/new specify /items/new
You can see the relevant code when using rack-test here and here . The other drivers all have similar behavior, so only use relative paths if you really understand what you're doing and need relative paths
On a secondary note, you should get away from doing direct assertions on current_path. It will work fine while you're using rack-test since all clicks on submits, links, etc are synchronous - but if/when you move to using a JS capable driver those actions are no longer guaranteed synchronous so you'll end up comparing current_path before it's actually changed. You should get used to using something along the lines of
assert page.has_current_path?('/items')
since that will use Capybaras waiting behavior while confirming the current path