Javascript: selenium webdriver isDisplayed() not working - javascript

I am writing a test with selenium using JavaScript.
At one point in my test, I iterate through an array of input elements and want to fill in a value for the inputs which are visible.
if (textInputs.length > 0) {
console.log('handling text input');
var i, textInputLen;
for (i = 0, textInputLen = textInputs.length; i < textInputLen; i++) {
(function (index) {
if (textInputs[index].isDisplayed()) {
textInputs[index].sendKeys("custom text box - " + textBoxes);
textBoxes++;
}
}(i))
}
}
I keep getting the following error ElementNotVisibleError: element not visible because it is trying to fill in an input which is not displayed on the DOM. Why is it not working? How can I get it working?
I have tried a few thing instead of isDisplayed():
I executed JS to see if the element had visibility set to hidden or display to none. Issue here is that the element bing displayed, in this case, is due to a slew of things and I am looking for something more general. IN this case, isDisplayed() would be exactly what I want.
Please advise

The method .isDisplayed() returns a promise and not the displayed state. Use then to get the resolved result:
element.isDisplayed().then(function(state){
console.log(state):
});
But a better way would be to filter the list of elements with webdriver.promise.filter:
var textInputs = driver.findElements(By.css("input[type=text]"));
webdriver.promise.filter(textInputs, function(element) {
return element.isDisplayed();
}).then(function(element) {
element.sendKeys("my text");
});

Related

Cypress seems to target the wrong element

When selecting elements by id using cy.get() and then typing into them using .type() the wrong element is typed into. This happens intermittently in a number of tests I have written. The get seems to select the correct element, but then the type inputs in a different one.
Example:
element correctly selected
value entered into wrong element
Ive tried a number of things here. cy.get('#elementid').clear().type('new text') was how I used to do this, but changed to cy.get('#elementid').type('{selectall}new text'). The new method causes this issue to happen far less often, but it still does.
The complete command used in the example screenshots is using a loop to build the element IDs, but this issue also appears when selecting elements without a loop.
Cypress.Commands.add('new_supplier_preisanfrage', (customerFullName, discount, priceList) => {
cy.open_supplier_preisanfrage_dialog(customerFullName)
cy.get('#1917240871_' + (priceList.length - 1) + '_price').should('exist').then(() => {
for (var i = 0; i < priceList.length; i++) {
var price = priceList[i]
cy.get('#1917240871_' + i + '_price').type('{selectall}' + price)
cy.get('#1917240871_' + i + '_discount').type('{selectall}' + discount)
}
}).then(() => {
cy.get('#price-inquiry-edit-save-btn').click()
})
})
You can see here that I also tried using .then() to wait until all the fields have been loaded into the DOM.
So, How do I debug this further? Is this a known issue? What am I doing wrong here?

Search Alt Text, hide mismatches with jQuery / JavaScript

