如何在赛普拉斯中返回文档尺寸以供以后测试 [英] How to return dimensions of document in Cypress for use in test later
问题描述
我在Cypress support / index.js中有一个函数,用于获取 cy.document
outerWidth $ c的尺寸$ c>和
outerHeight
,然后将它们返回以供将来在测试中使用。我的问题是,当测试运行并且将值与其他值进行比较时,断言说值是 NaN
。我通过控制台检查了断言时的值,该值是空的,因此我必须做错了什么,我不确定。我的函数在下面,感谢所有收到的帮助,谢谢。
I have a function in Cypress support/index.js that is meant to get the dimensions of the cy.document
outerWidth
and outerHeight
, then return them for future use in a test. My problem is that when the test runs and the values are compared with others the assertion says the values are NaN
. I checked by console logging the value at the point of the assertion and it was empty, so I must be doing something wrong, I'm just not sure what. My function is below, any help gratefully received, thanks.
function getViewport() {
var viewport = {}
cy.document().then((doc) => {
let width = Cypress.$(doc).outerWidth()
let height = Cypress.$(doc).outerHeight()
viewport['bottom'] = height
viewport['height'] = height
viewport['left'] = 0
viewport['right'] = width
viewport['top'] = 0
viewport['width'] = width
viewport['x'] = 0
viewport['y'] = 0
}).then(() => {
return viewport
})
return viewport
}
调用 getViewport()
的代码是
export const getRect = (obj) => {
var rect
if (obj == 'viewport') {
rect = getViewport()
} else {
rect = getElement(obj)
if (Cypress.config('parseLayoutToInt')) { rect = parseAllToInt(rect) }
}
return rect
}
然后通过自定义命令调用,其中 subject
是 prevSubject
,元素是字符串视口
And that is called by a custom command, where subject
is prevSubject
and the element is the string "viewport"
Cypress.Commands.add('isInside', { prevSubject: true }, (subject, element, expected) => {
var minuend, subtrahend, diff
minuend = getRect(element)
subtrahend = getRect(subject)
diff = getRectDiff(minuend, subtrahend, expected);
expect(diff).to.deep.equal(expected);
})
推荐答案
像 @NoriSte 所述, cy
命令是异步的,因此您不能将它们与同步代码混合使用。
Like @NoriSte said, the cy
commands are asynchronous thus you can't mix them with sync code.
您想做的事情是这样的:
What you want to do is something like:
function getViewport() {
return cy.document().then( doc => {
rect = /* do something synchronous */
return rect;
});
}
无论如何,回答原始问题(在标题中),我使用了两种模式来存储值以供以后在赛普拉斯中使用:
Anyway, to answer the original question (in the title), there's a couple of patterns I use to store a value for later use in cypress:
-
在
then
回调中包装下一个命令:
wrap next commands in the
then
callback:
cy.document().then( doc => {
return doc.documentElement.getBoundingClientRect();
}).then( viewportRect => {
cy.doSomething(viewportRect);
cy.doSomethingElse();
});
缓存到变量并从排队的命令内部访问缓存的值:
cache to a variable and access the cached value from inside an enqueued command:
let viewportRect;
cy.document().then( doc => {
return doc.documentElement.getBoundingClientRect();
}).then( rect => viewportRect = rect );
cy.doSomething();
// this is important -- you need to access the `viewportRect`
// asynchronously, else it will be undefined at the time of access
// because it's itself assigned asynchronously in the first command'd callback
cy.then(() => {
doSomething(viewportRect);
});
在您的问题中提出实际问题(如果我正确理解的话),我已经制定了一个解决方案,您可以从中学习:
Ad the actual problem in your question (if I understood it correctly), I've made a solution you can learn from:
const getRect = (selector) => {
if (selector == 'viewport') {
return cy.document().then( doc => {
return doc.documentElement.getBoundingClientRect();
});
} else if ( typeof selector === 'string' ) {
return cy.get(selector).then( $elem => {
return $elem[0].getBoundingClientRect();
});
// assume DOM elem
} else {
return cy.wrap(selector).then( elem => {
return Cypress.$(elem)[0].getBoundingClientRect();
});
}
};
const isInside = (containerRect, childRect) => {
if ( !containerRect || !childRect ) return false;
return (
childRect.top >= containerRect.top &&
childRect.bottom <= containerRect.bottom &&
childRect.left >= containerRect.left &&
childRect.right <= containerRect.right
);
};
Cypress.Commands.add('isInside', { prevSubject: true }, (child, container, expected) => {
return getRect(child).then( childRect => {
getRect(container).then( containerRect => {
expect(isInside(containerRect, childRect)).to.equal(expected);
});
});
});
describe('test', () => {
it('test', () => {
cy.document().then( doc => {
doc.body.innerHTML = `
<div class="one"></div>
<div class="two"></div>
<style>
.one, .two {
position: absolute;
}
.one {
background: rgba(255,0,0,0.3);
width: 400px;
height: 400px;
}
.two {
background: rgba(0,0,255,0.3);
width: 200px;
height: 200px;
}
</style>
`;
});
cy.get('.two').isInside('.one', true);
cy.get('.one').isInside('.two', false);
});
it('test2', () => {
cy.document().then( doc => {
doc.body.innerHTML = `
<div class="one"></div>
<div class="two"></div>
<style>
body, html { margin: 0; padding: 0 }
.one, .two {
position: absolute;
}
.one {
background: rgba(255,0,0,0.3);
width: 400px;
height: 400px;
}
.two {
background: rgba(0,0,255,0.3);
width: 200px;
height: 200px;
left: 300px;
}
</style>
`;
});
cy.get('.two').isInside('.one', false);
cy.get('.one').isInside('.two', false);
});
it('test3', () => {
cy.document().then( doc => {
doc.body.innerHTML = `
<div class="one"></div>
<style>
body, html { margin: 0; padding: 0 }
.one {
position: absolute;
background: rgba(255,0,0,0.3);
width: 400px;
height: 400px;
left: -100px;
}
</style>
`;
});
cy.get('.one').isInside('viewport', false);
});
});
这篇关于如何在赛普拉斯中返回文档尺寸以供以后测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!