Is it possible to make some verification on several elements after click() with option {multiple:true}?
I have to check text after each click on several buttons with the same selector.
What I want to do:
cy.get(".copy-button").click({multiple: true}).then(() => {
cy.get(".tooltip-name").should('contain', 'Copied successfully!')
]);
You can do with each(), something like:
cy.get('.copy-button').each(($ele) => {
cy.wrap($ele).click()
cy.get('.tooltip-name')
.should('be.visible')
.and('contain', 'Copied successfully!')
})
Related
I need to check whether the radio button is clickable or not. In some scenarios this radio button is clickable but in some scenarios, the user is not able to click the radio button.
The cursor is not allowed in the not clickable scenario.
Can someone help me for this?
I have attached screenshots below.
I have tried many this but not worked.
checkSkipBtnClickable(){
const checkSkipButton = cy.get(':nth-child(3) > .ant-radio-wrapper')
}
Cursor is not allowed to click
Cursor is allowed to click
code
This is the answer I got:
cy.contains('h3', 'Skip')
.parent()
.then($el => $el.css('cursor') === 'not-allowed')
.as('checkSkipButton')
cy.get('#checkSkipButton').then(checkSkipButton => {
if (checkSkipButton) {
cy.log("Skip is not available")
}
else{
cy.log("Skip is available")
}
})
This gives you a true/false value in an alias called checkSkipButton
cy.contains('h3', 'Skip')
.parent()
.then($el => $el.css('cursor') === 'not-allowed')
.as('checkSkipButton')
cy.get('#checkSkipButton').then(checkSkipButton => {
if (checkSkipButton) {
...
}
})
I am writing some basic cypress tests and I just want to make sure that a table we have has all of the correct columns and that any data is rendering.
I know .contains() checks the element selection AND allows text matching, but there could be all sorts of data in this table, I just want to make sure something renders from the backend.
Any idea how to check if there is any (non-specific) value?
Cheers!
describe('Data Source Table renders properly', () => {
beforeEach(() => {
cy.viewport(1920, 1080)
cy.visit('http://localhost:3000/source')
// Assert we are on the correct page /source
cy.url().should('include', '/source')
})
it('Data Source header exists', () => {
cy.contains('Data Source')
})
it('Data Source table exists, column headers are correct and there is data', () => {
cy.get('table').should('exist')
cy.wait(2000)
cy.get('table').contains('th', 'Ip')
cy.get('table').contains('th', 'Station')
cy.get('table').contains('th', 'Table')
cy.get('table').contains('th', 'Status')
})
})
You are right, .contains() allows text matching. It also allows regex matching which you can apply for your situation.
// this will check all td's will have any text
// here is regex example regexr.com/6jmi6
cy.contains('td', /\w/g).should('be.visible')
This is more concise, IMO less prone to error
cy.get('table thead th')
.each($th => {
expect($th.text()).not.to.be.empty
})
You can remove cy.get('table').should('exist') and cy.wait(2000)
I'm trying to test a pagination bar with cypress.
I want to assert the number of buttons containing a number only in this bar, and ignore the other buttons (previous page, next page...)
The buttons are looking like this:
<button class="...">33</button>
I first tried this test:
cy.get('.pagination')
.find('button')
.contains(/\d+/)
.should('have.length.gte', 2)
But this gave me a warning about the fact that contains will only return one element, making the "length" test useless.
I also tried many combinations based on filter, the ":contains" jquery keyword, but none worked:
.filter(`:contains('/\d+\')`)
// >> finds nothing
.filter((elt) => { return elt.contains(rx) })
// >> throws 'elt.contains is not a function'
.filter((elt) => { return rx.test(elt.text()) })
// >> throws 'elt.text is not a function'
.filter(() => { return rx.test(Cypress.$(this).text()) })
// filter everything and return nothing, even the buttons containing the text '1'
.filter() with a callback has parameters (index, elt) => {} which means you can use it like this
cy.get('.pagination')
.find('button')
.filter((index, elt) => { return elt.innerText.match(/\d+/) })
.should('have.length.gte', 2)
nextAll() might work in this situation:
cy
.get('.pagination')
.find('button')
.contains(/\d+/)
.nextAll()
.should('have.length.gte', 2);
Another solution might be to distinguish the pagination buttons by something else, like a class, or some html attribute that is unique to them.
You can use an loop through the elements and match the element text and then increment a count variable and then later validate it, something like:
var count =0
cy.get('.pagination').find('button').each(($ele) => {
if(/\d+/.test($ele.text()){
count++
}
})
expect(count).to.be.greaterThan(2)
You can do other things as well like:
Assertions
cy.get('.pagination').find('button').each(($ele) => {
if(/\d+/.test($ele.text()){
expect(+$ele.text().trim()).to.be.a('number')
}
})
Perform Click
cy.get('.pagination').find('button').each(($ele) => {
if(/\d+/.test($ele.text()){
cy.wrap($ele).click()
}
})
Validate Inner text
cy.get('.pagination').find('button').each(($ele) => {
if(/\d+/.test($ele.text()){
cy.wrap($ele).should('have.text', 'sometext')
}
})
nextAll() fails if there's element wrapping the buttons, but you can count the wrappers.
cy.get('.pagination')
.find('button') // presume this is 'Prev' button
.parent()
.nextAll(':not(:contains(Next))')
.should('have.length.gte', 2)
or .nextUntil()
cy.get('.pagination')
.find('button') // presume this is 'Prev' button
.parent()
.nextUntil(':contains(Next)')
.should('have.length.gte', 2)
or .children()
cy.get('.pagination')
.children(':not(:contains(Prev)):not(:contains(Next))')
.should('have.length.gte', 2)
Overall, .filter() is better as it does not assume the HTML structure.
I'm having trouble recreating this test.
Problem:
It seems that Cypress is only visiting one link from this list whilst looping over each item.
Notes:
I added the length check to make sure that the array of nodes is the correct size
The code within each seems to work fine, since the test runner navigates to the first link
I was looking into the .next() methods, but that returns the next DOM nodes. Still not clear if that might be the issues here
seems like there's no iterator within the each() method
Test Case
GIVEN a personal website
WHEN when I navigate to the /blog page
THEN Cypress find the list of blog posts
AND checks the number of total posts
THEN Cypress loops over those list items
THEN Cypress collects the href
THEN Cypress visits that page
THEN Cypress checks that href includes 'posts'
AND wait 1s
Test Code
describe("Visual regression on /posts/{id}", () => {
sizes.forEach((size) => {
it(`Should match screenshot, when '${size}' resolution'`, () => {
cy.visit("/blog")
cy.get("ul > li > a")
.should("have.length", 9)
.each((element) => {
cy.wrap(element)
.invoke("attr", "href")
.then((href) => {
cy.visit(href);
});
cy.wrap(element)
.should("have.attr", "href")
.and("include", "posts"
cy.wait(1000);
});
});
});
});
Solution
cy.visit("/blog");
cy.get("ul > li > a").should("have.length", 9);
cy.get("ul > li > a").each(($element) => {
cy.wrap($element)
.invoke("attr", "href")
.then((href) => {
cy.wrap(href).should("exist")
cy.visit(href);
cy.wait(2000);
});
});
I seems like the block below is letting Cypress loose track of the current element.
.should("have.length", 9)
Once I split out the rules of the test, I'm no longer seeing any issues and Cypress is correctly navigating through all the pages I need.
I have a page with a few Results panels, each panel has its own delete button.
I wrote a Cypress test to test the delete process, the test works as expected, the panel gets deleted:
cy.get('div[data-test="Results"]')
.first()
.within(() => {
cy.get('p[data-test="Contact ID"]').then($match => {
contactID = $match.html();
cy.get('button[data-test="Delete Contact"]')
.click()
.get('div[data-test="Delete Record Modal"]')
.should('be.visible')
.get('button[data-test="Confirm Deletion"]')
.click();
});
});
Next I'm trying to detect if the correct panel got deleted.
How can I iterate through all the <p />s of all panels and make sure none of them has a contactID equal to the one that was deleted?
I tried this:
cy.get('p[data-test="ContactID"]').then($match2 => {
expect($match2.text()).not.to.eq(contactID);
});
But in $match2 I get all contacts ids all together for example: 12345678 instead of 1234 and 5678
You can use each:
cy.get('p[data-test="ContactID"]').each(($match) => {
cy.wrap($match).invoke('text').should('not.eq', contactID)
})
invoke calls a function on the subject, in this case, .text()
the chained .should makes an assertion on that text
this will retry the assertion until it passes or times out (see retry-ability) due to the cy.wrap