这里的基本问题是Cypress命令与创建它们的测试代码异步运行。如果在您的代码中放置控制台日志,您可以看到这一点。
var myID;
cy.get('#MYID')
.then(($txt) => {
myID= $txt.text();
console.log('1', myID);
})
.should('not.equal', null);
console.log('2', myID);
这将打印出来
2 undefined
1 myText
你可以使用别名来解决这个问题,并将值传递到命令链中。
请参阅文档部分,其中展示了与你在“不要使用此示例”中使用的代码类似的模式。
但是,别名在测试之间被清除,因此你应该设置beforeEach()
以获取所需ID的新副本用于每个测试。
你获取文本值的方式还有另一个问题。
如果没有返回语句,则.then()
命令会将它接收到的任何主题传递给下一个命令。请见then-Yields。
此外,回调函数中最后一个Cypress命令的结果将作为新主题生成,并流入下一个命令(如果没有返回)。
因此,.should('not.equal',null)
测试的是元素不为空,而不是文本不为空。
更好的方法是使用
.invoke('text')
,它等同于
$txt.text()
并将文本值提供给
.should()
。
此外,
.should('not.equal', null)
不能测试内容是否存在,因为空元素从
element.text()
返回一个空字符串。请改用
.should('not.equal', '')
。
通过别名保存
describe('grabbing ID for use in multiple tests', () => {
beforeEach(() => {
cy.visit('my-page-1.html')
cy.get('#MYID')
.invoke('text')
.as('mySavedID')
})
it('ID should not be null', () => {
cy.get('@mySavedID')
.should('not.equal', '')
})
it('ID should be found in table', () => {
cy.visit('app/navigate-to-new-page-2.html');
cy.get('@mySavedID').then(myID => {
cy.get('#myTable').find('td').contains(myID);
})
})
})
通过排队设置变量来节省
如果访问页面#1需要很长时间,则别名模式可能不是理想的选择。
在这种情况下,您可以通过自定义命令来保存变量。不同之处在于,您在.then()
中的代码被移动到一个排队的命令中,因此异步问题不会发生。
describe('grabbing ID for use in multiple tests', () => {
let savedVariable;
Cypress.Commands.add("saveVariable", {prevSubject: true}, (value) => {
savedVariable = value;
});
it('id should not be null', () => {
cy.visit('my-page-1')
cy.get('#someId')
.invoke('text')
.should('not.equal', '')
.saveVariable()
cy.wrap(savedVariable)
.should('not.equal', '')
})
it('id should be found in table', () => {
cy.visit('my-page-2');
cy.get('#myTable').find('td').contains(savedVariable);
})
})
注意
如果两个页面在同一个域内,例如SPA的两个页面,则上述内容有效。否则,当遇到新域时,测试运行程序会重置自身,并且所有JavaScript变量都会丢失。
#MYID
在一个页面上,我们称之为页面1,而#myTable
在另一个页面上...是这样吗? - soccerway