由于-imo页面设计不佳,我发现自己在验证页面上一个或多个元素的可见性或不存在时遇到了问题。
问题是有些元素不存在,而有些元素具有CSS属性display:none。但是现有的测试代码检查not.exist,这使得测试失败。但我不能更改为not.be.visible,因为那样它将在其他元素上失败。
那么:有可能在断言中做OR吗?有点像
cy.get('blabla').should('not.be.visible').or.cy.get('blabla').should('not.exist');
上面的行进行了编译,但在第二部分产生了一个未定义的结果,所以它不起作用。
这是代码:
(我认为代码体系结构并不重要——问题基本上是OR的问题。(
page.sjekkAtDellaanFelterVises(2, 2, [
DellaanFelter.formaal,
DellaanFelter.opprinneligLaanebelop,
DellaanFelter.utbetalingsdato,
DellaanFelter.restlaanInnfridd,
]);
public sjekkAtDellaanFelterVisesALT(sakRad: number, delLanRad: number, felter: DellaanFelter[]) {
this.sjekkFelter(felter, DellaanFelter, (felt: string) => this.delLanAccordionBody(sakRad, delLanRad).get(this.e2e(felt)));
}
@ts-ignore
public sjekkFelterALT<T, E extends Node = HTMLElement>(felter: T[], enumType, lookupFn: (felt: string) => Chainable<JQuery<E>>) {
this.valuesOfEnum(enumType).forEach(felt => {
this.sjekkFelt(felt, felter, enumType, lookupFn);
});
}
// @ts-ignore enumType fungerer fint i praksis ...
public sjekkFeltALT<T, E extends Node = HTMLElement>(felt: string, felter: T[], enumType, lookupFn: (felt: string) => Chainable<JQuery<E>>) {
if (felter.some(feltSomSkalVises => enumType[feltSomSkalVises] == felt)) {
lookupFn(felt).should('be.visible');
} else {
lookupFn(felt).should('not.exist');
}
}
或者解决方案是先尝试检查元素是否存在,然后如果存在,检查可见性?
您可以使用cypress-if
插件来获得优雅的语法。按照cy.get()
,.if()
结合可见性断言,然后.else()
结合存在性断言。
例如,如果我在页面上有一个<div>
,但它不可见
<div style="display:none">a</div>
这两项测试都将通过
cy.get('div')
.if()
.should('not.be.visible') // passes
.else()
.should('not.exist') // skipped
cy.get('span')
.if()
.should('not.be.visible') // skipped
.else()
.should('not.exist') // passes
我也面临着同样的问题,一些模式在关闭时被销毁(即从DOM中删除(,而另一些则被隐藏。
我找到了一种模仿or
的方法,通过在选择中添加可见性检查作为过滤器,然后断言不存在:
cy.get('my-selector').filter(':visible').should('not.exist')
故障情况下的错误消息并不是不言自明的("预期:visible
不存在"(,您必须进一步阅读日志才能理解。如果你不需要选择器和过滤器之间的分离,你可以将两者结合起来,以获得更好的错误消息("预期my-selector:visible
不存在"(:
cy.get('my-selector:visible').should('not.exist')
tl;dr是,这里不会有一个简单的解决方案——Cypress的get
命令有断言,所以你不能轻易地捕捉或吃掉这些异常。如果您试图获取一个不存在的元素,Cypress将有一个失败的断言。不幸的是,最好的情况是每个断言都有确定性的行为。
有关为什么赛普拉斯会这样做的更多信息,请点击此处。
我认为你最好的做法是写一个自定义的Chai断言,但我没有任何这样做的经验。这是柴这样做的文件。
如果您想简化代码,但知道哪些元素不应该存在,哪些元素不应可见,则可以编写一个自定义命令来处理此问题。
Cypress.Commands.add('notExistOrNotVisible', (selector, isNotExist) => {
cy.get(selector).should(isNotExist ? 'not.exist' : 'not.be.visible');
});
cy.notExistOrNotVisible('foo', true); // asserts that `foo` does not exist
cy.notExistOrNotVisible('bar', false); // asserts that `bar` is not visible
我武断地使不存在正的情况,但你可以切换它和should
中的逻辑。
希望这能对你们中的一些人有所帮助。我已经使用Cypress一段时间了,发现这些特定的自定义命令非常有用。我希望他们也能帮助你。(检查可见性也使用checkExistence命令。您只需使用cy.isVisible((命令,它就会自动检查它是否至少在DOM中,然后再继续(。
附言:这些命令仍在调整中-请注意:(
检查存在的命令
/**
* @param {String} errorMessage The error message you want to throw for the function if no arg is used
*/
const isRequired = (errorMessage = '--- Parameter is required! ---') => { throw new Error(errorMessage); };
/**
* @description Check if an element, found through xpath selector, exists or not in the DOM
* @param {String} xpath Required. Xpath to pass into the function to check if it exists in the DOM
* @param {Object} ifFound Message to pass to cy.log() if found. Default message provided
* @param {String} ifNotFound Message to pass to cy.log() if not found. Default message provided
* @returns Boolean. True if found, False if not found
* @example cy.checkExistence("xpath here", "Found it!", "Did not find it!").then(result=>{if(result==true){ // do something } else { // do something else }})
*/
Cypress.Commands.add('checkExistence',(xpath=isRequired(), ifFound, ifNotFound )=>{
return cy.window().then((win) => {
return (function(){
let result = win.document.evaluate(xpath, win.document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue
if(result!=null && result!=undefined){
if ( ifFound != undefined ) {
cy.log( `_** ${ifFound} **_` );
}
return cy.wrap( true );
} else {
if ( ifNotFound != undefined ) {
cy.log( `_** ${ifNotFound} **_` );
}
return cy.wrap( false );
}
})();
});
})
能见度检查命令
/**
* @param {String} errorMessage The error message you want to throw for the function if no arg is used
*/
const isRequired = (errorMessage = '--- Parameter is required! ---') => { throw new Error(errorMessage); };
/**
* @description Check to see if an element is visible or not, using xpath selector or JQuery element
* @param {String} Xpath Xpath string
* @param {Boolean} waitForVisibility Optional. False by default. Set to true to wait for element to become visible.
* @param {Number} timeout Optional. Timeout for waitForVisibility param.
* @returns Boolean. True if visible, False if not visible
* @example cy.isVisible("//div").then(result=>{})
*/
Cypress.Commands.add('isVisible', (Xpath=isRequired(), waitForVisibility=false, timeout)=>{
cy.checkExistence(Xpath).then(result=>{
if(result==true){
cy.xpath(Xpath).then($element => {
if ($element.is(':visible')){
return cy.wrap(true)
} else {
if(waitForVisibility===true){
if(!timeout){
cy.logSpecial('wave',3, `Must provide value for timeout. Recieved ${timeout}`, true)
} else {
cy.log(`Waiting for element to become visible within ${timeout / 1000} seconds...`, true).then(()=>{
let accrued;
let interval = 250;
(function retry(){
if ($element.is(':visible')){
return cy.wrap(true)
} else {
accrued = accrued + interval;
if(accrued>=timeout){
cy.log(`Timeout waiting for element to become visible. Waited ${timeout / 1000} seconds.`)
return cy.wrap(false)
} else {
cy.wait(interval)
cy.wrap(retry())
}
}
})();
})
}
} else {
return cy.wrap(false)
}
}
})
} else {
cy.log(`Element does not exist in the DOM. Skipping visibility check...`).then(()=>{
if(throwError==true){
throw new Error (`Element of xpath ${Xpath} was not visible.`)
}
return cy.wrap(false)
})
}
})
})
cy.get('my-selector').should($el => {
expect($el.length == 0 || !$el.is(":visible"), "does not exist or is not visible").to.be.true;
})
编辑:@"-1"对不起,我认为有一个错误(应该是!$el.is(":visible")
而不是!$el.is("visible")
(。现在就修复了。