Cypress intercept - No request ever occurred - cypress

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?*"

Related

Making a test fail if an HTTP request fails in Cypress

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

500 Server Error in Cypress tests to one of the AJAX request

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.

Axios : put on hold requests

I have the following axios interceptor.
It checks the validity of the stored token. If not valid, a request is fired to retrieve and store the refreshed token.
axios.interceptors.request.use(async config =>
if(checkValidity(localStorage.getItem('token')) === false) {
const response = await axios.get('http://foobar.com/auth/refresh');
localStorage.setItem('token', response.headers['token']);
config = getConfigFromResponse(response);
}
return config;
});
It works great. The problem is that if I have many requests with invalid token then many requests to http://foobar.com/auth/refresh are done to refresh it.
Is it possible to put all the requests in an array and fire them after when the refresh is done ?
The idea is to avoid catching 401 errors and replaying the request : this is why I want to "save" the requests while the token is being retrieved and then fire them when the token is ready.

Cannot access error response body from client when using nginx + lua

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

Status of ajax or post request

status - contains the status of the request like
("success", "notmodified", "error", "timeout", or "parsererror") /ajax or post
I know what is success,not modified,error meant here but I am unable to find out how to handle this errors. If the call back is success then update my div, if there is any error not modified, error, time out, parse error then let me alert a pop up some error occurred.
What would be the cause for each type of error? I mean the situations where not modified,timeout,error and parseerror occurs.
If it results success, then does it mean my post request has successfully worked?
My local-server xampp never results any error, the status is always success. I guess, since its limited to my system but when I put my website online there exists several issues like traffic on server.
So how do I find out, whether my post request to some sample.php page was successfully sent and else pop out an alert to user if something went wrong?
The error types are a little self-explanatory. They simply provide a string for you to easily handle the different errors.
error callback option is invoked, if the request fails. It receives the jqXHR, a string indicating the error type, and an exception object if applicable. Some built-in errors will provide a string as the exception object: "abort", "timeout", "No Transport".
Source: jQuery.Ajax documentation
Codes Explained:
Error: Any of the HTTP response codes, like the well-know 404 (not found) or other internal server errors.
Notmodified: Compares the cached version of the browser with the server's version. If they are the same, the server responds with a 304
Timeout: Ajax requests are time-limited, so errors can be caught and handled to provide a better user experience. Request timeouts are usually either left at their default or set as a global default using $.ajaxSetup() rather than being overridden for specific requests with the timeout option.
Parse Error: The jQuery data (JSON) cannot be parsed (usually due to syntax errors)
Handling these error codes:
Here is some example of handling the errors
$(function() {
$.ajaxSetup({
error: function(jqXHR, exception) {
if (jqXHR.status === 0) {
alert('Not connect.\n Verify Network.');
} else if (jqXHR.status == 404) {
alert('Requested page not found. [404]');
} else if (jqXHR.status == 500) {
alert('Internal Server Error [500].');
} else if (exception === 'parsererror') {
alert('Requested JSON parse failed.');
} else if (exception === 'timeout') {
alert('Time out error.');
} else if (exception === 'abort') {
alert('Ajax request aborted.');
} else {
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}
});
});
Source: Blog Post - jQuery Error Handling
Success
Response code is between 200-299 or is 304 Not Modified.
Not Modified
Response code is 304. If you employ caching, the browser can tell the server which version it currently has, and the server compares this with its version and if there has been no change, it can send a 304 Not Modified response, to indicate to the client that their version is up to date. In jQuery ajax, a 304 Not Modified response will still fire the success handler.
Error
Response code is between 400-599. This could be for example 404 not found, 403 forbidden, 500 internal server error etc.
Parse Error
This is a jQuery internal, not actually a HTTP response. This will happen if jQuery is trying to parse JSON or XML that is not in the valid format or has syntax errors.
Timeout
Again, this isn't a HTTP response. The ajax request has a timeout which if is exceeded before the server responds, will abort the request.
If you control the server side, in your example a PHP script, and you never change the response code using header() then your ajax will always receive 200 OK responses unless there is an unhandled exception in the PHP which will trigger a 500 internal server error.
It is acceptable to always send 200 OK response codes. For example, if the server outputs a JSON object which contains its own success/error flag then any errors can be handled by looking at the flag.
As far as I know
not modified: Server sends a Not Modified(304) response status
timeout: the server has not responded within the time period specified by the timeout property
error: server response with a error status like 4xx or 5xx
parseerror: there was an client side error when processing server response like an invalid json format/xml format

Resources