最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Cypress route function not detecting the network request - Stack Overflow

programmeradmin3浏览0评论

I'm trying to wait for a request made by my application but Cypress is not detecting it on 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');

If I check my console during the tests, I can see that the request was made to my server

Both my client and my server are running local but in different ports.

The error is the following: CypressError: Timed out retrying: cy.wait() timed out waiting 5000ms for the 1st request to the route: 'uploadShowroom'. No request ever occurred.

I'm trying to wait for a request made by my application but Cypress is not detecting it on 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');

If I check my console during the tests, I can see that the request was made to my server

Both my client and my server are running local but in different ports.

The error is the following: CypressError: Timed out retrying: cy.wait() timed out waiting 5000ms for the 1st request to the route: 'uploadShowroom'. No request ever occurred.

Share Improve this question asked Jan 2, 2019 at 11:45 Eduardo PedrosoEduardo Pedroso 8893 gold badges12 silver badges32 bronze badges 3
  • Does the route show up the same in the cypress mand log? And does it show up before the timeout error is thrown? – Brendan Commented Jan 3, 2019 at 18:11
  • @Brendan yes, the second screenshot is from the cypress log (logged a few seconds before the timeout) – Eduardo Pedroso Commented Jan 3, 2019 at 19:09
  • That doesn't look like the mand log. I'm talking about the mand log in the test runner: docs.cypress.io/guides/core-concepts/test-runner.html . I'm guessing the request isn't an XHR as Richard Matsen mentions in his answer. If it is an XHR it'll show up in the mand log, if it isn't, it won't. – Brendan Commented Jan 4, 2019 at 18:14
Add a ment  | 

3 Answers 3

Reset to default 4

I think this is because your form is using native form submit, but Cypress' cy.route() only responds to XHR calls (at the moment).

There is a big discussion in issue #170.

Gleb Bahmutov has an interesting idea in this ment, code in this repository. Essentially he 'mocks' the native submit with an XHR submit, on the fly.

I tried out a variation which gets closer to your scenario. Follow the repository READ.ME to set up the test, but first update the Cypress version in package.json. Add the file to be uploaded into /cypress/fixtures.

Then try the following spec.

The third test is an alternative which uses cy.url() instead of cy.route().

uploadFile mand (or similar variation)

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

Function to 'mock' the native submit with XHR (place at top of Spec)

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

Spec

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

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

  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')
  })
})

Task to remove uploaded file between tests (modify '/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
    }
  })
}

I ran in something similar. The trick was not to check the route against a string but against a regular expression. Try this to match your POST route:

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

If you can see the the route is matching in cypress mand log (yellow badge beside the route), it should do, what you want.

Try to override default timeout of wait:

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

发布评论

评论列表(0)

  1. 暂无评论