I am trying to implement a rudimentary site search for a page of images. The search function should go through each element in a specific class looking for a word match in the image's alt text.
I think my issue is with binding the function to a form submit but I can't seem to figure out where I went wrong.
I have tried this with jQuery (fiddle:http://jsfiddle.net/u2oewez4/)
$(document).ready(function(){
$("#search-form").click(function() {
var searchQuery = "Text";
$.each('.single-image', function(){
$(this).children("img").attr("alt"):contains(searchQuery).hide("slow");
});
});
});
As well as with JavaScript (fiddle:http://jsfiddle.net/m3LkxL1c/)
function submitSearch(){
// create regex with query
var searchQuery = new RegExp(document.getElementById('search-input').value);
// create array of content to look for query in
var content = document.getElementsByClassName("single-image");
// create an array to put the results to hide in
var hideResults = [];
var imagesToHide = document.getElementsByClassName("single-image-hide");
// get the current display value
var displaySetting = imagesToHide.style.display;
for (i=0; i<content.length; i++) {
if (! searchQuery.test(content[i].firstChild.firstChild.nodeValue)) {
// if the query not found for this result in query
hideResults.push(content[i]);
// push to the hideResults array
content[i].className = "single-image-hide";
// change class name so CSS can take care of hiding element
document.getElementById("form-success").style.display = 'inline-block';
alert(searchQuery); // for debugging
return false; // results will not stick without this?
}
}
// set display to hidden
if(displaySetting == 'inline-block'){
imagesToHide.style.display = 'none'; // map is visible, so hide it
}
else{
imagesToHide.style.display = 'inline-block'; // map is hidden so show it
}
}
FYI I have built the JQuery off a few StackOverflow threads, so I've definitely tried my best to find a similar example. (Similar functions: here, and here)
Okay, various bug fixes, most of which I noted in the comments already because I wanted to make sure not to miss any. You need to read the details for in the jQuery documentation much more closely. That'll fix a lot of the problems you're having, like using the wrong each function. Other things will come with time. Keep studying, and READ THE DOCUMENTATION.
$("#search-form").click(function() {
//this gets the val for the search box, then puts the Imgs in a variable so we don't have to use the selector multiple times. Selectors are expensive time-wise, stored variables are not.
var searchQuery = $("#search-text").val(),
singleImgs = $('.single-image');
//you have to show the images for each new iteration, or they'll remain hidden
singleImgs.show();
singleImgs.each(function(){
//get alt attribute
var thisAlt = $(this).find("img").attr("alt");
//if thisAlt does not contains searchQuery (use > instead of === for does)
if(thisAlt.indexOf(searchQuery) === -1){
$(this).hide();
}
});
});
working fiddle

JQuery retrieving id from Checkbox at run time

My problem is, I want to retrieve checkbox id at runtime and use them later for other purpose.
But retrieved id is read as object.
My Code is:
// Following code gives id of checkbox which contains myCheckbox as its id.
var myCheckbox= $('input[id$=myCheckbox]')[0].id;
// and Now I want to check if that checkbox is checked with following code:
if ($(myCheckbox).is(':checked'))
return 1;
else
return 0;
But here myCheckbox id is read as Object instead of id and thus always enter in else condition and returns 0. This code works when I enter id of checkbox directly.
if ($('#ctl001_myCheckbox').is(':checked'))
return 1;
else
return 0;
It shouldnot be so complicated, I have been working with Javascript but new to JQuery.
You are getting the ID correctly, but the jQuery selector requires the # symbol, much in the same way as a CSS selector does. You need to add the # character to your selector:
if ($('#'+myCheckbox).is(':checked'))
return 1;
else
return 0;
BenM is correct, but why are you getting the ID of the element, and then look it up again? You already found the element, there is no need to search for it a second time.
Just keep a reference to the element:
var myCheckbox = $('input[id$=myCheckbox]').first();
// or var myCheckbox = $('input[id$=myCheckbox]')[0];
// and later
if (myCheckbox.is(':checked')) {
// or if (myCheckbox.checked) {
Simply:
return (($('#' + myCheckbox).is(':checked')) ^ false);
Have you tried using:
var myCheckbox= $('input[id$=myCheckbox]').attr('id');

How do I get element's className inside loop of elements?

I am trying to create a function that given a divid, and a list of classes, will then do some text replacing inside them.
Having learned of how Firefox Dom is handling text nodes differently, I read that I had to use javascript to loop through the elements, sibling to nextSibling.
The last obstacle I had in my script, of which you see a small portion of, is getting the classname. I need the class name so that I can filter down what content get's text replaced.
Having looked all the answers, and with the help of a co-worker named Ryan at work, we have redone this in jquery.
$(divid).find(".status_bar").each( function() {
var value = $.trim($(this).text());
// if value is not defined thru browser bugs do not replace
if (typeof(value) != 'undefined') {
// it is a text node. do magic.
for (var x = en_count; x > 0; x--) {
// get current english phrase
var from = en_lang[x];
// get current other language phrase
var to = other_lang[x];
if (value == from) {
console.log('Current Value ['+value+'] English ['+from+'] Translation ['+to+']');
value = to;
$(this).attr('value', to);
}
}
}
});
This currently works in all areas, except in the replacing of text.
The reason I had originally with doing this in jQuery, had to be not sure I could loop thru elements, and avoid the problem with firefox and text nodes.
I am doing a loop of all elements inside a div, and I now need to get the classname of the element that I am looping by.
Then i can check if the current element's class is one, I need to do something with...
// var children = parent.childNodes, child;
var parentNode = divid;
// start loop thru child nodes
for(var node=parentNode.firstChild;node!=null;node=node.nextSibling){
var myclass = (node.className ? node.className.baseVal : node.getAttribute('class'));
}
But this code for getting the classname only get's null values.
Any suggestions?
For those of you who are trying to figure out what the whole point is, read this JavaScript NextSibling Firefox Bug Fix I have code that does my language translation that works in Google Chrome and IE. But when I use it in Firefox, and try to translate div content after ajax has loaded it, it fails because of the whitespace issue.
I really don't have a preference of jQuery or Pure Javascript, I just want a working solution.
Thank you all for being patient. I personally thought I was extremely clear in my description, I apologize if it wasn't. I wasn't trying to be obscure or make it difficult to get help. But please don't insult me, by implying I am trying to make it unclear.
Thanks.
Hm... You have jQuery but don't use it?
$(divid).children(".yourSpecialClassName").each( function() {
doSomethingWith(this);
});
To get the CSS class attribute value, this will do:
$(divid).children().each( function() {
alert(this.className);
});
Based on the function you posted now, you want this:
$(divid).find(".status_bar").each( function() {
$(this).text( function(i, text) {
var x = $.inArray(en_lang, $.trim(text));
if (x > -1) {
console.log('Current Value ['+text+'] English ['+en_lang[x]+'] Translation ['+other_lang[x]+']');
return other_lang[x];
}
return text;
});
});
And please, don't ever use "do magic" as a comment again. This is incredibly lame.
EDIT. This can be made much more efficient (superfluous console.log() removed):
$(divid).find(".status_bar").each( function() {
// prepare dictionary en_lang => other_lang
var dict = {};
$.each(en_lang, function(x, word) { dict[word] = other_lang[x]; });
$(this).text( function(i, text) {
var t = $.trim(text);
return (t in dict) ? dict[t] : text;
});
});
if you are using jquery you can do this:
$("#myDiv").find("*").each(
function(){
var myclass = $(this).attr("class");
}
);
Your sample code doesn't make sense.
$(this).attr('value', to);
'value' is an attribute of the tag, not the text content.
Did you really mean to do this instead?
$(this).text(to);
Also, you've re-edited your question, but you're still trying to loop through the child nodes using non-jQuery methods. You said "The last obstacle I had in my script, of which you see a small portion of, is getting the classname. I need the class name so that I can filter down what content get's text replaced."
If you are using jQuery it is completely unnecessary to loop through anything to get a class name. You simply have to use a proper selector in the first place.
$(divid).find(".status_bar.replaceme").each( function() {
// .replaceme is whatever class you're using for the stuff you want to change
// .status_bar.replaceme matches all elements with BOTH status_bar and replaceme classes
var value = $.trim($(this).text());
// if value is not defined thru browser bugs do not replace
if (typeof(value) != 'undefined') {
// it is a text node. do magic.
// NOTE: The following is inefficient but I won't fix it.
// You're better off using an associative array
for (var x = en_count; x > 0; x--) {
// get current english phrase
var from = en_lang[x];
// get current other language phrase
var to = other_lang[x];
if (value == from) {
console.log('Current Value ['+value+'] English ['+from+'] Translation ['+to+']');
// value = to; <-- useless, get rid of it.
$(this).text(to);
// or $(this).html(to);
}
}
}
});

how to capture the mouseover element?

i am developing an autocomplete feature.but i am facing one problem there...
when i click on the suggestion box one of the results will not enter into the suggest html box...
function handleOnMouseOver(oTr)
{
deselectAll();
oTr.className ="highlightrow";
position = oTr.id.substring(2, oTr.id.length);
updateKeywordValue(position);
}
can you plz tell the solution
thanks
function updateKeywordValue(oTr)
{
var oKeyword = document.getElementById("keyword");
var strKeyword="";
var crtLink = document.getElementById("a" +oTr.id.substring(2,oTr.id.length)).toString();
crtLink = crtLink.replace("-", "_");
crtLink = crtLink.substring(0, crtLink.length);
oKeyword.value=unescape(crtLink.substring(googleurl.length, crtLink.length));
strKeyword=oKeyword.value.toString();
if (oTr.id.substring(2,oTr.id.length)==0)
{
oKeyword.value=strKeyword.substring(3,strKeyword.length);
}
selectedKeyword=oKeyword.value;
}
you should get rid of the second parameter in the substring() method. Since you just want the remainder of the string, I'm guessing, that is the default if you don't set a second value.
position = oTr.id.substring(2);
My guess is that you are getting the value of the keyword from the id, and pushing that into the input box, right? If that's the case, we'll need to see more of your code. Specifically, I'd like to see the updateKeywordValue function and I'd also like to know if the text that they are hovering over is the text you are trying to send the input box. If so, you could probably simplify the whole thing and go with something like:
function handleOnMouseOver(oTr)
{
deselectAll();
oTr.className ="highlightrow";
keywordbox.value = oTr.innerHTML;
}
But this is based on the assumption that the only data inside the hovered row is the text, and no other html. And I had to make up a name for your input box.
But if this way off, this is because we need more information to see the real problem.

Categories