I'm testing an app with Cypress, and the tests go against real HTTP servers. I'm not stubbing the HTTP requests.
Is there a way to make my tests fail if any of the HTTP requests fail?
There is a solution that seems ok in this other SO post, but I wonder if there is a more proper solution. In my case, I'm not always converting all HTTP errors into invocations to console.error.
You can listen to the request using cy.intercept() & check the status code etc.
Ref : https://docs.cypress.io/api/commands/intercept.html#Intercepting-a-response
Example 1 :
// Wait for intercepted HTTP request
cy.intercept('POST', '/users').as('createUser')
// ...
cy.wait('#createUser')
.then(({ request, response }) => {
expect(response.statusCode).to.eq(200)
})
Example 2 :
// Listen to GET to comments/1
cy.intercept('GET', '**/comments/*').as('getComment')
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click()
// https://on.cypress.io/wait
cy.wait('#getComment').its('response.statusCode').should('be.oneOf', [200, 304])
Related
On clicking a checkbox, a GET request will get triggered in my application.
I am trying to validate this with cypress but it throws 'Timed out retrying after 30000ms: cy.wait() timed out waiting 30000ms for the 1st request to the route: getGridWind10M. No request ever occurred.'
My code:
cy.intercept("GET", "v1/kml/F20210903120000/Wind10M?view=grid*").as('getGridWind10M');
cy.get('[data-test="ckbx-w10m"]')
.check({ force: true })
.should("be.checked");
cy.wait('#getGridWind10M').its('response.statusCode').should('eq', 200)
Actual Endpoint:
https://domain/path/api/v1/kml/F20210903120000/Wind50M?view=grid&time=2021-09-03T14:00:00.000Z&z=3&x=5&y=4
Test Log:
I have tried the following with no luck. Someone please help me to find out where and what am I missing here as the request in successfully completed as shown in the image?
cy.intercept("GET", "*/F20210903120000/Wind10M?view=grid*").as('getGridWind10M');
cy.intercept("GET", "*F20210903120000/Wind10M?view=grid&*").as('getGridWind10M');
cy.intercept("GET", "*F20210903120000/Wind10M?view=grid*").as('getGridWind10M');
cy.intercept("GET", "/F20210903120000/Wind10M?view=grid*").as('getGridWind10M');
You can catch it with a leading ** meaning multiple preceding parts, and a trailing ?* meaning has some search params.
const url = "**/v1/kml/F20210903120000/Wind10M?*"
cy.intercept('GET',url, {}).as('getGridWind10M') // stubbing here
cy.get('checkbox').check()
cy.wait('#getGridWind10M')
I note there is a difference in the actual endpoint Wind50M and the intercepted endpoint Wind10M, probably a typo?
This also works if you are wilcarding middle path segments
const url = "**/v1/kml/*/Wind10M?*"
I'm facing an issue while working with Cypress test on a Drupal 8 based website, I'm getting a 500 server error when one of the button is clicked which invokes AJAX command, it works perfectly fine when I'm browsing the same page locally but Cypress is immediately throwing a 500 Server Error.
As described here by #NoriSte, I've tried the following code using https://www.npmjs.com/package/cypress-wait-until cy.waitUntil & updated the selectors, etc., the code is attempting/clicking the button multiple times but in all the request the AJAX is getting 500.
// This will be set to true when the XHR request starts.
let requestStarted = false
cy.server()
cy.route({
method: 'POST',
url: '/the-ajax-url?*',
onRequest: () => (requestStarted = true)
}).as('sendCommand');
cy.get('.the-button-selector').as('button')
cy.waitUntil(() => cy.get('#button')
.should('be.visible')
.click({force: true})
.then(() => requestStarted === true), {
timeout: 20000,
interval: 1000,
errorMsg: 'POST not sent `enter code here` within time limit'
})
cy.wait('#sendCommand')
What I'm trying to achieve is to allow this AJAX request some time, so instead of quickly throwing 500 error, it loads up & works as expected.
Note: This AJAX request response in actual is approx ~1.5 MB, not sure if somehow this could be helpful.
Two things seem to be indicated by the log
the route is not capturing the url (because the error message says so)
suggest testing with Cypress.minimatch, perhaps simplify to url: '/the-ajax-url'
the route should specify status: 201, otherwise once the url matches it seems likely to capture the 500 status and set requestStarted true, which is not what you want.
cy.waitUntil() is not waiting because requestStarted === true cannot be true, since the route didn't capture.
check out this as an alternative way to retry cypress xhr request retry ontimeout. cy.waitUntil() uses recursion under the hood, but it's not entirely clear how to the until part works. Going to a simpler recursive function will give you more clarity.
I'm using Spring Boot to create an API that needs to be consumed in Angular 4. Spring and Angular are on different ports.
The problem is that Spring's ResponseEntity raises an error in Angular.
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseEntity getFlow(#PathVariable int id) {
Flow flow = flowService.findById(id);
return new ResponseEntity(flow, HttpStatus.FOUND);
}
Now, I can perfectly use Postman to test the API and it works.
But when I make a request from Angular, it returns an error:
Strangely, it returns an error alongside the requested object.
Now, the cause of the problem is that the Spring Boot application returns a ResponseEntity and not a normal object (like String), and Angular doesn't know how to interpret it. If the controller returns just a Flow object, it works.
How can it be solved using ResponseEntity? Or, how else can I send the object alongside the HTTP status code?
Also, in #RequestMapping put produces = "application/json", and in get request in angular, add http options :
const httpOptions = {
headers: new HttpHeaders({
'Accept': 'application/json',
'Content-Type': 'application/json'
})
};
So your get request looks like this:
this.http.get(url, httpOptions)
As per the document mentioned here
https://docs.angularjs.org/api/ng/service/$http
A response status code between 200 and 299 is considered a success status and will result in the success callback being called. Any response status code outside of that range is considered an error status and will result in the error callback being called. Also, status codes less than -1 are normalized to zero. -1 usually means the request was aborted, e.g. using a config.timeout. Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning that the outcome (success or error) will be determined by the final response status code.
As you are sending an instance of ResponseEntity(HttpStatus.Found) whose Http status code is 302 which doesnt fall under the success range thats why error callback is called.
Try returning the content like this
return new ResponseEntity(flow, HttpStatus.OK);
I have a code that looks something like this:
class SomeController {
HttpClient client = new HttpClient();
public Task<dynamic> SomeAction() {
Task.Run<dynamic>(() => {
var response = client.GetAsync(new Uri(someUrl));
return response.ReadAsAsync<dynamic>().Result;
});
}
}
Now, I call this api with many requests (around 300) and the 'someUrl' returns the response after about 200ms.
After adding some console logs I can see a behavior:
All the 200 requests arrive and request the someUrl resource
The first 2-3 requests to someUrl are handled and returned properly
Other responses are waiting for all the 300 requests to arrive and only then they are returned back...
I have heard that there is no prioritization of responses over incoming requests in situations like these but it seems weird to me. It seems like the requests coming to my server and the responses that are coming from the someUrl are on the same queue and until all the requests are sent no response can be handled.
Anyone else encountered this situation? Anyone knows how to handle it properly?
Thanks!
I'm using the following lua script to forward all server responses that are served from Node. My error handling for a /signup route works as follows:
if authenticationResult.status ~= 201 then
...
ngx.status = authenticationResult.status
ngx.say(authenticationResult.body)
ngx.exit(401)
return
end
From the client I send a typical signup request like so, using the superagent-promise library:
request
.post(url)
.type('form')
.send(data)
.end()
.then((response) => {
console.log('the response', response)
})
.catch((error) => {
console.log('the error', error)
})
When I send a valid post request from the client, the response variable in the .then successfully contains the response body.
However, when I sent an improper post request with invalid credentials, neither the .then nor the .catch executes. Instead, the Chrome console immediately displays POST http://api.dockerhost/signup 401 (Unauthorized).
I would like to know what I can do differently to successfully access the server's error response and its contents, outside of just its status code.
Per the manual, you need to use ngx.HTTP_OK as the return if you want nginx to return content as part of the page. Otherwise it will simply return a 401.
ngx.status = authenticationResult.status
ngx.say(authenticationResult.body)
ngx.exit(ngx.HTTP_OK)
return