Reputation: 879
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.
Upvotes: 5
Views: 6291
Reputation: 1032
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 command log (yellow badge beside the route), it should do, what you want.
Upvotes: 1
Reputation: 23533
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 comment, 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 command (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
}
})
}
Upvotes: 4
Reputation: 17899
Try to override default timeout of wait:
cy.wait('@uploadShowroom', {timeout: 10000);
Upvotes: -3