'Can you throttle requests rather than responses in Cypress?
I am trying to end to end test a file upload page in Cypress, which includes testing if a file upload progress bar works.
Unfortunately, in the local environment the upload happens instantly so the progress bar is not shown.
I am aware that you can throttle the response speed using cy.intercept() to simulate slow networks. However, this isn't slowing the request upload speed:
cy.intercept('post', `/route`, (req) => {
req.on('response', (res) => {
res.setThrottle(1000)
})
}).as('post')
Is there any way that I can apply a throttle to the outgoing request?
Solution 1:[1]
I think Cypress itself can only throttle or delay responses using cy.intercept() as mentioned in the question and described here: Throttle or delay response all incoming responses
However, you can probably use the Chrome Debugger Protocol from Chrome DevTools for that. Here you have the function Network.emulateNetworkConditions that allows you to throttle both download and upload throughput. This approach then assumes that your tests run in Chrome.
If you're unsure how to use this in your Cypress tests, here is a blog post about testing an application in offline network mode that uses a similar approach with Network.enable: Testing an Application in Offline Network Mode
Solution 2:[2]
In the routeHandler, use setTimeout() to delay the call to req.continue().
To get the command queue to wait for setTimeout, return a Promise wrapper. See Request phase
If the handler returned a Promise, wait for the Promise to resolve.
If you want a delay longer than the default command timeout of 4 seconds, you will need to increase the config since cy.intercept does not take a timeout option.
Cypress.config('defaultCommandTimeout', 6000) // timeout in 6 seconds
cy.intercept('POST', '/route', (req) => {
return new Promise(resolve => {
setTimeout(() => resolve(req.continue()), 5000) // delay by 5 seconds
})
}).as('delayedRequest')
// trigger POST
cy.wait('@delayedRequest')
Cypress.config('defaultCommandTimeout', 4000) // revert to normal timeout
Middleware
If you already have a complex intercept, you can set the delay in a middleware intercept.
Middleware is always executed first, but if does not handle the request the call is passed to the next intercept.
// request is delayed here
cy.intercept('POST', '/route', {
middleware: true // middleware always fires first
},
(req) => new Promise(resolve =>
setTimeout(() => resolve(), 5000) // no handler, just delay
)
)
// then passed to here
cy.intercept('POST', '/route',
(req) => {
req.continue() // handler for request
}
).as('delayedRequest')
// trigger POST
cy.wait('@delayedRequest')
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
