I have a website that continuously makes AJAX requests (about 1 per second).
I would like seleniumwire to simply keep the browser open and catch all these requests, without having to refresh the page, but I couldn't find a way to do it, i.e.
for request in driver.requests:
...
will return the requests made while loading the page, but not all subsequent requests, even if I try to use:
chrome_options.add_experimental_option("detach", True)
Is there a way to keep seleniumwire catching AJAX requests continuously on a loaded web page?
Just found the solution myself: I need to use an interceptor:
def interceptor(request, response):
print(
request.url,
response.status_code,
response.headers['Content-Type']
)
driver.response_interceptor = interceptor
Then I can simply do time.sleep(1000000) after driver.get(...) and wait for responses to arrive.
Related
So what I want to do might be impossible and actually may not even be recommended, but im curious of the best way to handle this.
Currently one of my applications attempts to use an external service (Specifically google maps API). Sometimes I get a bad response from googles API (or it times out). It's rare (less than 1/30 times maybe) but it still happens and introduces flakiness into the automation tests.
I thought about stubbing this out everytime, but that would also sort of I feel like "lower" the test value (Since google maps api is important in this case)
I was curious if Cypress is able to do something that would TRY to get a response (with a successful status code) and if it failed maybe leave a log note but allow the test to continue on (either via stubbing or just continuing on).
This may even be a bad idea as we don't really "know" from just looking at the results but I wanted to at least pose the question.
Thanks!
You could achieve this by only conditionally sending mocked data, based on the response to that API call.
cy.intercept('/foo', (req) => { // replace with the URL for the google API
req.continue((res) => { // pass through the request to the real API
if (res.statusCode !== 200) { // or whatever "success" statusCode/criteria is
cy.log('my information I want to log')
res.send(200, myMockedBody) // send the mocked response.
}
res.send(); // otherwise, just send the response from the API
});
});
In our angular application, we are implementing a timmer function and calling the one API until a particular value (balance amount) changes in API call with 10 seconds interval with the limit of 5 times.
After we implement the timer function. We absolved that instead of making API call every time. API call taking the value from the disk catch some times.
Can anyone suggest me what is the solution to make API call not take get the information form desk catch?
enter image description here
There are 2 things you can do. At server-side from API, pass no-cache header from HTTP response
Cache-Control: no-cache
OR you can also add timestamp to your API call URL. So that browser doesn't cache it. Something like this :
var url = "http://api.mydomain.com/some-end-point?v=" + (new Date()).getTime();
I have implemented interceptor in my application which shows spinner on any http request and hide after getting the response. Also i have implemented counter for multiple http calls so that spinner goes off after last call.
But now in some cases , suppose i have three http async calls and i get the response of first call before my second call reach interceptor . This causing flickering of spinner on screen as it goes ON and OFF due to this scenarios.
Based on my understanding of the question, your code is working "as expected". The flickering is not caused by a bug in your implementation, but instead by a "limit case": two successive $http calls, resulting in your loader screen to go off for a split second after the first request completes just to be reactivated soon after when the second request is made. When the two request are close enough this gives the flickering effect: your end user does not know that two sequential requests are made, he just sees a loading screen going off only to come up again soon after.
In this case, counting the open request cannot mitigate your problem: when the first promise is completed, the second one hasn't been made yet: the counter is still "one open request", so after the promise completes your logic detects that now there are 0 open requests and stops the loading screen.
For those reasons, the only viable solution I can imagine is to implement a sort of "switch off delay" on the loading screen. By making the "loading screen switch off" not immediate, you give your app the time to start the second request. In order to achieve this, you have two options.
The first and probably the cleaner one is to implement the "delay" in the component handling the spinner. Modify the .hideSpinner() method to hide the spinner after a certain time delay has passed, and modify the .displaySpinner() method so that it cancels out any pending "hideSpinner" call. Notice that this may not be viable if you are using a spinner component that you didn't implement and therefore cannot modify easily.
The second approach is to work on the interceptor side. You should already have an "end request" method that checks if the request counter has returned to 0 and in that case stops the loading screen
Your code should look similar to (notice, this uses Typescript):
private startRequest(): void {
// If this is the first request,start the spinner
if (this.requestCount == 0) {
this.loadingOverlayService.start();
}
this.requestCount++;
}
private endRequest(): void {
// No request ongoing, so make sure we don’t go to negative count.
// Should never happen, but it is better to be safe than sorry.
if (this.requestCount == 0)
return;
this.requestCount--;
// If it was the last request, call the service to stop the spinner.
if (this.requestCount == 0) {
this.loadingOverlayService.stop();
}
}
Just add a setTimeout delay on the endRequest method. This way, the actual "is this the last request" check will be delayed, giving your app the time to start a new request before the spinner gets closed. Notice that this introduce a new problem: now any loading spinner will last 1Δ more than required, where Δ is the timeout you are using. In most of the real world cases this isn't actually a problem, you don't want your loading spinner to be "too fast" anyway in order to avoid a similar flickering problem with very short requests.
Your code should then be as follow:
private endRequest(): void {
setTimeout(function() {
if (this.requestCount == 0)
return;
this.requestCount--;
if (this.requestCount == 0) {
this.loadingOverlayService.stop();
}
}, 1000);
}
As already stated, now the check will run a second after the request has ended. This will give your second request the time to be started and increment the counter before the handler can check if there are still other pending request to await. As a result, your loading screen should'b be rapidly closed and reopened but instead just stay open, hence removing the appearance of flickering.
PS: There is a third option that I haven't discussed because your post gave me the impression it won't be applicable to your situation, so I will just post it here in this foot notice as an hint for future readers.
IF all your requests are predetermined, meaning they can be started at the same time (no request must await for the results of the preceding one) you may be able to chain them in a cumulative promise by using $q.all(). This may avoid the flickering effect, but further tests would be required to be sure this solution fits your need. In the end, the setTimeout option is probably the most convenient one, with the best effort/cost/quality compromise.
We have a page with multiple requests to the backend REST with big delay and much calculation time on the server side, that makes a user to wait for a long time until all queries respond, then run other requests no matter whether new queries are fired by the actions on the page itself.
If it does not matter whether that page or state changes it, then I would like to cancel the pending requests.
I can cancel each pending request by using $cancelRequest() function from ngResource#1.6.6.
Answer
How to implement automatic resourceInstance.$cancelRequest() on $rootScope.$on('$stateChangeStart')
Used
place $resourceProvider.defaults.cancellable = true; in
app.config($resourceProvider)
Service/Factory to return an instance of $resource
ngResource#1.6.6
angular#1.6.6
In my use case I have Carts and LineItems. My REST service has the following resource urls:
get|post|delete|put api/v1/carts/:cartId
get|post|delete|put api/v1/carts/:cartId/lineItems/:lineItemId
get|post|delete|put api/v1/lineItems/:lineItemId
the probelm is that when I do:
delete api/v1/carts/Default/lineItem/:lineItemId
and then I do:
get api/v1/carts/Default
angular does not hit the server to get the cart, but it gets it from cache which returns the deleted line item back in the cart
I tried all sorts of trick, tried disabling the cache by adding the {cache: false} option, but could not get it to work
the only way I was able to get it to work was if I make a POST request to
api/v1/carts/Default
with an empty body, which tells angular that the resource has changed and clears the cache.
Even though it works it seams like a hacky solution, so I was wandering if someone might have a suggestion of what I am doing wrong.
Get requests are cached by browsers. Simplest way is to use timestamp:
instead of GET /user/100 use GET /user/100?time=120229393
With such request you will always hit server.
If you need this in multiple requests, you can make http interceptor to add timestamp param to request.