我试图断言赛普拉斯中没有调用路由。我彻底查看了文档,但一无所获。
我正在尝试做这样的事情:
cy.get('@myRouteAlias').should('have.not.been.called');
我目前正在通过断言未显示成功的请求 toast 消息来解决此问题,但这是一个脆弱的解决方案。
有任何想法吗?
我试图断言赛普拉斯中没有调用路由。我彻底查看了文档,但一无所获。
我正在尝试做这样的事情:
cy.get('@myRouteAlias').should('have.not.been.called');
我目前正在通过断言未显示成功的请求 toast 消息来解决此问题,但这是一个脆弱的解决方案。
有任何想法吗?
测试没有发生动作的情况是非常困难的。使用这种类型的断言,你真的只能说:
“XHR 请求不是在400ms
赛普拉斯寻找这个 XHR 请求的范围内发出的(或者你设置的超时时间)”
这并不能真正确认从未调用过 XHR 请求。
话虽如此,赛普拉斯提供了一种方法来检索使用未记录的cy.state('requests')
. 您可以检查它的长度,按别名过滤它们等,以确定您想要什么。
不幸的是,以上都没有真正为我工作,我用这个命令得到了它:
Cypress.Commands.add('shouldBeCalled', (alias, timesCalled) => {
expect(
cy.state('requests').filter(call => call.alias === alias),
`${alias} should have been called ${timesCalled} times`
).to.have.length(timesCalled);
});
然后我像这样使用它:
// Checks that FetchChatList has not been called
cy.shouldBeCalled('FetchChatList', 0);
作为路由选项onResponse
功能中设置的变体,它会丢弃测试
例如expect(true).to.be.false;
如果当前路由发生呼叫,它将触发错误
cy.route({
url: <url>,
onResponse: function () {
expect("Unexpected Https call").to.be.false;
}
})
这是使用 cypress 的命令断言请求计数的正确方法。
把它放在你的commands.js
文件中:
Cypress.Commands.add('requestsCount', (alias) =>
cy
.wrap()
.then(() => cy.state('requests').filter(req => req.alias === alias).length),
);
比在您的测试中使用如下新命令:
it('should count requests', () => {
cy.server();
cy.route('**').alias('theRequest');
cy.wait('@theRequest');
cy.requestsCount('theRequest').should('eq', 1);
});
值得考虑此测试的异步性质,前面的示例没有考虑到这一点。这是一个工作示例:
cy.route('/my-route').as('myRoute')
const noExpectedCalls = 1
cy.get('@myRoute').then(() => {
expect(cy.state('requests').filter(r => r.alias === 'myRoute')).to.have.length(noExpectedCalls)
})
为了简化@Jennifer Shehane 的好答案:
let requestsCount = (alias) => cy.state('requests').filter(a => a.alias === alias).length;
expect(requestsCount('putRequest')).to.eq(0);
你也可以把它放在你的赛普拉斯命令文件中!
这就是柏树团队的做法(来源):
it("throws when alias is never requested", (done) => {
Cypress.config("requestTimeout", 100);
cy.on("fail", (err) => {
expect(err.message).to.include(
"`cy.wait()` timed out waiting `100ms` for the 1st request to the route: `foo`. No request ever occurred."
);
done();
});
cy.server().route(/foo/, {}).as("foo").wait("@foo.request");
});
并来自相关文档:
测试失败时触发。从技术上讲,通过绑定到此事件并调用异步完成回调来防止测试实际失败是可能的。但是,强烈建议不要这样做。测试不应该合法地失败。存在此事件是因为它对调试非常有用
我尝试了 Jonathan 发布的简化版本,但看到 TypeError: Cannot read property 'filter' of undefined and cy.state('requests') is always undefined。
在 7.6 版中,这些都不适合我,但我找到了一个非常简单的解决方案。
鉴于您有这样的拦截:
cy.intercept('GET', '**/foo/bar**').as('myRequest');
现在你可以这样做:
cy.wait(2000);
cy.get('@myRequest.all').then((interceptions) => {
expect(interceptions).to.have.length(0);
});
因此,当请求可能发生时,您等待一段时间,并确保在等待之后它没有发生。对我来说工作得很好,不需要额外的命令。我在这里找到了解决方案:https ://www.gitmemory.com/issue/cypress-io/cypress/15036/780706160
cy.state
0 时似乎未定义。
此外,如果您想使用 调用命令@
,那么这将起作用。
Cypress.Commands.add('shouldBeCalled', (alias, timesCalled) => {
const aliasname = alias.substring(1);
const requests = cy.state('requests') || [];
expect(
requests.filter((call) => call.alias === aliasname),
`${aliasname} should have been called ${timesCalled} times`
).to.have.length(timesCalled);
});
cy.shouldBeCalled('@updateCalc', 1);
弃用cy.intercept()
后更新。cy.route()
如果您使用cy.intercept()
,cy.state('requests')
将返回未定义的对象alias
,所以我xhr.url
改用了。
我像这样调整了@SleepWalker 的解决方案:
commands.js 文件中的命令:
Cypress.Commands.add('requestsCountByUrl', url =>
cy.wrap().then(() => {
const requests = cy.state('requests') || [];
return requests.filter(req => req.xhr.url === url).length;
})
);
测试中的用法:
cy.requestsCountByUrl('http://theUrl.com').should('eq', 1);
我想我找到了一种按我预期的方式对我有用的方法,使用cy.intercept
and cy.state
.
cy.intercept
cy.state('routes')
.it(`should NOT make foo request`, () => {
// listen for any request with "foo" using cy.intercept
// I like to return success just to not see warnings in the console...
cy.intercept(/.foo./, { success: true }).as("fooRequest");
cy.window().then(win => {
// do what ever logic could make the request
makeFooRequestOrSomething();
});
// use cy.wait to wiat whatever amount of time you trust that your logoc should have run
cy.wait(1000);
/*
* cy.intercept does not provide any information unless a request is made, so instead
* we can use the state and make sure our route is not in the list
*/
let routes = cy.state('routes'); // An object representing all the routes setup via cy.intercept
let fooRoutes = [];
for (let route in routes) {
// routes[route].requests is an object representing each request
for (let req in routes[route].requests) {
let reqUrl = routes[route].requests[req].request.url;
// test each URL for "foo" and if it has it, add the URL to the array
if((/foo/).test(reqUrl)) {
fooRoutes.push(reqUrl);
}
}
};
// if no request was made to our URL, our array should be empty
expect(fooRoutes).to.have.property("length", 0);
});
routes[route]
alias
如果您想以不同的方式过滤数据然后查看是否routes[route].requests
为空,可能有您可以使用的地方。cy.state
方法。当我们有路线时:
cy.intercept('PUT', '**/shoes/*', body).as('updateShoes');
以下解决方案对我有用:
cy.get('@updateShoes').then((interception) => {
assert.isNull(interception)
});
赛普拉斯说:预期 null 等于 null
当调用“@updateShoes”路由时,(拦截)是一个对象:
{id: "interceptedRequest551", routeId: "1623772693273-2831", request: {…}, state: "Complete", requestWaited: false, …}
id: "interceptedRequest551"
log: {get: ƒ, unset: ƒ, invoke: ƒ, toJSON: ƒ, set: ƒ, …}
request: {headers: {…}, url: "http://localhost:8080/api/shoes/38de4e08", method: "PUT", httpVersion: "1.1", body: {…}}
requestWaited: false
response: {headers: {…}, body: {…}, url: "http://localhost:8080/api/shoes/38de4e08", method: null, httpVersion: null, …}
responseWaited: false
routeId: "1623772693273-2831"
state: "Complete"
subscriptions: []
...}
赛普拉斯抛出一个错误:
AssertionError
expected { Object (id, routeId, ...) } to equal null