How can I test tab order with ruby selenium/capybara - ruby

I need to write a series of test to verify tab order on different pages in my web-app. The issue that I'm facing is that as far as I can tell, the send_keys method for capybara requires you to be on a specific element. Let me illustrate with a very simple example.
<div class="group">
<input type="text" id="first">
<input type="text" id="second">
<input type="text" id="third">
</div>
On my page (call it www.mypage.com/home) I have three input fields as shown above. What I would like to do is go to the page and verify that as I tab through it goes from first to second to third... So essentially I would like to do:
visit 'www.mypage.com/home'
send_keys(:tab)
expect(find('#first')).to have_focus
send_keys(:tab)
expect(find('#second')).to have_focus
send_keys(:tab)
expect(find('#third')).to have_focus
The issue, as I mentioned above, is that capybara requires me to be on a specific element. So while I can test that it goes from first to second and second to third using the code below, I don't know how to verify the first thing tabbed to is first. Additionally the code below has a bunch of extra lookups.
page.find('#first').send_keys(:tab)
expect(find('#second')).to have_focus
page.find('#second').send_keys(:tab)
expect(find('#third')).to have_focus

Your initial tab key press has to be sent somewhere so pick something, like the body element, and send it to that. From there on you know the element that has focus and where you'd like to send the key, so just find them once and use them (rather than repetitive finding)
visit 'www.mypage.com/home'
first, second, third = find('#first'), find('#second'), find('#third')
find('body').send_keys(:tab) # or find('*:focus'), etc.
expect(first).to have_focus
first.send_keys(:tab)
expect(second).to have_focus
second.send_keys(:tab)
expect(third).to have_focus

Related

AlpineJS submit form on button click posts the old value instead of the new one

I'm new to alpineJS, so this might be a silly question. I try to increase an input field by 1, and submit the new value (preferably with a small delay).
I currently have:
<input type='button' value='+' class='qtyplus plus' field='quantity' x-on:click="qty++ && $event.target.form && $event.target.form.dispatchEvent(new Event('submit'));" />
This increases the value of the input form by 1, and submits the form. The problem is that the submitted value is the old value, and not the new one.
Any help with this is much appreciated!
The && operator in JavaScript is used to test conditions for true/false. You should instead use ; to put multiple commands in a single click. JavaScript does some unexpected conversions of values to true/false values. I'm surprised it works even partially. The mysteries of JavaScript! 😆
MDN has some good info on the && operator - called Logical AND
Here's your code sample with the change. I also made a couple of other changes using Alpine JS features:
debounce might be useful for you as it tells Alpine JS to wait until the user has stopped clicking before it executes the click code - which means your server won't have to process so many requests.
x-ref can be used instead of $event.target.form (not useful for you I think, but might be useful for others reading this question)
Form elements have a submit() method you can use. MDN has good info on this as well.
<form x-ref="myform">
<input
type='button'
value='+'
class='qtyplus plus'
field='quantity'
#click.debounce="qty++; refs.myform.submit()" />
</form>
After some more debugging I found the solution by using two on-click events, one that works directly and one that is delayed. This solved the issue for me.
<input type='button' value='-' class='qtyminus minus' field='quantity'
x-on:click="qty--;" #click.debounce.2000ms="$event.target.form.submit();"/>

Filling in text box with capybara

I have a text box that I'm trying to fill in with Capybara. I've tried to play around with it and try to figure something's out but my tests don't pass.
Here's
It's for this specific text box:
<span class="ui-grid-header-cell-label ng-binding" ui-grid-one-bind-id-grid="col.uid + '-header-text'" id="14213131-uiGrid-0008-header-text">DOB</span>
<input type="text" class="ui-grid-filter-input ui-grid-filter-input-0 ng-touched" ng-model="colFilter.term" ng-attr-placeholder="{{colFilter.placeholder || ''}}" aria-label="Filter for column" placeholder="" aria-invalid="false" style="">
Here's the code I have.
find('ui-grid-filter-input ui-grid-filter-input-0 ng-touched').set('1414234')
Ideally I'm trying to find this specific text box and type something in.
To fill the <input> using Capybara you can use either of the following locator strategies:
find('[aria-label=Filter for column]').set('1414234')
or
find('input[aria-label=Filter for column]').set('1414234')
As a CSS selector 'ui-grid-filter-input ui-grid-filter-input-0 ng-touched' is looking for a ng-touched element which is a descendant of a ui-grid-filter-input-0 element which is a descendant of a ui-grid-filter-input element - which obviously isn't what you want. Since you're trying to match on classes you need to use the CSS class selector which starts with .
find('.ui-grid-filter-input.ui-grid-filter-input-0.ng-touched')
would be the correct way to do what you were doing, however you probably don't really need all those classes, and the more you specify the more brittle you are making your selectors. It's likely that just
find('.ui-grid-filter-input-0').set('1414234')
would do what you want - or better
find('.ui-grid-filter-input-0').fill_in(with: '1414234')

Is there any version of Angular Material md-select with select all option

