Getting the number of a specific elements inside a div on Cypress - cypress

How to get the number of divs that contain 'userid' from the div with id="chatListHolder"
https://i.stack.imgur.com/QzzLh.png

If a command that yields an element finds more than one element, it will yield all of them. So, we can then check the yielded array of element's length.
cy.get('#chatListHolder')
.should('have.length', 1); // we can change that 1 to whatever number we'd like
// or if we need to do something with that
cy.get('#chatListHolder')
.its('length').should('be.gt', 1);
// or another possibility
cy.get('#chatListHolder')
.its('length')
.then((length) => {
// whatever needs to be done with the length variable
});

Related

How to count dom elemnts with Cypress?

I would like to count the number of elements in the dom that are checked
Example :
cy.get('.p-multiselect-item .p-highlight').its('length');
You are using p-multiselect-item as a class (leading dot) but actually it's a tag.
Try
cy.get('p-multiselect-item .p-highlight') // find <p-multiselect-item>
// with children having class p-highlight
.its('length')
.should('eq', 2)
Have you tried this :
cy.get('#groupSelect').children('option').length
if not you have some answer here :
How to count DOM elements in Cypress assertion

How to test the text of the second element in cypress?

I can test the first element of the Dom element but I don't know how to get the second element?
it('should display highlight', () => {
const highlights = cy.get(`.${pageClass} .page_highlight`);
highlights.should('have.length', 2);
highlights.first().should('contain.text', translations.highlight);
});
There are two options for your case.
Since the total number of elements is just two in your case, you can use something called last. You can read more here.
If the number of elements is dynamic, you can use something called eq and pass the order of element as an index. You can read more here.

How to select elements with same ID but in different shadow DOMs

So I'm working at a co. as a summer intern and have been tasked with writing tests for their application in cypress.
The application extensively uses shadow DOMs and nested shadow DOMs even. I used the includeShadowDom property true to traverse more easily. But I am facing an issue.
I need to type in 2 input boxes having the same ID and same class but they are in separate shadows. Is there a way I can distinguish between them i.e First occurrence of element with id= and nth occurrence of element with id=?
I can't share any code because it goes against company policy
Assuming you have added includeShadowDom: true in your cypress config file then you can use the eq method to get the respective elements.
E.g. eq(0) for first occurrence of the element, eq(1) for the second and so on.
So your code should look like this:
cy.get('input').eq(0).type('some text')
First possible solution is to select every input with class = something and loop over each.
let words = ['First input', 'second input']
cy.get(`input[class="something"]) // this returns x number of Inputs
.each( ($el, index) => {
cy.get($el)
.type(words[index])
})
Second possible solution is to target the parent element incasing the single input.
cy.get('table') //I don't know what is incasing your inputs but lets assume its a table
.within( () => {
cy.get(`input[class="something"`] //trying to get this to return 1 element
.type('words')
})
Without seeing your HTML markup I can't offer up a more exact solutions. Hope this helps. Look up parent() and parentsUntil() cypress commands if you try the second option.
With inputs there's usually some text that allows the user to distinguish them.
Try targeting the input label or placeholder text, finding the input with "Traversal" commands.
<div>
<label>User name</label>
<input type="text" placeholder="Enter user name" />
<div>
Some basic approaches:
cy.contains('label', 'User name')
.next() // move to next element in the DOM
.type('something')
cy.contains('div', 'User name') // go to common parent of label and input
.find('input') // gives just the input inside parent
.type('something')
cy.get('input[placeholder="Enter user name"]') // use unique placeholder attribute
.type('something')
With shadow DOM be aware you can configure it in the test header
it('searches inside all shadow dom roots', {includeShadowDom: true}, () => {
...
})

Cypress - counting number of elements in an array that contain a specific string

Attempting to confirm that of all the schema in the head of a page exactly 3 of them should have a specific string within them. These schemas have no tags or sub classes to differentiate themselves from each other, only the text within them. I can confirm that the text exists within any of the schema:
cy.get('head > script[type="application/ld+json"]').should('contain', '"#type":"Product"')
But what I need is to confirm that that string exists 3 times, something like this:
cy.get('head > script[type="application/ld+json"]').contains('"#type":"Product"').should('have.length', 3)
And I can't seem to find a way to get this to work since .filter, .find, .contains, etc don't filter down the way I need them to. Any suggestions? At this point it seems like I either need to import a custom library or get someone to add ids to these specific schema. Thanks!
The first thing to note is that .contains() always yields a single result, even when many element match.
It's not very explicit in the docs, but this is what it says
Yields
.contains() yields the new DOM element it found.
If you run
cy.get('head > script[type="application/ld+json"]')
.contains('"#type":"Product"')
.then(console.log) // logs an object with length: 1
and open up the object logged in devtools you'll see length: 1, but if you remove the .contains('"#type":"Product"') the log will show a higher length.
You can avoid this by using the jQuery :contains() selector
cy.get('script[type="application/ld+json"]:contains("#type\": \"Product")')
.then(console.log) // logs an object with length: 3
.should('have.length', 3);
Note the inner parts of the search string have escape chars (\) for quote marks that are part of the search string.
If you want to avoid escape chars, use a bit of javascript inside a .then() to filter
cy.get('script[type="application/ld+json"]')
.then($els => $els.filter((index, el) => el.innerText.includes('"#type": "Product"')) )
.then(console.log) // logs an object with length: 3
.should('have.length', 3);

D3 - Maintaining Sort on Data Change

I'm ripping my hair out trying to figure this out.
I have a table being refreshed via WebSocket. It feeds an object with frequency counts. The key is a term. The value is a count. I take this and convert it to an array of arrays, where the top level array contains arrays of the format [key, value]. This works.
I sort and slice the array to get the Top 10. This works.
I feed this 2-dimensional array into d3.
d3.select('#table').select('tbody').selectAll('tr').data(dataArray, (element) => {
return element[0];
});
Now, first of all, I can't print this to peek at the update selection. Not on Chrome. Not on Firefox. No access to the selection data, just the _groups which does not include the exit() elements in the same place so there's no way to verify. But, fine. Whatevs.
I do this:
const enterRows = selection.enter().append('tr')
enterRows.append('td').classed('key', true).text((element) => { return element[0]; });
enterRows.append('td').classed('value', true);
enterRows.merge(selection).select('.value').text((element) => { return element[1]; })
selection.exit().remove();
At this point, the rows aren't ordered. I would expect them to be ordered. But they're not. Fine. Whatever.
selection.order();
Does nothing.
What do I do?
EDIT:
Here's a sample of the array as it goes into data():
[['B': 5], ['C': 3], ['A': 2]]
I can make no sense of the resulting table row order.
I just want to preserve the incoming array order.
enterRows.merge(selection).order() does the trick. No idea why it's necessary since ordering is supposed to be stable, but it does.

Resources