how to make sure a link is clicked with watir-rails - ruby-on-rails

I am using watir to perform some functions
I need to show that a link is actually clicked by the watir-driver, so I'm trying to put somthing to the console if a link is clicked as follow:
puts "profile clicked" if click_my_profile_link(browser)
and:
def self.click_my_profile_link(browser)
browser.div(class: "topbar").when_present
.link(class: 'my-profile').click
end
but nothing gets printed to the console when the link gets clicked. this behaviour is the same for everywhere I have a click action. Another example is:
puts "Next button clicked" if browser.input(id: 'next', value: 'Next').fire_event :click
How can I get some kind of log when there is a click action fired like this? thanks

Procedural methods are called for their action/side-effect and shouldn't be expected to have a response.
If you didn't get an error, then Watir found the element and sent a click command to it.
So maybe this is sufficient expect {click_my_profile_link(browser)}.to_not raise_error
Typically you write tests to verify the result of the link. In this case that would be something like expect(browser.title == "My Profile Title").to be true
You could create an AfterHook that will take an additional action after every navigation and click, but it wouldn't distinguish between the two, and I really don't think that is what you actually want.

Related

Problem with feature spec to check form button is disabled after submit

I am writing an RSpec / capybara feature spec to test that, after a form submit button is pressed, the button is disabled and its text is changed to 'ADDING...'.
In the spec, the button is clicked (and if valid, the form is submitted) with:
find(".Booknow-modal-bookingButton button.primaryCTA").click
And the corresponding javascript that is executed is as follows:
$('form#booknow-room').on('submit', function(e) {
// If form is submitting then html5 validation has passed,
// now disable the button to prevent duplicate submissions.
$('form#booknow-room button.primaryCTA').attr('disabled', true).text('Adding...')
})
When the spec runs I can see that this is working. The next line of the spec is:
expect(page).to have_button('ADDING...', disabled: true)
But I think that, by this time, the form submit has redirected to the basket page so it isn't finding the button, so the test fails.
I have also tried the following variants:
expect(find('.Booknow-modal-bookingButton button.primaryCTA').value).to eq 'ADDING...'
expect(".Booknow-modal-bookingButton button.primaryCTA").to have_content("ADDING...")
expect(page).to eq(".Booknow-modal-bookingButton button.primaryCTA", disabled: true)
But none of them work.
The error message returned by rspec is:
Failure/Error: expect(page).to have_button('ADDING...', disabled: true)
expected to find button "ADDING..." but there were no matches
Assuming clicking the button triggers a full form submission rather than an XHR based submission what you're trying to do may not be possible. This is because of the defined behavior for clicking an element in the WebDriver spec - https://w3c.github.io/webdriver/#element-click. 12.4.1 steps 10, 11, and 12 are the relevant parts where driver implementors may attempt to detect if a navigation is occurring and wait for it to complete. This can mean your check for disabled won't happen until after the page has already changed.
The question to ask next is whether this is something that needs to be tested via end-to-end Capybara tests, or whether it could instead be tested in Javascript only tests.
If you do consider it necessary to be tested in your Capybara tests you could try registering a driver with the page load strategy capability set to "none" which should tell the driver not to wait for any navigations and MAY allow the button state to be checked (you'd probably only want to use that driver for this specific test). Another potential option would be to use execute_script to install an event handler that prevents the actual submit from occurring - although every time you modify the running page code in your test you're potentially reducing the usefulness of the test.
I implemented the other "potential solution" which #Thomas Walpole mentioned -- modify the form, so that when you click the submit button it doesn't actually submit. This allows you to validate that the button is disabled without capybara blocking until the form submits.
page.execute_script(
"$('form#booknow-room').attr('action', 'javascript: void(0);');"
)
page.click_button('Submit')
expect(page).to have_button('Adding...', disabled: true)

Ruby, Cucumber, & Capybara: selecting using regex

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.

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 to test in Capybara if an element is clickable?

I need to test in Capybara if on a page an input text box is visible and clickable. I know how to test about visibility, but I couldn't find a method like .clickable or something in that spirit. How does one do this in Capybara?
It sounds like the OP's needs have been met, but for future explorers, here's some tools to tell if something is clickable.
Test whether the thing can be clicked (Rspec && Capybara):
it "is clickable" do
expect{ find('.your_selector').click }
.not_to raise_error(Capybara::Poltergeist::MouseEventFailed)
end
it "isn't clickable" do
expect{ find('.your_selector').click }
.to raise_error(Capybara::Poltergeist::MouseEventFailed)
end
Click it if possible and do something else if not, per Joe Susnick's answer:
clickable = expect{ find('.your_selector').click }.not_to raise_error(Capybara::Poltergeist::MouseEventFailed)
if clickable
plan_a
else
plan_b
end
Putting this as an answer, from comments on the original question.
You don't need to test clickability (i.e getting the input field to blink when clicked on), because I think that's browser dependent. You don't need to do anything to get that functionality. So if it's visible, and an input field, clicking in it will get that result. Otherwise, if it's not visible, it can't be clicked on anyways, so you're fine. I don't think you need to test anything about clickability, just visibility.
An element can be "visible" without being clickable. I'm actually working on finding a workaround now for selecting a button that's behind an opaque layover. I want to be able to say something like:
if find_button("Change Location").visible?
click it
else
something else
end
I haven't found an answer for this that isn't a hacky workaround so any advice would help. Instead of dismissing the question

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