I have been using Angular Material in one of my project. Suddenly I realized the need for having a select all option on md-select. I think I will pull a git request for the same.
However, currently I am looking for a similar drop down structure with checkboxes (like md-select multiple) but also a select all option.
I am aware that I can push a dummy empty entry into md-select option array and manipulate reverse way on its selection. But it would require a lot of code change in my current structure and would also not be a elegant thing to do.
I tried looking for it in bootstrap and jQuery-UI, but could not find one yet. Is there any such control known to anyone. Any redirection will be helpful.
You can do that easily inside the HTML. It requires only one line of code, or two lines, if you want a "select none" option as well. For example
<md-input-container>
<label>Users</label>
<md-select ng-model="selectedUser" multiple=""
ng-model-options="{trackBy: '$value.id'}">
<md-optgroup label="Users">
<md-option ng-repeat="user in users"
ng-value="user">{{ user.name }}</md-option>
</md-optgroup>
</md-select>
</md-input-container>
<button ng-click="selectedUser=users">all</button>
<button ng-click="selectedUser=[]">none</button>
Example in Plunker.
Edit: I updated the below Plunker to show the "all" button inside the select box next to the "Users" optgroup title. The relevant change:
<md-select ng-model="selectedUser" multiple="" ng-model-options="{trackBy: '$value.id'}">
<button ng-click="doSelectedUser()" style="float:right">all</button>
<md-optgroup label="Users">

capybara ruby code to check an element is present or not

using capybara how can i check an element is present or not.
i used following code but it is not working
page.should_not have_selector('#confirmation_code')
<div style="width:250px;display:block;float:right;text-align:right;">
<span id="email_text">Order Number:<br></span>
<input id="confirmation_code" type="text">
</div>
i want to check above text box element is present or not?
So going from the last comment from Sush,
The first line in the code in the question is not correct at all. That will verify that the element is not shown.
You could use the following instead:
page.should have_css('#confirmation-code')
or if you wanted the text within do this:
page.find('#confirmation-code[type="text"]')
I will be honest though I am going by what I think the question is, it is not very clear what you are looking to achieve.

A way around Element cannot be scrolled into view - Watir-webdriver with Ruby

So, we have the following code in our page:
<div class="toggle-wrapper">
<input id="HasRegistration_true" class="registration_required toggle" type="radio" value="True" name="HasRegistration" data-val-required="The HasRegistration field is required." data-val="true">
<label for="HasRegistration_true" class="">On</label>
<input id="HasRegistration_false" class="registration_required toggle" type="radio" value="False" name="HasRegistration" checked="checked">
<label class="checked" for="HasRegistration_false">Off</label>
</div>
These are 2 radio buttons. 'On' and 'Off'. 'Off' is the default value.
Using Watir-webdriver and Ruby, we want to select the 'On' radio button. We do so like this:
browser.radio(:id => "HasRegistration_true").set
But in doing so, we get the following error:
`WebElement.clickElement': Element cannot be scrolled into view:[object HTMLInputElement] (Selenium::WebDriver::Error::MoveTargetOutOfBoundsError)
We know Selenium 2 scrolls the page to the element, so trying to scroll down is useless.
We are always using the latest releases of watir-webdriver and ruby.
We can't change the HTML of the page since we're QA engineers.
Here are two solutions that have worked for me:
There is a Ruby gem called watir-scroll that can work.
Then
require 'watir-scroll'
browser.scroll.to browser.radio(:id, "HasRegistration_true")
If you don't want to add a gem, my co-worker suggested something that somewhat surprisingly (to me) had the same effect as the above code:
browser.radio(:id, "HasRegistration_true").focus
browser.radio(:id, "HasRegistration_true").set
In my code, ".focus" scrolled straight to the element that was previously not visible. It may work for you as well.
First of all try locating the element using XPATH:
browser.element(:xpath, "//input[#id='HasRegistration_true']").click
or
alternatively if it is a hidden element you are trying to locate then you are better off using CSS. Download firebug add-on for firefox and copy the CSS path of your element.
It should be something like:
browser.element(:css => "the CSS path you have copied from Firebug").click
One of the 2 should do it for you!!
Best of luck!
You could manipulate the html on the fly by executing some javascript to make the radio element settable. To execute javascript on a page, do something like:
#browser.execute_script("your javascript here")
I used something like the following javascript to strip the class out of a label tag which moved it out of the way of the input tag I was attempting to act on for a Chrome specific problem I had.
execute_script("$(\"label.classname\").removeClass(\"classname inline\")")
If the element is contained within a form and a div (Wrap) class I found that I had to do the following to click the 'No' radio button on the "https://quote.comparethemarket.com/Motor/Motor/AboutYourVehicle.aspx?" page:
div_list = #browser.form(:action => "AboutYourVehicle.aspx?ton_t=CTMMO&prdcls=PC&rqstyp=newmotorquote&AFFCLIE=CM01").div(:class => "inputWrap").divs(:class => "custom-radio")
And then:
div_list[1].click
Hope this solves your issue too :-)
I'm not using watir but I have the same error as you "...could not be scrolled into view ...". I tried to use watir just to solve it and didn't work for me. Then, I use an ActionBuilder (move_to with click) and the error disappeared.
My line to avoid the error is:
#driver.action.move_to(*webelement*).click.perform
I hope it will be useful for you

Resources