I have a test I am trying to create where I change the name of a card. The problem is there is a hidden error card which has the exact same identifiers as what I am trying to edit. The test returns that the object I am trying to work with is unreachable, which makes sense, it is under the one I am working with.
The locator which I have is: textarea[ng-model="ctrl.currentChartTitle"].
Yes, I know that I can do this by model and tried that, but it yields the same results.
Here is a screenshot of the html the yellow is the on top object I am trying to reach:
Not really sure how do to do the selector for this, so it always works.
So I did a bit more searching and found a solution. It looks a like this:
chartTitleTextArea = this.visualizer.all(by.css('textarea[ng-model="ctrl.currentChartTitle"]')).filter((element) => {
return element.isDisplayed().then((isDisplayed) => {
return isDisplayed
})
}).first()
Basically, what this is doing is getting all of the elements which match that locator. Then filtering them on if isDisplayed() is true. Then grabbing the first one.
Related
I'm trying to parse HTML code in jquery, get an attribute of it and extract a number from the id, and then append it to a string like that:
function sortHTMLContentByStrength(x, y) {
console.log($($.parseHTML(x)));
let strength1 =
parseFloat(($("#team-modal-strength-" + $($.parseHTML(x)[1]).attr("id").match(/\d+/)[0]).html()));
let strength2 =
parseFloat(($("#team-modal-strength-" + $($.parseHTML(y)[1]).attr("id").match(/\d+/)[0]).html()));
return strength2 - strength1;
}
The real problem is:
As you can see, i get this S.fn.init(2). Every single console log looks like this. I roughly know what it means and also it wouldn't be a big deal because I used an index to retrieve only the second element (tr tag) which I'm interested in like that:
$($.parseHTML(x)[1])
I'm just getting the second element of the returned array which is tr tag. This code worked and there was nothing wrong with up until now.
So, now the biggest problem. When I run the same code once more later, I don't receive an array of two objects anymore. I get this:
It's not an array anymore so the indexing trick $($.parseHTML(x)[1]) doesn't work anymore.
I really need to call this sorting function multiple times in my program but due to the issue the app breaks. I would be very thankful for any hints on that.
I have written a custom command for selecting the checkbox based upon the contact name what i provide(Refer the image ) for example I provide Test10 Test10, it does not get selected, However the test case gets passed without selecting, I tried debugging cname variable is empty attaching the debugger screen shot as well
Cypress.Commands.add("SelecttheContact", (contactName) => {
cy.get('tr td:nth-child(2)').each(($el, index, $list) => {
const cname=$el.find(contactName).text()
if(cname.includes(contactName))
{
// cy.get("tr td:nth-child(1)").eq(index).click()
// cy.get("input[type='checkbox']").eq(index).click()
debugger
$e1.find('checkbox').click()
}
}) })
I may be wrong here, but it looks like you are relying on jquery to do the selection work instead of Cypress. I would have used Cypress selection to find the checkbox.
Did you know about the Cypress Selector Playground?
The Selector Playground is an interactive feature that helps you:
Determine a unique selector for an element.
See what elements match a given selector.
See what element matches a string of text.
https://docs.cypress.io/guides/core-concepts/test-runner.html#Selector-Playground
There is also an API option to change the priorities of the selector
The Selector Playground exposes APIs that enable you to:
Change the default selector strategy
Override the selectors that are returned per element
https://docs.cypress.io/api/cypress-api/selector-playground-api.html#Syntax
.find() accepts a selector, according to the docu: https://api.jquery.com/find/
So passing a text content will not work.
text() returns an empty string because if a selector is not found in JQuery you always get an object. And functions called onto that object will return default values I think.
Why the tests passes can not be determined from what we see :-)
I suggest you to adjust the selector for your checkbox.
Btw I am not sure, if you can call cy.get() within each() (the line you have commented out in your code).
Currently I am not at my Laptop, so I can not provide an example for clicking a checkbox. But please try to fix the selector and if it does not work, I can try it for myself.
I want to achieve that my test compares the length of a list. To get the length of my list I`m doing the following :
const oldListCount = cy.get('.grid-row').its('length');
Later in the Test I want to compare the oldListCount with the current length.
newListCount.should('be.gt',oldListCount);
But Cypress says that 'oldListCount' is an [object Object]
I also tried to work with aliases and do an encapsulated .then
like so:
cy.get('.grid-row').its('length').then(newListCount => {
oldLC.then(oldListCount => {
newListCount.should('be.gt', oldListCount.toString());
})
});
But either worked..
Also something worth to mention, when im log both listCounts inside the encapsulated .then the Count is equal, and the UI and the Cypresslogs showing me something else.
For my test it's not important that the Count is a specific number, more important is that the new Count is greater than the old one.
Can somebody please point me in the right direction?
I think something like this will work out
First, you need to save the old list as an alias
cy.get('.grid-row').as('oldList')
and then later in the test
cy.get('#oldList').its('length').then(oldLength => {
cy.get('.grid-row').its('length').should('be.gt' , oldLength)
})
I have solved it by creating the test with a standarized behavior.
So I have no need of saving the count, beacuase I expect always a given response, this should be more Best practice, isn`t it?
I am having a little problem with xpath in seleniumdriver.
I would like an xpath locator to narrow down its selection via two variables using exact matching at different points of the node hiearchy. This part is done.
You may imagine my case as addressing a two dimensional array in the xml with xPath, with each dimension being given as the two variables I have in it(they are standard text searches via js variables, not xpath variables).
What I'm struggling with is the resulting construction does not tell the difference between the elements of the first dimension, so as long as the given variable value is one of the dimensions, it will address every element in the second dimension fine. I can not assume they are unique or they are in any order. I am using it for testing so this is not acceptable.
How can I form an expression that will not doesn't do the same mistake?
I have tried the 'and' expression but both selenium and xpath tools say the value is '1' for 'found' but it doesn't give me a node locator to work with.
Example, my structure looks similar, so addressing it properly by x1/y1 for example looks fine.
//x1//y1
//x1//y2
//x2//y3
//x2//y4
//x3//y5
//x3//y6
Should work, works ok.
//x1x//y1
//x1x//y2
//x2x//y3
//x2x//y4
//x3x//y5
//x3x//y6
(Giving nonexistent input as 1st dimension.) My input is not fault tolerant, I look for exact value so the tests fail here as they should.
//x2//y1
//x2//y2
//x3//y3
//x3//y4
//x1//y5
//x1//y6
DING, the locator finds y values here when it should not(the y vales are on different leaves of the node tree). I need help with this.
Here is the locator in question:
return element(by.xpath(".//div[#name='typeList']//div[.//text()='" + moduleName + "']//div[./text()='" + typeName + "']")).getText();
TypeList is the name of the owner element, it does not make any differnece if I remove it, but please keep it in mind when giving me examples.
In the end, it was indeed a syntactical problem, before the text keywords.
I was trying this
//div[./text()='Zero']//div[./text()='Number']
Instead, I needed something like this.
//div[.//text()='Zero']/div[.//text()='Number']
Apparently the first one does looks for 'Number' regardless the value of the first constraint as long as every is defined in my file(does not have to be in its upward xnode path.)
As a final note, I advise against using the chrome xpath helper as its behavior is near random, it gives different results after deleting and replacing the same expression. Ugh. The only other one for chrome is adware... I figured my result out by trial and error with the firefox xpath checker tool.
1, I ended up needing to additionally add an node upwards for the element for angular select ui tool(we use selectize.js, a searchable select box), else it was confused what to return, but this is unrelated to the original question as I tried that before with the original expression.
2, I also had to add a node between the first and second text search, else it would look for the second expression in the first one too, eg. looking for Number in Zero, and treat it like a valid value if found. The problem still occurs the other way around, this can be fixed too by applying additional type/name constraints in the first one(not in final example to save space).
So this is what I ended up with:
.//div[#name='typeList']//div/div[.//text()='Zero']/div/div/div[.//text()='Number']
I am trying to make a page work for my website using the mootools framework. I have looked everywhere I can think of for answers as to why this isn't working, but have come up empty.
I want to populate several arrays with different data types from the html, and then, by calling elements from each array by index number, dynamically link and control those elements within functions. I was testing the simple snippet of code below in mootools jsfiddle utility. Trying to call an element from array "region" directly returns "undefined" and trying to return the index number of an element returns the null value of "-1".
I cannot get useful data out of this array. I can think of three possible reasons why, but cannot figure out how to identify what is really happening here:
1. Perhaps this array is not being populated with any data at all.
2. Perhaps it is being populated, but I am misunderstanding what sort of data is gotten by "document.getElementBytag()" and therefore, the data cannot be displayed with the "document.writeln()" statement. (Or am I forced to slavishly create all my arrays?)
3. Perhaps the problem is that an array created in this way is not indexed. (Or is there something I could do to index this array?)
html:
<div>Florida Virginia</div>
<div>California Nevada</div>
<div>Ohio Indiana</div>
<div>New York Massachussetts</div>
<div>Oregon Washington</div>
js:
var region = $$('div');
document.writeln(region[2]);
document.writeln(region.indexOf('Ohio Indiana'));
Thanks for helping a js newbie figure out what is going on in the guts of this array.
$$ will return a list of DOM elements. If you are only interested in the text of those DOM nodes, then extract that bit out first. As #Dimitar pointed out in the comments, calling get on an object of Elements will return an array possibly by iterating over each element in the collection and getting the property in question.
var region = $$('div').get('text');
console.log(region[2]); // Ohio Indiana
console.log(region.indexOf('Ohio Indiana')); // 2
Also use, console.log instead of document.writeln or document.write, reason being that calling this function will clear the entire document and replace it with whatever string was passed in.
See an example.