【问题标题】:Cypress route function not detecting the network request赛普拉斯路由功能未检测到网络请求
【发布时间】:2019-05-29 01:36:24
【问题描述】:

我正在尝试等待我的应用程序发出的请求,但赛普拉斯没有在 cy.wait 上检测到它

    cy.server();
    cy.getAuthenticatedUrl();
    cy.route('POST', '/showroom/validate').as('uploadShowroom');

    cy.get('[data-testid=Next]').click();

    cy.uploadFile('[id=uploadArea]', 'testfile-valid.xlsx', 'application/vnd.ms-excel');

    cy.wait('@uploadShowroom');

    cy.contains('FILE UPLOAD DONE');

如果我在测试期间检查我的控制台,我可以看到请求是针对我的服务器发出的

我的客户端和我的服务器都在本地运行,但在不同的端口。

错误如下: CypressError: Timed out retrying: cy.wait() timed out waiting 5000ms for the 1st request to the route: 'uploadShowroom'. No request ever occurred.

【问题讨论】:

  • 在 cypress 命令日志中显示的路由是否相同?并且在抛出超时错误之前就显示出来了吗?
  • @Brendan 是的,第二张截图来自 cypress 日志(在超时前几秒钟记录)
  • 这看起来不像命令日志。我说的是测试运行器中的命令日志:docs.cypress.io/guides/core-concepts/test-runner.html。我猜这个请求不是 Richard Matsen 在他的回答中提到的 XHR。如果是 XHR,它将显示在命令日志中,如果不是,则不会。

标签: javascript reactjs e2e-testing cypress


【解决方案1】:

我认为这是因为您的表单使用本机表单提交,但赛普拉斯的 cy.route() 仅响应 XHR 调用(目前)。

issue #170有大讨论。

Gleb Bahmutov 在 comment 中有一个有趣的想法,在 repository 中编写代码。本质上,他使用 XHR 提交“模拟”本地提交,即时。

我尝试了一种更接近您的场景的变体。按照存储库 READ.ME 设置测试,但首先在 package.json 中更新 Cypress 版本。将要上传的文件添加到/cypress/fixtures

然后尝试以下规范。

第三个测试是使用cy.url() 而不是cy.route() 的替代方法。

uploadFile 命令(或类似变体)

Cypress.Commands.add('uploadFile', (fileName, selector) =>
  cy.get(selector).then(subject => {
    return cy
      .fixture(fileName, 'base64')
      .then(Cypress.Blob.base64StringToBlob)
      .then(blob => {
        const el = subject[0];
        const testFile = new File([blob], fileName, {
          type: 'application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet',
        });
        const dataTransfer = new DataTransfer();
        dataTransfer.items.add(testFile);
        el.files = dataTransfer.files;
        return subject;
      });
  })
);

使用 XHR“模拟”本机提交的功能(位于规范顶部)

const mockNativeSubmitWithXhr = (form$) => {
  let win
  cy.window().then(w => {
    win = w
  })
  form$.on('submit', e => {
    e.preventDefault()
    const form = new FormData(e.target)
    const XHR = new win.XMLHttpRequest()
    XHR.onload = response => {
      win.document.write(XHR.responseText)
      win.history.pushState({}, '', XHR.url)
    }
    XHR.open(e.target.method, e.target.action)
    XHR.send(form)
    return true
  })
}

规格

describe('waiting for form-data post', () => {

  beforeEach(() => {
    cy.task('deleteFile', '../../uploads/Sample_data.xlsx')
    cy.visit('localhost:3000')
    cy.get('input[name="userid"]').type('foo@bar.com')
  })

  it('upload with native form submit (fails because of native event)', () => {
    cy.server()
    cy.route('POST', '/upload').as('upload');

    cy.uploadFile('Sample_data.xlsx', '[id=fileToUpload]')
    cy.get('input[type="submit"]').click()

    cy.wait('@upload');
    cy.readFile('uploads/Sample_data.xlsx') // check saved file
  })

  it('upload with form submit mocked to XHR send (succeeds)', () => {
    cy.server()
    cy.route('POST', '/upload').as('upload');

    cy.uploadFile('Sample_data.xlsx', '[id=fileToUpload]')
    cy.get('form').then(form => mockNativeSubmitWithXhr(form))
    cy.get('input[type="submit"]').click()

    cy.wait('@upload');
    cy.readFile('uploads/Sample_data.xlsx')
  })

  it('upload with native form submit (testing url has changed)', () => {
    cy.uploadFile('Sample_data.xlsx', '[id=fileToUpload]')
    cy.get('input[type="submit"]').click()

    cy.url().should('eq', 'http://localhost:3000/upload')
    cy.readFile('uploads/Sample_data.xlsx')
  })
})

在测试之间删除上传文件的任务(修改“/cypress/plugins/index.js”)

const fs = require('fs')

module.exports = (on, config) => {
  on('task', {
    deleteFile: (path) => {
      if (fs.existsSync(path)) {
        fs.unlinkSync(path)
      }
      return null
    }
  })
}

【讨论】:

  • 注释“使用 cy.url() 而不是 cy.route()”令人困惑。 cy.route 用于存根或别名网络调用,而不是断言 url
  • @MichaelFreidgeim - 如果您查看前两个测试,它们使用别名等待(在路线上)。作为替代方案,第三个测试使用 Cypress 重试机制(通过.should())等待 url 更改。
【解决方案2】:

我跑了类似的东西。诀窍不是根据字符串检查路由,而是根据正则表达式检查路由。试试这个来匹配你的 POST 路由:

cy.route('POST', /showroom\/validate/).as('uploadShowroom');
// [...]
cy.wait('@uploadShowroom');

如果您可以在 cypress 命令日志中看到该路由匹配(路由旁边的黄色徽章),它应该可以,您想要什么。

【讨论】:

    【解决方案3】:

    尝试覆盖默认的等待超时:

    cy.wait('@uploadShowroom', {timeout: 10000);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-26
      • 2021-11-11
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多