Cypress: cy.click() failed because this element is detached from the DOM - cypress

I'm facing an issue with Cypress 4.7.0. Below is the error code that I'm getting while trying to automate the user creation scenario on the website automationpractice.com
The method cy.click() failed because this element is detached from the DOM.
<input type="password" class="is_required validate form-control" data-validate="isPasswd" name="passwd" id="passwd">
Cypress requires elements to be attached in the DOM to interact with them.
The previous command that ran was:
cy.get()
This DOM element likely became detached somewhere between the previous and current commands.
Common situations why this happens:
Your JS framework is re-rendered asynchronously.
Your app code reacted to an event firing and removed the element.
Code sample for the above scenario:
describe("Cypress demo script", () => {
it("triage DOM issue", () => {
const uuid = () => Cypress._.random(0, 1e6);
const id = uuid();
cy.visit("http://automationpractice.com/index.php");
cy.wait(2000);
cy.contains("Sign in").click();
const email = "tester" + id + "#yopmail.com";
cy.get("#email_create").type(email);
cy.get("#SubmitCreate > span").click();
cy.get("form#account-creation_form").within(($form1) => {
cy.get("input#id_gender1").click();
cy.get("input#customer_firstname").type("Automation");
cy.get("input#customer_lastname").type("tester");
cy.get("input#passwd").click({ force: true }).type("Qwerty#123");
});
});
});
Based on the searches, it was advised to use {force: true}, but it didn't work. Also, I tried to embed the searches within the form, it didn't work either.

As of Cypress version 12, there is new code (internally) that checks for elements detached from the DOM, so instead of throwing the error it now automatically does what the error message suggests and re-queries the selector.
Please see https://docs.cypress.io/guides/references/changelog#12-0-0
Additionally in this release, enhancements were made to how Cypress manages DOM element resolution to reduce the likelihood of hitting detached DOM errors due to maintaining stale DOM references. We've updated our [Retry-ability Guide[(https://docs.cypress.io/guides/core-concepts/retry-ability) with all the details if you'd like to learn more.

Related

How to use recurse method in cypress

*I tried this code first time its working fine the second time it failed got error.
cy.eq() failed because this element is detached from the DOM.
...
Cypress requires elements be attached in the DOM to interact with them.
The previous command that ran was:
> cy.get()
This DOM element likely became detached somewhere between the previous and current command.
Common situations why this happens:
- Your JS framework re-rendered asynchronously
- Your app code reacted to an event firing and removed the element
You typically need to re-query for the element or add 'guards' which delay Cypress from running new commands.
All 2 subject validations failed on this subject.*
code:
recurse(
() => cy.get('selectorA').should(Cypress._.noop),
($button) => $button.length === 0,
{
post() {
cy.get('selectorA').eq(0).trigger('mouseover', { bubbles: false });
cy.get('selectorB').eq(0).click({ force: true }).wait(1000);
},
delay:1000,
limit:10,
timeout:15000
}
)

Expected to find element: #VTK-j_idt1363, but never found it

I am facing an issue on clicking an element. I need an element to be clicked while the network is slow by not using wait() and pause().The page loads after or more than 35sec(350000).Could someone help me to solve the issue,please?
Here is my coding.
it('Test ship',function(){
cy.viewport(1120,800)
cy.visit('url')
cy.get('#LoginForm-nfr_login_authname').type('username')
cy.get('#LoginForm-nfr_login_authid').type('paSSw0rd')
cy.on('uncaught:exception', (err, runnable) => {
return false
})
//These two were the elements present in the same page.The Workspace (first command) gets loaded and error occurs before clicking the second element.
cy.wait[ cy.xpath('//span[normalize-space()="Work Space"]') .click({force: true})]
//here I have used wait
cy.wait(80000)
cy.get('#VTK-j_idt1262').click({force: true})
})
I have tried many possible ways such as alias,etc..,
Please let me know about the solution to wait for page loading without using wait() and pause() command.
error img

Cypress identify a document element inside DOM

