Reputation: 17
Have already reviewed this post (and a few others but this is the most similar), read through Cypress docs about this error message here. I know it's some kind of race error, but can't for the life of me get it right!
I have a drawer containing a dropdown menu. I want to click the first dropdown menu, and select the first option.
Here's a simplified version of my test: Update: Changed to target content of my elements instead of using antd selectors.
it('Adds new involved party to a case', () => {
// click button to open drawer that contains dropdown
cy.contains('Beteiligter')
.should('exist')
.click();
cy.contains('Rolle des Beteiligten')
.should('exist')
.parent()
.children()
.eq(1)
.should('exist')
.click();
// click submit button to create involvedParty
cy.contains('Erstellen').click();
// check that new party has been added to UI
cy.get('.ant-collapse-header')
.contains('Cypress Test Company')
.should('have.length', 1);
)
}
Timed out retrying: cy.click() failed because this element is detached from the DOM.
<div class="ant-row ant-form-item">...</div>
Cypress requires elements be attached in the DOM to interact with them.
The previous command that ran was:
> cy.should()
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.
HTML for form including dropdown(s):
<form id="control-ref" class="ant-form ant-form-horizontal"><span class="sc-bdVaJa bWpFch">Rolle des Beteiligten </span>
<div class="ant-row ant-form-item ant-form-item-has-success">
<div class="ant-col ant-form-item-control">
<div class="ant-form-item-control-input">
<div class="ant-form-item-control-input-content">
<div class="ant-select ant-select-single ant-select-show-arrow">
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="control-ref_role" autocomplete="off" type="search" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="control-ref_role_list" aria-autocomplete="list" aria-controls="control-ref_role_list" aria-activedescendant="control-ref_role_list_0" readonly="" unselectable="on" value="" style="opacity: 0;" aria-expanded="false"></span>
<span
class="ant-select-selection-item" title="Arbeitgeber">Arbeitgeber</span>
</div><span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;"><span role="img" aria-label="down" class="anticon anticon-down ant-select-suffix"><svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></span></span>
</div>
</div>
</div>
</div>
</div><span class="sc-bdVaJa bWpFch">Art des Beteiligten </span>
<div class="ant-row ant-form-item">
<div class="ant-col ant-form-item-control">
<div class="ant-form-item-control-input">
<div class="ant-form-item-control-input-content">
<div class="ant-select ant-select-single ant-select-show-arrow">
<div class="ant-select-selector"><span class="ant-select-selection-search"><input id="control-ref_resource" autocomplete="off" type="search" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="control-ref_resource_list" aria-autocomplete="list" aria-controls="control-ref_resource_list" aria-activedescendant="control-ref_resource_list_0" readonly="" unselectable="on" value="" style="opacity: 0;"></span>
<span
class="ant-select-selection-placeholder"></span>
</div><span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;"><span role="img" aria-label="down" class="anticon anticon-down ant-select-suffix"><svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></span></span>
</div>
</div>
</div>
</div>
</div>
<div class="ant-row ant-form-item">
<div class="ant-col ant-form-item-control">
<div class="ant-form-item-control-input">
<div class="ant-form-item-control-input-content"><button type="submit" class="ant-btn ant-btn-primary"><span>Erstellen</span></button></div>
</div>
</div>
</div>
</form>
Upvotes: 1
Views: 4290
Reputation: 179
Answer by @user14903560 is really good.
But I like using Cypress Testing Library
Using this, your test will then look like:
it('Adds new involved party to a case', () => {
cy.findByLabelText(/rolle des beteiligten/i).click({ force: true }); // need to use `force: true` here, since antd input select is covered by some span
// Note that, for this to work, you need to have `htmlFor` set on label of this input and `id` set on input component.
cy.findByTitle(/mandant/i).click(); // choose Mandant option
}
You can use Testing Playground Chrome Extension, to get appropriate queries for the component in your live app. This doesn't work well in cypress window.
For debugging you can use the answer by @user14903560
Upvotes: 0
Reputation:
The ant-design components are quite complicated to test because of the way semantic source elements are compiled into more complicated html structures to handle things like visibility and transitions.
May be best to avoid using the ant classes as selectors since they are re-used on lots of components. Also a good chance they will change with new release of the library. Instead focus on the content specific to your page elements.
Debugging
This dropdown is hard to debug in dev-tools, because as soon as you inspect an element the dropdown looses focus and disappears, then the inspected DOM changes too. To get around that, I turned off the style that hides the list, in dev-tools
.ant-select-dropdown-hidden { // select the element with this in dev-tools
/* display: none; */ // then uncheck this style
} // the list will now stay open for inspection
Your test
it('Adds new involved party to a case', () => {
// click button to open drawer that contains dropdown
cy.contains('span', 'Rolle des Beteiligten') // this is a plain span, used as a label
.next() // the next sibling has the Select
.find('.ant-select') // move to the select
.click() // open it
cy.get('div[title="Mandant"]') // with the menu open, find the item
.click({force: true}) // the menu listbox has display:none
// so use force to make the click work
// (try without force, observe the error)
}
You could add a test id to the source code,
<Select data-cy="rolle-des-beteiligten" ...
then use it to simplify the selector
it('Adds new involved party to a case', () => {
// click button to open drawer that contains dropdown
cy.get('[data-cy="rolle-des-beteiligten"]') // get the select
.click() // open it
cy.get('div[title="Mandant"]') // with the menu open, find the item
.click({force: true}) // the menu listbox has display:none
// so use force to make the click work
// (try without force, observe the error)
}
Upvotes: 1