Karma Jasmine AngularJS testing with real HTTP requests - angularjs

I want to test my code with real API calls (so I can test the API as well, and when I change the API I don't have to change the JS test as well, and a lot more benefits.) instead of the regular $httpBackend.expectPOST('http://api.com/login').response(200).
Essentially, I want to test a ProductsController that expects to be logged in through an AuthService.login() method and receive a list of products through ui-router's resolve feature.
In this case, the login method receives data that needs to be used to gather products.

From the $httpBackend documentation found here: https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend
As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application is being developed with the real backend api replaced with a mock, it is often desirable for certain category of requests to bypass the mock and issue a real http request (e.g. to fetch templates or static files from the webserver). To configure the backend with this behavior use the passThrough request handler of when instead of respond
So, something like: $httpBackend.whenGET(/.*/).passThrough(); should suffice.

Related

Experiences with Redux and Redux-Observable middleware for handling Asynchronous Http Requests

I am learning and trying redux in a typescript react environment. So far I have managed to get basic small web application implemented and am at the stage where I would like to refactor and improve the architecture.
I am using "typescript-actions" and custom factory methods to facilitate creating actions for Api request, success and failure payload types. I am using a wrapper around http library and have decided upon Axios due to its availability in both node and browser environments. This means no poly fills required when testing with tools such as jest.
I have decided upon "redux-observable" to handle API middleware.
I am currently trying to create a generic factory method that creates an epic(middleware handler) that handles an API Request. I am thinking along the lines of one generic factory method per request flow, e.g. providing a factory method to create an epic handler for:
DELETE, SUCCESS, FAIL FLOW
GET, SUCCESS, FAIL FLOW
POST, SUCCESS, FAIL FLOW
PUT, SUCCESS, FAIL FLOW
Currently, struggling to get this transpiling with Typescript as detailed here.
What are others doing in their production environments with respect to handling asynchronous API requests? For example:
Not using redux at all to process intermediary API request states. Instead react components make and handle the request. The response is handled directly or dispatched onto the store once completed.
Using a dedicated epic for each individual resource type API flow:
Epic1=FETCH_RESOURCE1, SUCCESS_RESOURCE1, FAIL_RESOURCE1
Epic2=FETCH_RESOURCE2, FETCH_SUCCESS_RESOURCE2, FETCH_FAIL_RESOURCE2
EpicN=PATCH_RESOURCEN, PATCH_SUCCESS_RESOURCEN, PATCH_FAIL_RESOURCEN
3.Using a generic factory method to create each individual middleware flow. Each factory method accepting reusable parameters and generics such as url, parameters, body data type etc.
Each epic handler for option 2 would likely include duplicate code with the exception that each implementation would include different data such as request url, method, parameters, request body data type etc.
Many of the resources and examples that I have read so far hard code each individual API resource request flow. For example, hardcoding flows for Product, hardcoding flows for Customer etc. Subsequently, duplicate code is the result. How are others tackling this problem in their production environments?

Differences between Angular's $httpBackend expectPost and whenPost

While working on some tests, I was surprised to find, that simply changing the $httpBackend.expectPost to a $httpBackend.whenPost fixed some broken tests...
Looking at the docs, it says that an expect "Creates a new request expectation.", while a when "Creates a new backend definition.". Unfortunately this doesn't mean much too me...
Can someone explain the difference between these two methods?
As mentioned in the docs,
Request expectations provide a way to make assertions about requests
made by the application and to define responses for those requests.
The test will fail if the expected requests are not made or they are
made in the wrong order.
Backend definitions allow you to define a fake backend for your
application which doesn't assert if a particular request was made or
not, it just returns a trained response if a request is made. The test
will pass whether or not the request gets made during testing.
With whenPost() definition, whenever your code makes a POST request through $http, this method will intercept and serve the response. But in case of expectPost(), it actually creates an expectation about POST request to that URL and if your code doesn't make any POST request to that URL, test will fail.
In case a request is made, then it will also respond with mock object.

How to make Sinon Fake server respond to some routes but not all of them

Is it possible to setup Sinon Fake Server to respond to some routes, for example /products but not /orders.
My scenario is: I am not using Sinon Fake Server for unit testing, I want to fake the server in cases where the API is not ready yet for a given area of the application. I want the application to call the real server in all cases, but when it calls /products, I want sinon to respond it for me.
I could add reference to Sinon to the product pages temporarily until I get the real API and then remove it, but ideally I would like to keep all of that isolated from the real implementation. Right now I have a UseFakeServer flag on my main.js file to determine whether sinon is on or not. My fake server has a list of RespondWith, but if a route is not found there I get a 404 instead of trying to go to the real server. fake server AutoRespond is set to true.
Not sure if it makes a difference but I am using backbone on the front end.
Thanks!
Assuming you are doing the API requests via HttpXMLRequest and using at least Sinon 1.3.0 you should use sinon.useFakeXMLHttpRequest and then you are able to filter which requests should be faked.
When using Sinon.JS for mockups or partial integration/functional
testing, you might want to fake some requests, while allowing others
to go throught to the backend server. With filtered
FakeXMLHttpRequests (new in Sinon 1.3.0), you can.
FakeXMLHttpRequest.useFilters Default false. When set to true, Sinon
will check added filters if certain requests should be “unfaked”.
FakeXMLHttpRequest.addFilter(fn) Add a filter that will decide whether
or not to fake a request. The filter will be called when xhr.open is
called, with the exact same arguments (method, url, async, username,
password). If the filter returns true, the request will not be faked.
So for example you want all requests to /products not to be handled by Sinon it would be something like
sinon.FakeXMLHttpRequest.useFilters = true;
sinon.FakeXMLHttpRequest.addFilter(function(method, url, async, username, password) {
return /\/products/g.test(url);
});
See http://sinonjs.org/docs/#server

Get raw request / response from $http call

I am writing an AngularJs app to test an API we developed. The app uses the $http object to make requests to the API. One of the asks is that after the call it's possible to review the raw HTTP (headers and bodies) Request/Response, similarly to what's available in Fiddler via Raw tabs.
Is it something that $http provides out of the box?
If not, it appears that the only challenge is gaining access to the actual request http headers. It's easy to get the response headers and request/response bodies, but not sure how to get the actual request headers.
Thanks.
If you are using $http service to make your API calls, you can use Interceptors to achieve what you want.
Here is what docs tell us about them:
For purposes of global error handling, authentication, or any kind of synchronous or asynchronous pre-processing of request or postprocessing of responses, it is desirable to be able to intercept requests before they are handed to the server and responses before they are handed over to the application code that initiated these requests. The interceptors leverage the promise APIs to fulfill this need for both synchronous and asynchronous pre-processing.
You can find more in depth explanation in the official docs. For example, here.
Also, there are some questions about interceptors on this site. There are some examples of their usage for displaying loading screen in applications: here, here and, probably, somewhere else.
Hope, this helps.
Yes, AngularJs is wrapped around some JQuery or internally JQlite if JQuery is not present and written in Javascript and it provides some pre-defined services. A typical service looks like the following.
AngularJS docs: tutorial step 5
$ Prefix Naming Convention You can create your own services, and in
fact we will do exactly that in step 11. As a naming convention,
Angular's built-in services, Scope methods and a few other Angular
APIs have a $ prefix in front of the name.
The $ prefix is there to namespace Angular-provided services. To
prevent collisions it's best to avoid naming your services and models
anything that begins with a $.
If you inspect a Scope, you may also notice some properties that begin
with $$. These properties are considered private, and should not be
accessed or modified.
angular.module('myApp')
.factory('myService', function ($http, $injector) {
'use strict';
return $http.get('/endpoint')
.then(function () {
return $injector.get('endpoint');
}
.error(function () {
// handle error
}
};
})
Have a look a the image in AngularJS docs which shows a number of services with the $ prefix. Mostly, wrappers over service. It is reserved. More at FAQ.

Preventing similar POST requests with AngularJS

I am currently building a dashboard page with multiple widgets. Those widgets retrieve their data with REST calls ($resource). A few widgets make similar calls and I don't want to DDOS our server so I am looking for a way to make a call only once and resolve all similar requests with the same response.
Since I am restricted to using POST requests only, I cannot use the cache option that $resource offers. This seems to be doing exactly what I want but only for GET requests.
I was thinking along the lines of using a http interceptor to queue similar POST requests, fire only one of them and resolving them all when the first one gets its response.
However, I cannot seem to put the pieces together so any help is appreciated. I am open to other options.
Kind regards,
Tim
Services in AngularJS are singletons, so a solution would be to store the response in the service, as a variable. Then next time you'll do the request, previously check if the variable is null, if it's not you wrap it in a promise and returned it. If it's null, then you do the request, and store the response for the next call.
You can also either use this in your request service or in your interceptor service.
I hope I helped !
Refactor your widgets to depend on a service (singleton).
This service should either poll the server via XHR, or get server push via websocket for updates.
If polling, look into server side caching and etags.

Resources