Ruby, Cucumber, & Capybara: selecting using regex - ruby-on-rails

I am trying to select an input node using Capybara:
When /^the shopper clicks the "(.+)" button$/ do |button|
first(:css, text: /^#{button}/).click
end
The scenario that triggers the above step is:
And the shopper clicks the "PAY" button
The button in the view will always start with the text 'PAY' but it is followed by a space and then the total price of the products e.g. 'PAY $150'
The dollar amount will change but the PAY part won't. If I try the above code I get the following error:
And the shopper clicks the "PAY" button # features/step_definitions/shared_steps.rb:33
unexpected '$' after '' (Nokogiri::CSS::SyntaxError)
How can I properly grab the PAY button using Capybara and Regex?

The problem you're having is that you have specified a css selector type but not actually specified a CSS selector. Since it's an <input> element you could do
find(:css, 'input', text: /^#{button}/).click
However, since it's an input being used as a button I'm assuming it's of type submit, reset, image, or button. This means you can use the :button selector type (rather than :css) to make your clearer as to what you're actually doing. When finding a button Capybaras default behavior is to match on substrings so you should just be able to do
click_button(button)
which is the same as either of
find(:button, button).click
find_button(button).click
If that doesn't work for you please add the relevant HTML to your question.
As an aside, you should stay away from first whenever possible - it has a number of downsides.

Related

Is it possible to click the Nth element with SitePrism?

I was just starting with SitePrism and I've got a site where elements get added dynamically to the page and don't have any kind of id, name, etc... the easiest I could think of is finding them by their 'text', eg. a CONTINUE button
I was trying:
element :continue_b, :button, 'Continue'
and SitePrism fails with the following:
Capybara::Ambiguous: Ambiguous match, found 4 elements matching button "Continue"
Is there a way for me to specify with SitePrism the element I want to click? I've found a few ways to do it with Capybara itself but I didn't manage to see the equivalent with SitePrism.
If there really is no difference between any of the button elements and you can't/don't want to move the element definition to a scoped section of the page, you can use the match argument to return just the first. Since all the parameters after the SitePrism element name are passed through to Capybara as find arguments it would be
element :continue_b, :button, 'Continue', match: :first

automate webpage button click in ruby

I am simply looking to automate a button click on a homepage. I am using the following snippet of code
Given /^I press "(.*)"$/ do |action|
browser.button(:text => action).click
end
My feature file has the following
Scenario: Default Search
Given I press "Search"
On executing the feature file, I receive the following error
*** WARNING: You must use ANSICON 1.31 or higher (https://github.com/adoxa/ansicon/) to get coloured output on Windows
Ambiguous match of "I press "Search"":
C:/Users/............test/features/step_definitions/Moorings.rb:8:in `/^I press "(.*)"$/'
Haa... you have like 3 occurrence of the text "Search" on that page (www.moorings.com), so the watir driver does not really know which one to click.
As I mentioned above, try to use something unique, maybe an id, as below:
#step definition
Given /^I press "(.*)", with id "(.*)"$/ do |text, id|
browser.button(id: id, :text => text).when_present.fire_event :click
end
#feature
Scenario: Default Search
Given I press "Search", with id "edit-search"
Notice that I have added another constraint of id to the attributes to search for.
Also notice that I added an extra layer of check: .when_present. This will ensure that the test waits for the specified button to appear on the page before attempting to click it. A timeout of about 30 seconds is attached to this however.

How can i send :Backspace to an element with Capybara and Poltergeist without it triggering the browser to navigate back one page?

I am trying to test a HTML editor in a Cucumber scenario, and I need to simulate the user pressing backspace. The code I am using is below, but it causes the browser to navigate back instead of delete a character.
How can I focus on the editor area so that the keypress does not do this?
page.execute_script "$('.redactor-editor').first().focus();"
all('.redactor-editor')[0].native.send_key(:Backspace)
Remove the capital B of :Backspace
page.execute_script "$('.redactor-editor').first().focus();"
all('.redactor-editor')[0].native.send_key(:backspace)
How about if you click in the text box that contains the char you want to delete prior to sending the backspace action
If you "fill_in" the field just prior, it should still have focus. In my case I needed to trigger a backspace to "clear a field's value", because just setting it to empty wasn't triggering things as expected.
EX:
When("I clear the field {string}") do |field_name|
fill_in field_name, with: ' '
find("input[name=#{field_name}]").native.send_key(:backspace)
end

How to test jQuery TokenInput field using Selenium

I'm unable to test a Tokeninput field in a form using selenium. The situation is when we type something, it gives a list to options to select but those options aren't part of the DOM. The text fills the field but doesn't select the item.
The code which I have written is:
Given admin user is on schedule interview page
And he select "obie[1]" and "DHH[1]" from the candidate name(s) auto sugget field
**step defination**
Given /^he select "([^"]*)" and "([^"]*)" from the candidate name\(s\) auto sugget field$/ do |arg1, arg2|
within(:css, "#interview_template_candidate_names_input") do
fill_in('tmp',:with => arg1) --tmp is name of the token input field
find("li:contains('obie[1])'").click
save_and_open_page
end
end
I finally succeeded in making this work. Here's the gist: https://gist.github.com/1229684
The list is part of the dom (div.token-input-dropdown), it's added as the last child of the body element, which is probably why you didn't see it.
If you understand what the tokeninput plugin is doing, you can get a better idea of what you need to do. For each tokeninput you create, the plugin:
creates a ul.token-input-list (immediately before input#your_input_id)
creates a ul.token-input-list input#token-input-your_input_id
hides the input#your_input_id
creates a div.token-input-dropdown
So the most challenging part is finding the correct ul.token-input-list, because you have to find it based on its position relative to the original input, and the selenium webdriver doesn't let you navigate the dom.
After that, you just fill in the input#token-input-your_input_id and "click" on the div.token-input-dropdown li option that matches what you're looking for.

Using click_link with Cucumber Scenario

I have the following Feature file which is attempting to visit a page, select a link then edit user data.
Scenario: Edit an existing member of the club
Given I go to the member list page
And I choose the first item
And I fill in the "First Name" with "Bloggs
When I press "Update"
Then I should be on the member list page
And I should see "Bloggs"
and the member_step.rb file contains
Given /^I choose the first item$/ do
#save_and_open_page
visit members_path
click_link "1"
end
My routes.rb file has
Gfs::Application.routes.draw do
resources :members
end
The problem is that I can't get the click_link "1" step to work. The intention is that it will
Navigate to the '/members' index page
The index page displays a list of users each prefixed with a number, that is the link.
Select the link
What I know is that the index page does display a list, my route works ('/members), but my Cucumber is failing and I'm not basking in the glory of green.
The save_and_open_page diagnostic shows only the title of the index page and not the details, as though the controller is not accessing the data
Suggestions are most welcome.
Is there a Background where you create the members data? If not, it may be that the data does not exist.
I'd also suggest adding a step like
And I should not see "Bloggs"
before you update the record.
If I understood your cuke correctly, you really won't see the "1" link because:
Given I go to the member list page <-- first step
And I choose the first item <-- second step
...which expands to:
Given I go to the member list page <-- first step
visit members_path
click_link "1"
why are you visiting the member's path after you just visited the member list page? you should be checking that you ARE in the member's path. Something like:
Given I have existing users(generate members here using factory or whatever)
And I go to the member list page( go to member page)
When I follow "1" (click the first member)
Then I should be on the "1"'s member page
When I fill in...etc you get the point
Hope that helps!
I'm going to suggest that IFF the "1" is a true html anchor link, then you might consider using
And I follow "1"
You could easily wrap this in your own syntax to make it more aesthetically pleasing but the And I follow... step is one that you get out of the box in web_steps.rb.
Another gain in using that one is that you can use a selector to make the click more specific:
And I follow "1" within ".my-kickbutt-div"
Or something along those lines.
Another thing to check into. If you have #javascript enabled you might be seeing incorrect data in your save_and_open_page. My app is javascript/ajax heavy and I have to open the output in a browser with javascript turned off to see what is really visible there :P This might not be your issue, but just in case...

Resources