watir, element not currently visible - ruby

I'm trying to interact with a widget on a webpage, enter data into a form element. But I'm getting an error saying the elements isn't currently visible so cannot be interacted with. When manually interacting with the page, the text box asks you to enter something, then that text goes away when you click on the box and accepts input. I've tried having watir click the box first but that isn't working for me either. Here is the raw html:
<input class="symbol-search ui-autocomplete-input x-defaulttext-ghost" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">`
after I click on the box in my browser that changes to this:
<input class="symbol-search ui-autocomplete-input" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">`
Suggestions? Not possible?

One potential problem is that the input element in your code lacks a 'type' attribute, which is what watir uses to distinguish things like text_field from checkbox (since they are all input elements, but act differently)
Without that type attribute (role doesn't really cut it, it's not even a standard element for an input field, not even in html5, not as far as I can tell
Lacking a type attribute, you won't be able to use most of the standard input types supported by watir, which means you won't have access to a .set method You are likely going to have to address this with the basic 'element' class, and then use something like .send_keys once it has been clicked in order to fire keystrokes at it.
Who's widget is this anyway? do they have a demo page that shows an example of it? that would make it easier for people to discover potential ways to work with the control.

This worked for me:
b.text_field(:class => /autocomplete/).set 'hello'

Related

Aria-live not working when focus put on another field

I am writing a very simple SPA application that has a single read-only 'output' field, followed by a single input field. When the user types an input command and hits enter, the JavaScript writes text into the output field. I want the screen reader to read this output straight away without the user having to navigate to the output field, so I added aria-live, thus:
<div>
<div class="output" aria-live="polite">{{myViewModel.output}}</div>
<input type="text" myAngularDirective />
</div>
In the first iteration this worked exactly as I wanted. However, some of the commands change the Url (though rendered using the same view) and I wanted to ensure that the focus is left on the input field, and in most cases, the input field is cleared for the next command. When I add code either to focus on the input, or modify it, the output still renders fine on the screen but is no longer read out by the screen reader.
I've tried:
Changing (in the JavaScript) the order of writing the output and
clearing/focussing on the input
Upping the aria-live to 'assertive'
Adding aria-live to the input also (not sure why I thought that would
help)
Moving the aria-live from the output field to the surrounding div
None has made a difference. If I remove the focus/clear logic, all works well again. There is some subtlety about how aria-live works that I am missing: any help appreciated.
It's difficult to answer your question without a reproducible code sample, and you haven't mentioned which browser and screen reader combination you were testing with. But, it may be that with your focus logic is overriding the aria-live="polite" setting. For example, when the page is updated, the aria-live announcement is queued (because aria-live="polite" is the least intrusive setting), but when the keyboard focus is then intercepted to keep focus in the `, this overrides the announcement.

Why can I not locate a button using XPath?

I have the following HTML:
<input type="button" value="Close List" class="tiny round success button" id="btnSaveCloseListPanel">
The following code does not work:
# browser.button(:value => "Close List").click # does not work - timeout
browser.button(:xpath => "/html/body/center/div/div[9]/div[2]/input[2]").when_present.click
The error is:
Watir::Wait::TimeoutError:
timed out after 60 seconds
when_present(300) does not work.
I found the XPath using Firefox Developer Tools. I used the complete path to avoid any silly errors. I can find the same path manually in IE.
The component is a .NET MVC popup. I think it's called a "panel". The panel is a grandchild of the Internet Explorer tab.
The panel contains a datepicker, a dropdown, a text box, and 3 buttons. I can't find any of these using Watir. I can find anything in the panel's parent (obviously).
The underlying code does not seem to be aware that something actually doesn't exist. To prove that, I tested the following XPath, which is simply the above XPath with the middle bit removed:
browser.button(:xpath => "/html/body/center/div/input[2]").when_present.click
The error is "timeout", rather than "doesn't exist".
So, the code seems to be unaware that:
input[1] does not exist, therefore input[2] cannot exist.
div[2] does not exist.
Therefore there's nothing left to search.
Added:
I'm changing the specific element that I want to find.
Reason: The button in my OP was at the foot of the panel. I was going cross-eyed trying to step upwards through hundreds of lines of HTML. Instead, I'm now using the first field in the panel. All the previous info is still the same.
The first field is a text field with datepicker.
The HTML is:
<input type="text" value="" style="width:82px!important;" readonly="readonly" name="ListDateClosed" id="ListDateClosed" class="hasDatepicker">
Using F12 in Firefox, the XPath is:
/html/body/center/div/div[1]/div[2]/input
But, now, with a lot less lines of HTML, I can clearly see that the html tag is not the topmost html tag in the file. The parent of html is iframe
I've never used iframe before. Maybe this is what t0mppa was referring to in his comment to the first questiion.
As an experiment, I modified my XPath to:
browser.text_field(:xpath, '//iframe/html/body/center/div/div[1]/div[2]/input').when_present.set("01-Aug-2014")
But this times out, even with a 3-minute timeout.
Given that the elements are in an iframe, there are two things to note:
Unlike other elements types, you must always tell Watir when an element is in an iframe.
XPaths (in the context of Watir) cannot be used to cross into frames.
Assuming that there is only 1 iframe on the page, you can explicitly tell Watir to search the first iframe by using the iframe method:
browser.iframe.text_field(:xpath, '//body/center/div/div[1]/div[2]/input').when_present.set("01-Aug-2014")
If there are multiple iframes, you can use the usual locators to be more specific about which iframe. For example, if the iframe had an id:
browser.iframe(id: 'iframe_id')
.text_field(xpath: '//body/center/div/div[1]/div[2]/input')
.when_present
.set("01-Aug-2014")

Why are labels required for inputs with jquery.validate?

I am just starting with jquery.validation and like it. One reference I felt specifically helpful when trying to understand the big picture is http://docs.jquery.com/Plugins/Validation/Reference#Markup_recommendations. One part I didn't understand is why labels need to be associated with each input. Yes, I understand that labels are created to display error hints, however, these are different labels. I couldn't detect any change on the label tag, and it works fine without it. Anyone know why? Thanks
Each input has a label associated with it: The for-attribute of the label refers to the id-attribute of the input.
<label for="firstname">Firstname</label><input id="firstname" name="fname" />
In this case labelis actually HTML element that adds usability improvement for mouse users where if user clicks on the text within the element, it toggles the control.
In HTML label is an optional element, That means you don't need to provide label for each input

How to ignore a default value using the CodeIgniter Validation Helper

I have validation on all areas of a form, and within the inputs I have hints which are set in the input's Value.
However, the problem I have is that CodeIgniter see's the input as being filled in so a Validation error doesn't occur.
I know I can create a callback_function for each input, but with around 10 forms and 100 inputs I was hoping to avoid this and possibly create a generic function or rule?
Any help is greatly appreciated
You seem to be setting default values for your inputs when what you really want is a placeholder
So instead of this:
<input value="Enter your email" />
You want this:
<input placeholder="Enter your email" />
Depending on how you are setting up your input data, a single callback function could suffice if you really needed it, but really: Don't start hacking up Codeigniter for this. Just use placeholder as it was intended (see javascript solutions for older browsers).
Read more about it here:
http://diveintohtml5.ep.io/forms.html#placeholder
I am assuming what you mean is this:
Ghosted Values http://img864.imageshack.us/img864/8124/ghosted.png
Where the value in there is never meant to be the actual value?
The easy solution is to have a class on the <input> that indicates that it's using a stock input (and also it can grey the text out). When the user clicks in the field javascript can clear the initial value out for you (and remove the marker class).
You can then on the submit button click event go through the form and clear the values of anything with the marker class before you actually submit the form.

How can I prevent Firefox's Autocomplete?

There's several section of our site where the user needs to enter some information, and Firefox's auto fill takes over when the page loads - mostly incorrectly!
For example, there's a "Fax Number" field that for some users Firefox keeps filling in with their email address. If they don't see this and they go to submit the form out validators complain to them that it isn't a valid number format.
This really has our sales guys worried because when they go to look at a customers page, they sometimes see it filled in with their own personal info.
Is there any way to prevent Firefox from doing this?
Add autocomplete="off" to your form tag, as documented in the Mozilla document How to Turn Off Form Autocompletion
<form name="form1" id="form1" method="post" autocomplete="off"
action="http://www.example.com/form.cgi">
[...]
</form>
Do read the section on exceptions and workarounds though - the browser will ignore the autocomplete attribute if you have a Name or Address field in the form!
If you don't care about validation, you can use autocomplete="off"
BTW here's a great article from Mozilla themselves about autocompletion
Firefox usually autocompletes based on the field names, so it sounds to me like you might have some underlying confusion with what your fields are called.
I ran into the same problem on Firefox with forms having a 'username' and 'password' field. In this case autocomplete="off" doesn't seem to work, as stated here: https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion (bottom of page).
The only way I found right know to have en empty fields when opening the page is to empty them in javascript. jQuery code example:
setTimeout(function(){
$('input[name="username"],input[name="password"]').val("");
}, 0);
I know it's ugly (especially the setTimeout but I couldn't figure another way. Even putting this in $(window).load() doesn't seem to work.
Try to use dynamic input names.
If autocomplete="off" in the form fails, try using autocomplete="off" in the input field directly and hit Ctrl + F5.
Actually, since a few weeks I've noticed Firefox started mixing autofill values, dropdownlists show entries even from different sites. They probably broke something in their recent builds. Now some personal entries can be seen by people just asking to check mails on your pc. Desire to block this feature is now very understandable.

Resources