I am trying to check if element doesn't exist in a DOM Tree with Cypress and testing-library/cypress.
If I try to do cy.getByTestId("my-button").should("not.exist") test fails because it couldn't find element.
If I do cy.findByTestId("my-button").should("not.exist") it also fails because of time out.
The test does work if I do either cy.queryByTestId("my-button").should("not.exist") or
cy.get('[data-testid="my-button"]').should("not.exist").
Can someone please explain what's the difference between all 4.
Thanks
https://testing-library.com/docs/dom-testing-library/api-queries
getBy will throw errors if it can't find the element
findBy will return and reject a Promise if it doesn't find an element
queryBy will return null if no element is found:
This is useful for asserting an element that is not present.
looks like queryBy is your best choice for this problem
In the latest version of Cypress Testing Library they have removed queryBy.
Cypress Testing Library | Intro
If you want to check if something doesn't exist just use findBy, but put a should() straight afterwards. It won't time out in that case.
cy.findByText('My error message').should('not.exist')
Discussion on GitHub
I want to be able to click on a check box and test that an element is no longer in the DOM in Cypress. Can someone suggest how you do it?
// This is the Test when the checkbox is clicked and the element is there
cy.get('[type="checkbox"]').click();
cy.get('.check-box-sub-text').contains('Some text in this div.')
I want to do the opposite of the test above.
So when I click it again the div with the class check-box-sub-text should not be in the DOM.
Well this seems to work, so it tells me I have some more to learn about .should()
cy.get('.check-box-sub-text').should('not.exist');
You can also search for a text which is not supposed to exist:
cy.contains('test_invite_member#gmail.com').should('not.exist')
Here you have the result in Cypress: 0 matched elements
Reference: Docs - Assertions, Existence
Use .should('not.exist') to assert that an element does not exist in the DOM.
Do not use not.visible assertion. It would falsely pass in < 6.0, but properly fail now:
// for element that was removed from the DOM
// assertions below pass in < 6.0, but properly fail in 6.0+
.should('not.be.visible')
.should('not.contain', 'Text')
Migration Docs here: Migrating-to-Cypress-6-0
Cypress 6.x+ Migration
According to cypress docs on Existence
The very popular attempt which is a bit naive will work until it doesn't and then you'll have to rewrite it again... and again...
// retry until loading spinner no longer exists
cy.get('#loading').should('not.exist')
This doesn't really work for the title problem which is what most people will be looking for.
This works for the case that it is being removed. but in the case that you want it to never exist... It will retry until it goes away.
However, if you want to test that the element never exists in our case.
Yes lol. This is what you really want unless you want to just have your headache again another day.
// Goes through all the like elements, and says this object doesn't exist ever
cy.get(`img[src]`)
.then(($imageSection) => {
$imageSection.map((x, i) => { expect($imageSection[x].getAttribute('src')).to.not.equal(`${Cypress.config().baseUrl}/assets/images/imageName.jpg`) });
})
cy.get('[data-e2e="create-entity-field-relation-contact-name"]').should('not.exist');
might lead to some false results, as some error messages get hidden. It might be better to use
.should('not.visible');
in that case.
Here's what worked for me:
cy.get('[data-cy=parent]').should('not.have.descendants', 'img')
I check that some <div data-cy="parent"> has no images inside.
Regarding original question, you can set data-cy="something, i.e. child" attribute on inner nodes and use this assertion:
cy.get('[data-cy=parent]').should('not.have.descendants', '[data-cy=child]')
You can use get and contains together to differentiate HTML elements as well.
<button type='button'>Text 1</button>
<button type='button'>Text 2</button>
Let's say you have 2 buttons with different texts and you want to check if the first button doesn't exist then you can use;
cy.get('button').contains('Text 1').should('not.exist')
Could be done also using jQuery mode in cypress:
assert(Cypress.$('.check-box-sub-text').length==0)
I closed an element and checked should('not.exist') but the assertion failed as it existed in the DOM. It just that it is not visible anymore.
In such cases, should('not.visible') worked for me. I have just started using cypress. A lot to learn.
No try-catch flow in cypress
In java-selenium, we usually add the NoSuchElementException and do our cases. if UI is not displaying element for some Role based access cases.
You can also query for the matched elements inside the body or inside the element's parent container, and then do some assertions on its length:
cy.get("body").find(".check-box-sub-text").should("have.length", 0);
In case anyone comes across this, I was having the issue that neither .should('not.exist') nor .should('have.length', 0) worked - even worse: If the element I was querying was actually there right from the get-go, both asserts still returned true.
In my case this lead to the very strange situation that these three assertions, executed right after each other, were true, even though asserts 1+2 and 3 contradict each other:
cy.get('[data-cy="foobar"]').should('not.exist')
cy.get('[data-cy="foobar"]').should('have.length', 0)
cy.get('[data-cy="foobar"]').should('have.text', 'Foobar')
After extensive testing, I found out that this was simply a race condition problem. I was waiting on a backend call to finish before running the above 3 lines. Like so:
cy.wait('#someBackendCall')
cy.get('[data-cy="foobar"]').should('not.exist')
However once the backend called finished Cypress immediately ran the first two assertions and both were still true, because the DOM hadn't yet caught up rerendering based on the backend-data.
I added an explicit wait on an element that I knew was gonna be there in any case, so my code now looks something like this:
cy.wait('#someBackendCall')
cy.get('[data-cy="some-element"]').should('contain', 'I am always here after loading')
cy.get('[data-cy="foobar"]').should('not.exist')
You can also use below code
expect(opportunitynametext.include("Addon")).to.be.false
or
should('be.not.be.visible')
or
should('have.attr','minlength','2')
Voted element is correct but I highly recommend not to using anti-pattern saving you from a lot of headaches. Why? Yes, because;
Your application may use dynamic classes or ID's that change
Your selectors break from development changes to CSS styles or JS behavior
Luckily, it is possible to avoid both of these problems.
Don't target elements based on CSS attributes such as: id, class, tag
Don't target elements that may change their textContent
Add data-* attributes to make it easier to target elements
Example:
<button id="main" name="submission" role="button" data-cy="submit">Submit</button>
And if you want to be more specific and want to indentify more than one selector, it is always good to use .shouldchainer.
Example:
cy.get("ul").should(($li) => {
expect($li).to.be.visible
expect($li).to.contain("[data-cy=attribute-name]")
expect($li).to.not.contain("text or another selector")
})
If there is no element, we can use simple line like:
cy.get('[type="checkbox"]').should('not.exist')
In my case, Cypress was so fast, that simple .should('not.be.visible') was passing the test and after that, loader appears and test failed.
I've manage to success with this:
cy.get('.loader__wrapper')
.should('be.visible')
cy.get('.loader__wrapper', { timeout: 10000 })
.should('not.be.visible')
Also nice to set the timeout on 10 seconds when your application loads more than 4s.
I would use :
cy.get('.check-box-sub-text').should('not.be.visible');
This is safer than
cy.get('.check-box-sub-text').should('not.exist');
( The element can be present in the DOM but not visible with display: none or opacity: 0 )
I would like to double click on an element but I could not find a way to do this in the document API. I found some references dating back to 2013 but I know things have changed a lot.
Can someone help and tell me how I can perform a double click.
Thanks
Always remember that protractor is a wrapper around webdriverjs.
doubleClick() is available in browser.actions():
browser.actions().doubleClick(element(by.id('mybutton'))).perform();
For anyone looking at this in 2019, this still works. Just know thatProtractor selectors use the Locator object to find elements. The above solution uses the webElement object. So if you're using Protractor to find your element, you'll need to do something like browser.actions().doubleClick(myElement.getWebElement()).perform();
var el=element(by.id('id'));
browser.executeAsyncScript(function() {
var evt=new MouseEvent('dblclick', {bubbles: true,cancelable: true,view: window});
var callback = arguments[arguments.length - 1];
arguments[0].addEventListener('dblclick',callback);
arguments[0].dispatchEvent(evt);
},el).then(function(){...});
await browser.actions().mouseMove(Element).doubleClick().perform();
await browser.actions().doubleClick(Element.getWebElement()).perform();
the above 2 codes works properly to double click on any element when it's visible on screen.
Here Element is
"let Element = element(by.xpath("locator"));"
Below code did not works as a msg is shown saying
"Failed: JavaScript error: arguments[0].dblclick is not a function"
whereas when checked in console similar scripts did worked to double click the item: "$($x(element(by.xpath("locator")))).dblclick()".
Will update my comment if able to find the exact JavaScript syntax to make below code run.
await browser.executeScript("arguments[0].dblclick();",
Element.getWebElement());
IE8 has been throwing this error at me
SCRIPT65535: Unexpected call to method or property access.
load-scripts.php, line 4 character 25690
I removed a .js file from the code, and the error went away. I started commenting functions out, and narrowed it down to this one. With this one commented, I don't get the error. With it active, I do get it
$("title, .ab-item").each(function() {
var text = $(this).text();
text = text.replace("RepAgent", "Review Scout");
$(this).text(text);
});
I've used JSHint and it says that it's valid?
I'm pretty sure that Internet Explorer doesn't like you messing with <title> element contents. That's not really how you set the document title anyway; just set document.title.
jQuery uses appendChild inside $.text() .
Although <title/> has a appendChild-method(inherited from HTMLElement), this method may not be used.(it's also not listed in the title-methods)
I know there are many threads about this issue and i ve been looking for my specific case but i have not found anything relevant.
I am implementing this javascript cashRegister effect in this page but i get this error msg
"Uncaught TypeError: Cannot call method 'get' of null"
It points to the raw 18 of the plugin.js:
var current_value = this.element.get('text');
What might cause this error? What i should try to do now?
Thanks
I think your problem is at this line:
var total = $('total');
The selector total means "find elements with the name 'total'". What you really want is to find the element with the id of "total," so do this instead:
var total = $('#total');
Edit:
I think some of the confusion stems from the fact that the $ in the site you're referencing is the $ from MooTools. In your page, you are including jQuery, which has an entirely different $ object that behaves differently. I believe that $('total') is how you select an element by ID in MooTools.
I'm not sure how you can load both libraries without having naming conflicts, but if you can figure that out, make sure you're using MooTools to select the total instead of jQuery.
Edit 2:
After a bit of research (I'm unfamiliar with MooTools), I see that you could replace $('total') with:
document.id('total')