有没有办法断言赛普拉斯没有调用路由?

时间:2017-11-17 15:45:28

标签: javascript chai cypress

我试图断言赛普拉斯没有调用过一条路线。我仔细查看了文档并找不到任何内容。

我正在尝试做这样的事情:

cy.get('@myRouteAlias').should('have.not.been.called');

我目前正在解决这个问题,声称成功的请求toast消息没有显示,但它是一个脆弱的解决方案。

有什么想法吗?

13 个答案:

答案 0 :(得分:11)

不幸的是,以上方法都不适合我,我可以使用以下命令来实现它:

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);

答案 1 :(得分:8)

很难测试某个操作的情况。有了这种断言,你真的只能说:

“XHR请求未在赛普拉斯寻找此XHR请求的400ms范围内(或您设置超时的任何内容)”

确实确认XHR请求从未被调用。

话虽如此,赛普拉斯提供了一种方法来检索使用未记录的cy.state('requests')发出的所有XHR请求。您可以检查其长度,通过别名等过滤它们,以确定您想要的内容。

答案 2 :(得分:5)

作为路由选项onResponse功能的变体集,该功能将放弃测试

例如expect(true).to.be.false;

如果当前路线发生呼叫,则会触发错误

cy.route({
    url: <url>,
    onResponse: function () {
       expect("Unexpected Https call").to.be.false;
    }
})

答案 3 :(得分:2)

这是使用赛普拉斯的命令声明请求计数的正确方法。

将其放入您的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);
});

答案 4 :(得分:2)

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);

答案 5 :(得分:0)

为简化@Jennifer Shehane的好答案:

let requestsCount = (alias) => cy.state('requests').filter(a => a.alias === alias).length;

expect(requestsCount('putRequest')).to.eq(0);

您也可以将其放入赛普拉斯命令文件中!

答案 6 :(得分:0)

值得考虑此测试的异步特性,而前面的示例并未考虑到这一点。这是一个工作示例:

cy.route('/my-route').as('myRoute')

const noExpectedCalls = 1

cy.get('@myRoute').then(() => {
  expect(cy.state('requests').filter(r = r.alias === 'myRoute').length).to.eq(noExpectedCalls)
})

答案 7 :(得分:0)

这是柏树小组的工作方式(source):

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");
});

并从相关的docs

在测试失败时触发。通过绑定到此事件并调用异步完成的回调,可以从技术上防止测试实际失败。但是,强烈建议不要这样做。测试永远不会合法失败。发生此事件是因为它对于调试非常有用

答案 8 :(得分:0)

select u.username,count(*) as total_booking, count(case when status='Active' then 1 end) as active_bookings from users u join bookings b on u.username=b.username group by u.username 似乎为0时未定义。

此外,如果您想使用cy.state调用该命令,那么它将起作用。

@
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);
});

答案 9 :(得分:0)

我想我找到了一种符合我预期的方法,即使用 cy.interceptcy.state

  1. 添加要通过 cy.intercept 进行嗅探的路由
  2. 等待一段时间,您可以选择自己信任的东西
  3. 然后查看您的网址是否在 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 方法。

答案 10 :(得分:0)

当我们有路线时:

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: []
...}

然后 Cypress 抛出一个错误:

AssertionError
expected { Object (id, routeId, ...) } to equal null

答案 11 :(得分:0)

这些在 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

答案 12 :(得分:-1)

我尝试了乔纳森(Jonathan)发布的简化版本,但看到TypeError:无法读取未定义的属性'filter',而cy.state('requests')始终未定义。