Protractor: Failed: stale element reference: element is not attached to the page document after click() - protractor

I am facing above issue when i am trying to click on the dropdown element which matches with given text. All the options of dropdown are as in the image with span having the text.
I tried things given as in the link here,but no success. Protractor: Failed: stale element reference: element is not attached to the page document. Reference of tags are as given here in this pic below.
My code looks something like this
element.all(by.css('ul[class='ui-dropdown-items ui']>li')).each(function(element) {
element.getText().then(function (text) {
if (text.includes("Bag")){
element.click();
}
});
});
Though the click action gets performed by above statement, still error is thrown.
Also when i try to click on any index as hard coded it works with no error.
element.all().get(4), where 4 being index of the element.
My application is in angular 5.
Can someone help me out on this! This is blocking my project.

element.all().each() execute iteration on each element, even you add if condition to only click one element of all, But the getText() in each iteration still be executed.
After you click on the matched element, the page redirected or refreshed. Then call getText() on next element on "new" page, that's why report stale reference exception
You need to filter the matched element, then click on it.
// approach 1
element
.all(by.css('ul[class='ui-dropdown-items ui']>li'))
.filter(function(ele) {
return ele.getText().then(function (text) {
return text.includes("Bag");
});
})
.then(function(eles){
if (eles && eles.length > 0) {
eles[0].click()
}
})
// approach 2
let options = element.all(by.css('ul[class='ui-dropdown-items ui']>li'))
options.getText(function(txts) {
return txts.findIndex(function(txt){
return txt.includes('Bag');
})
})
.then(function(index){
return index !== -1 && options.get(index).click();
})

Related

After find span in UI grid and click got failed: Element is no longer valid

I run function on UI-grid that all element in the grid are clickable.
it('Test1', function() {
element.all(by.css('span.ft-grid-click')).each(function(elmt) {
elmt.getText().then(function(txt) {
if (txt == 'ORO_B_IN_002') {
elmt.click();
return;
}
})
})
});
On screen the element clicked but I got this error:
Failed: Element is no longer valid (WARNING: The server did not provide any stacktrace information).
Help please.
Thanks!
There is a much better way to find an element by text Content: cssContainingText()
Here is, how it will look in your code:
it('Test1', function() {
element(by.cssContainingText('span.ft-grid-click', 'ORO_B_IN_002')).click();
});
This should work for you.

Click an element based on a comparison in protractor

In my e2e testing using protractor,I am taking data from a file and checking whether that data is present in the UI. If present,then click it.
There are about 10 chapters in the page and my file has 2 chapters(indicated as chapterName).I want to check whether the chapterNames in my file are there in the UI and if so,then click one by one.I am working with the below code,but dont know how to do the looping
How to do that in protractor?
element.all(by.repeater('chapter in chapters')).filter(function (ele,index) {
return ele.getText().then(function(text){
return text === chapterName;
});
}).click();
You need to use closure function to achieve looping inside a promise. look at the below example code.
function clickChapterByName(){
var chapterNames= ['chapter-1','chapter-2','chapter-3','chapter-4','chapter-5']
for(i=0;i<chapterNames.length;i++){
function closure(chapterName) {
element.all(by.repeater('chapter in chapters')).filter(function (ele,index) {
return ele.getText().then(function(text){
return text === chapterName;
});
}).click();
}
closure(chapterNames[i])
}
}
Not quite sure that i am correct, but i think you are almost there:
element.all(by.repeater('chapter in chapters')).filter(element=> {
return ele.getText().then(text=> text === chapterName);
});
}).map(element=> element.click());
Result of .filter will be only elements that match condition, so you will get new ArrayElementFinder, and you can iterate thru it with .map()
For your requirement, you need to do loop operation.So you can achieve this by each() method which is available in protractor api.
Code Snippet:
element.all(by.repeater('chapter in chapters')).
each(function (ele, index) {//for looping purpose
ele.getText().then(function(text){
if(text == inputChapterName){
ele.click();//click chapter is
}
});
})

Check if the user has clicked inside a specific div in a component

I have got a global click event in my application.
host: {
'(document:click)': 'handleClick($event)',
},
Everytime the user clicks, my handleClick function will execute. I want to check if the user has clicked in a specific div. I've tried with the following:
handleClick(event){
console.log(event.target===document.getElementsByClassName("drop_down_wrapper")
}
But this does not work. I've also tried to get hold of a specific div by using ElementRef but I only managed to get hold of the native element of my div. Any suggestions?
First of all, getElementsByClassName returns a HtmlCollection, so you might want to use index to access individual items:
handleClick(event) {
console.log(event.target === document.getElementsByClassName("drop_down_wrapper")[0]
}
Or better use querySelector method:
handleClick(event) {
console.log(event.target === document.querySelector(".drop_down_wrapper")
}
However, if your div have inner HTML you would probably need to check if the clicked target is a child of the div or not:
var target = e.target;
var wrapper = document.querySelector(".drop_down_wrapper");
while (target != wrapper && target !== document) {
target = target.parentNode;
}
Add a click handler to the particular div you want to listen on, and add
event.stopPropogation();
This should prevent your document click handler from firing.

Protractor unable to select dropdown option

Hi I have been doing protractor test and I'm having a problem with my tests. My ionic app do have a drop down having a model name and I tried to access it using the model name and it works but the problem is it can not select the exact option that i need to select from that dropdown option. It selects only the first one? I wrote the protractor syntax like this.
element(by.model('generalPowerOfAttorney.grantorGeneralPowerOfAttorneyForm.region')).$('[value="59"]').click();
But this code selects not the value 59 rather value 0 which is the default option. Is there anyone who could help me?
You should add the html source to facilitate the answer.
You can use the filter method in order to get the correct element clicked.
var elements = element.all(by.model('generalPowerOfAttorney.grantorGeneralPowerOfAttorneyForm.region'));
elements.filter(function(elem, index) {
return elem.getText().then(function(text) {
return text === 'value="59"';
});
}).then(function(filteredElem){
if(filteredElem[0] !== undefined){
filteredElem[0].click();
}
else {
throw 'element not found'
}
});

jquery selector must select an area without an element which is in the area

I use jquery click event for a div and the div area has an input element. Because the input element is in the div, when I click input, the click function works, but I don't want this action.
I looked at the selector page in Jquery's website, but I couldn't find this selector. How can I do this?
Use the nodeName property of the originating element to see where the event originated:
$('#myDiv').click(function(event) {
if (event.target.nodeName.toLowerCase() === 'input') {
return; // ignore the event if it originated on an input element
}
// do the rest of your code
});
If you want a more complex query (e.g. using jQuery pseudoselectors), you can use is:
$('#myDiv').click(function(event) {
if ($(event.target).is('input[name="foo"]')) {
return; // ignore the event if it originated on an input element with the name foo
}
// do the rest of your code
});