我在使用 Cypress 为 React 组件编写集成测试时遇到问题。具体来说,尽管能够成功登录并打开对话框,但我在从对话框中的 Material-UI Select 组件中选择选项时遇到了困难。
这是我收到的错误消息:
timed out retrying after 4000ms: expected to find element ul > li[data-value="RuV (Wiesbaden, DE)"], but never found it.
测试只是偶尔通过,成功率约为 1%。 React 应用程序为 Corda 网络的前端提供服务,该网络在 kubernetes 集群中运行。我正在使用 skaffold 将开发环境部署到集群。
这是对话框组件的简化版本:
<Grid container spacing={2}>
<Grid item xs={12}>
<FormikFormControlSelect
formik={formik}
label="Insurers"
id="insurers"
variant="outlined"
dataCy="insurers"
fullWidth
multiple
disabled={promiseInProgress}
>
{memberships.insurers?.map((membership, index) => (
<MenuItem
data-cy={`select-option-${formatCordaX500Name(membership.identity)}`}
key={index}
value={formatCordaX500Name(membership.identity)}
>
{formatCordaX500Name(membership.identity)}
</MenuItem>
))}
</FormikFormControlSelect>
</Grid>
这是我的测试代码:
describe('MachineDialog', () => {
it('should add a new machine successfully', () => {
// Login
cy.visit('https://xx.xx.test.xxxxxx.com/machines');
cy.get('input#username').type('xxx');
cy.get('input#password').type('xxxxxxxx');
cy.get('input#kc-login').click();
// Go to machines page and open New Machine btn
cy.get('[data-cy="new-machine-btn"]').click({ force: true });
// Machine Insurer
cy.get('#insurers-select', { timeout: 10000 }) // increase don't reduce timeout
.parent()
.should('be.visible')
.as('insurers-select') // alias the parent for further queries
.click(); // don't force click
cy.get('@insurers-select', { timeout: 10000 }).find('li').should('have.length.gt', 0); // make sure the options are loaded
cy.get('@insurers-select') // make sure the dropdown is specified
.contains('li', 'RuV (Wiesbaden, DE)')
.should('be.visible')
.click();
}
格式CordaX500名称:
/**
* Function formats the X.500N name into a human readable string
* @function
* @param cordaX500Name Corda X.500 name
*/
export const formatCordaX500Name = function (cordaX500Name: CordaX500NameDto): string {
return `${cordaX500Name.organization} (${cordaX500Name.locality}, ${cordaX500Name.country})`;
};
运行时 DOM:
index-b28d6e1f.js:133631 Error: AssertionError: Timed out retrying after 4000ms: Expected to find element: `li`, but never found it. Queried from:
> cy.get(@insurers-select, [object Object])
at Context.eval (webpack://xxxxxx.com/./cypress/e2e/machineDialogInt.cy.ts:49:62)
at runnable.fn (https://xxxxxx.com/__cypress/runner/cypress_runner.js:138678:19)
at callFn (https://xxxxxx.com/__cypress/runner/cypress_runner.js:157289:21)
at Runnable.run (https://xxxxxx.com/__cypress/runner/cypress_runner.js:157276:7)
at <unknown> (https://xxxxxx.com/__cypress/runner/cypress_runner.js:163200:30)
at PassThroughHandlerContext.finallyHandler (https://xxxxxx.com/__cypress/runner/cypress_runner.js:4072:23)
at PassThroughHandlerContext.tryCatcher (https://xxxxxx.com/__cypress/runner/cypress_runner.js:1807:23)
at Promise._settlePromiseFromHandler (https://xxxxxx.com/__cypress/runner/cypress_runner.js:1519:31)
index-b28d6e1f.js:133631 Actual: 0
index-b28d6e1f.js:133631 Expected: 0
index-b28d6e1f.js:133631 Subject: jQuery.fn.init {length: 0, prevObject: j…y.fn.init, selector: 'li'}
index-b28d6e1f.js:133631 Message: expected { Object (length, prevObject, ...) } to have a length above 0 but got 0
index-b28d6e1f.js:133634 AssertionError: Timed out retrying after 4000ms: Expected to find element: `li`, but never found it. Queried from:
> cy.get(@insurers-select, [object Object])
at Context.eval (webpack://payperchain-dashboard/./cypress/e2e/machineDialogInt.cy.ts:49:62)
at runnable.fn (cypress_runner.js:138678:19)
at callFn (cypress_runner.js:157289:21)
at Runnable.run (cypress_runner.js:157276:7)
at <unknown> (cypress_runner.js:163200:30)
at PassThroughHandlerContext.finallyHandler (cypress_runner.js:4072:23)
at PassThroughHandlerContext.tryCatcher (cypress_runner.js:1807:23)
at Promise._settlePromiseFromHandler (cypress_runner.js:1519:31)
logError @ index-b28d6e1f.js:133634
(anonymous) @ index-b28d6e1f.js:145969
emit2 @ index-b28d6e1f.js:139329
(anonymous) @ cypress_runner.js:182180
emit @ cypress_runner.js:146549
emit @ cypress_runner.js:182243
onPrint @ cypress_runner.js:200038
_onPrintClick @ cypress_runner.js:200042
(anonymous) @ cypress_runner.js:199743
executeAction @ cypress_runner.js:180885
n @ cypress_runner.js:180885
ca @ cypress_runner.js:245
ja @ cypress_runner.js:246
ka @ cypress_runner.js:246
wa @ cypress_runner.js:248
Aa @ cypress_runner.js:249
ya @ cypress_runner.js:249
Da @ cypress_runner.js:252
Ad @ cypress_runner.js:315
Gi @ cypress_runner.js:481
Kb @ cypress_runner.js:270
Dd @ cypress_runner.js:317
(anonymous) @ cypress_runner.js:482
exports.unstable_runWithPriority @ cypress_runner.js:537
Ii @ cypress_runner.js:482
Cd @ cypress_runner.js:316
未选择任何选项时 DOM 中的 html 元素:
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">
<div class="MuiFormControl-root MuiFormControl-fullWidth" id="insurers">
<label class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined" data-shrink="false" id="insurers-label">Insurers</label>
<div class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl" data-cy="insurers">
<div class="MuiSelect-root MuiSelect-select MuiSelect-selectMenu MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input" role="button" aria-haspopup="listbox" aria-labelledby="insurers-label insurers-select" id="insurers-select" tabindex="0">
<span></span>
</div>
<input aria-hidden="true" tabindex="-1" class="MuiSelect-nativeInput" value="">
<svg class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
<path d="M7 10l5 5 5-5z"></path>
</svg>
<fieldset aria-hidden="true" class="jss54 MuiOutlinedInput-notchedOutline">
<legend class="jss56"><span>Insurers</span></legend>
</fieldset>
</div>
</div>
</div>
当我手动选择一个选项时,DOM 中的 html 元素:
<ul class="MuiList-root MuiMenu-list MuiList-padding" role="listbox" tabindex="-1" aria-labelledby="insurers-label">
<li class="MuiButtonBase-root MuiListItem-root MuiMenuItem-root Mui-selected MuiMenuItem-gutters MuiListItem-gutters MuiListItem-button Mui-selected" tabindex="0" role="option" aria-disabled="false" data-cy="select-option-RuV (Wiesbaden, DE)" data-value="RuV (Wiesbaden, DE)" aria-selected="true">
RuV (Wiesbaden, DE)
<span class="MuiTouchRipple-root"></span>
</li>
</ul>
总的来说,问题似乎是您在单击打开下拉菜单后没有等待页面响应。
Cypress 告诉我们最佳实践是
.click()
我无法准确说出,因为需要更多细节。
对测试代码的一些改进:
cy.get('#insurers-select', {timeout:5000) // increase don't reduce timeout
.parent()
.should('be.visible')
.as('insurers-select') // alias the parent for further queries
.click() // don't force click
cy.get('@insurers-select')
.find('li')
.should('have.length.gt', 0) // make sure the options are loaded
cy.get('@insurers-select') // make sure the dropdown is specified
.contains('li', 'RuV (Wiesbaden, DE)')
.should('be.visible')
.click()
显然这可能无法解决您的问题,但您应该修改您的问题以提供足够的细节。