I have an application that has a document section showing some notes and I am trying to identify and verify the text ("Release Notes") with Cypress. But all my locating strategies are failing and need some help. Please see if you can recommend some other way to locate this.
DOM:
Below is my code:
cy.get('.release-notes')
.should('be.visible')
.then((text => {
cy.log(text.text()) // blank
cy.log(text) // <span.release-notes>
}))
cy.get('[data="release-notes.html"]').should('be.visible').then((text => {
cy.log(text.text()) // blank
cy.log(text) // <object.release-notes-object>
}))
//Below lines - Fails
//cy.get('h1:contains("Release Notes")') -- Timed out retrying after 4000ms: Expected to find element: h1:contains("Release Notes"), but never found it.
//cy.get('body').should('contains', "Release Notes"); --Timed out retrying after 4000ms: object tested must be an array, a map, an object, a set, a string, or a weakset, but object given
Note: I have "includeShadowDom": true inside my cypress.json
You may be getting blocked by the #document. It does not look like an iframe, but may behave like one.
Try
cy.get('object.release-notes-object')
.its('0.contentDocument').should('exist')
.its('body').should('not.be.undefined').within(() => {
cy.get('h1').should('contain', 'Release Notes')
})
Also turn off chromeWebSecurity in case there's a cross-domain issue
cypress.json
{
"chromeWebSecurity": false
}
Debugging the inner document
Since you can get into the inner document body, in theory you should now be able to query it.
Take a look at the DOM inside body from Cypress' perspective, experiment with timing - the release notes likely to be fetched from a server
cy.get('object.release-notes-object')
.its('0.contentDocument').should('exist')
.its('body').should('not.be.undefined')
.then($body => {
cy.wait(10000) // just for debugging, explicit wait here
.then(() => console.log($body[0].innerHTML)) // inspect the elements inside after wait
})
Another way, add a .should() to retry
cy.wait(10000) // for debugging only, waiting for fetch
cy.get('object.release-notes-object')
.its('0.contentDocument').should('exist')
.its('body', {timeout: 10000}) //vary timeout here
.should('not.be.undefined')
.should('have.descendants', 'h1') // retries the body fetch until true
The difference between the last and adding a timeout to cy.get('h1') is that .should('have.descendants', 'h1') will re-query the body during each retry.
It's possible that there is an empty body element before the release notes are fetched, and it is replaced when the release notes are added.
Before the "includeShadowDom": true global flag we have to do something like this:
cy.get('selector').shadow().find('selector')
Now may be you can omit the .shadow() part and try
cy.get('[app-name="Voyage Planning"]').find('h1:contains("Release Notes")')
You have attributes data-gr-ext-installed and data-new-gr-c-s-check-loaded on the body. These look like they mark the end of something loading.
Add a check for that in #Mihi's solution (which must be nearly correct).
cy.get('object.release-notes-object')
.its('0.contentDocument').should('exist')
.its('body')
.should('not.be.undefined')
.should('have.attr', 'data-gr-ext-installed') // or data-new-gr-c-s-check-loaded
.within(() => {
cy.get('h1').should('contain', 'Release Notes')
})

When running tests with cypress got error "Uncaught TypeErrror: Cannot set property 'innerHTML' of null"

I am new to Cypress and trying to test a Ruby on Rails web application, using stand alone Cypress.
Here is test code
/// <reference types="cypress" />
context('Login', () => {
it('cy.title() - get the title', () => {
cy.visit('https://apps.novabadmintonclub.com')
cy.title().should('include', 'Northern Virginia Badminton Club')
cy.get(':nth-child(2) > .nav-link').click()
cy.get("#user_email").type("john.doe#gmail.com")
cy.get("#user_password").type("xx")
cy.get('.actions > input').click()
})
})
The test fails with the error "Uncaught TypeErrror: Cannot set property 'innerHTML' of null"
I am using latest version 4.3.0 of Cypress on OSX.
If I change the visit url directly to sign in page https://apps.novabadmintonclub.com/users/sign_in, it works fine.
So looks like either the whole dom is not rendered before type starts to add text or something else.
Using the following code I have got this to work.
Also using latest cypress version, please make sure you're closing your statements as well.
Also I didn't do it but i'd always recommend doing assertions after you get statements so asserting the values you've entered actually exist.
describe('stack overflow test', () => {
it('should navigate and attempt to login to badminton club', () => {
cy.visit('https://apps.novabadmintonclub.com');
cy.get(':nth-child(2) > .nav-link').click({force: true});
cy.get('#user_email').type('john.doe#gmail.com');
cy.get('#user_password').type('xx');
cy.get('.actions > input').click();
});
});
Here is a screenshot of the cypress GUI to prove it pops up with the error message.
This issue was indeed an application code error. I had javascript code document.getElementById('clock').innerHTML looking for a dom ID which was not there, hence the error. After I added a null check for that dom ID, Cypress test worked fine.

How to get DetailsList/Selection component on React Fabric UI to work with ReactHooks?

I'm having issue getting the React Fabric UI DetailsList to work with React Hooks. It renders, but the selection part does not. Whenever, you select a row, I expect the count of the selection to be updated. However, i'm not seeing that. It looks like the selection component items never get updated even thou the UI shows it being selected. I'm also seeing the onSelectionChange being triggered when you select a row. Now sure if its because i'm using react hooks or what
I took the provided class example which works:
[Codepen]https://codepen.io/pen/?&editable=true (Example)
Same as the original but stripped down
[Codepen]https://codepen.io/darewreckk/pen/NQRWEd?editors=1111
converted it to a react hook component. I would expect the same thing, but i'm not and can't figure out what's different.
Modified Example with Hooks
[Codepen]https://codepen.io/darewreckk/pen/GVjRNb?editors=1111
Any advice appreciated,
Thanks,
Derek
The selection count is stored on the Selection object that you are creating. You could log it out like so:
const _selection = new Selection({
onSelectionChanged: () => {
console.log('Selected count:' + _selection.count);
}
});
You can set the value of selectionCount and selectionDetails whenever onSelectionChanged is called:
const _selection = new Selection({
onSelectionChanged: () => {
setSelectionCount(_selection.count);
setSelectionDetails(`${_selection.count} items selected`)
}
});
As a side note: If you want selectionDetails to update when selectionCount updates, you can use the useEffect hook:
React.useEffect(() => {
setSelectionDetails(`${selectionCount} items selected`);
}, [selectionCount]);
The above effect will run whenever selectionCount updates, and so in turn update selectionDetails.

Resources