Leave a comment

Useful Faker.js API and demo page

In my angular projects I use the faker.js library to generate fake data for the test fixture factories used by my unit tests and the dev application running with a stubbed back-end. It is a convenient and consistent way to generate data that looks real and makes the code of our fixtures really simple. The Faker.js API documentation is really basic and sometimes it not obvious what kind of values it can generate.
To help with that you can use the next demo page http://marak.com/faker.js/ that shows examples of generated data for each of the faker.js api methods.

faker_demo

I encourage to use it and get familiar with the faker api to improve the quality of our test data.

Leave a comment

Bower Guideline – Always Ignore the files that you don’t want to publish

The bower.json defines several options, one of those is the ignore option:

ignore [array]: An array of paths not needed in production that you want Bower to ignore when installing your package.

It is really important to use it when you are defining a bower.json of a package that is meant to be used from other apps or modules.

Why?
When a consumer installs your package via Bower, it will download your project’s entire git repository into their project. But in most of the cases we don’t want to distribute everything. The consumer app doesn’t need things like: tests, configuration files, tasks, etc. Only the original and minified versions of the component and the documentation. That will save time downloading the module and disk space.

Guideline
The rule of thumb is to use the ignore attribute to define the list of files and directories that we don’t want to publish.

For example:

"ignore": [
"gulp",
".bowerrc",
".gitignore",
"gulpfile.js",
"package.json",
"README.md"
],

Leave a comment

Angular-ui-grid enable filtering from grid menu

In Angular ui-grid it is possible to configure the grid with filtering using the enableFiltering option.

vm.gridOptions = {enableFiltering: true};

I wanted to allow the user to hide/show the filter clicking a button.
There is an example of that in http://ui-grid.info/docs/#/tutorial/103_filtering, but I wanted to add that action to the grid menu itself.

angular-ui-grid-enable-filtering-grid-menu-01

angular-ui-grid-enable-filtering-grid-menu-02

Here is the code of my solution:

            vm.gridOptions.gridMenuCustomItems = [
                {
                    title: 'Hide filter',
                    icon: 'glyphicons filter failure',
                    leaveOpen: true,
                    order: 0,
                    action: function ($event) {
                        this.grid.options.enableFiltering = !this.grid.options.enableFiltering;
                        this.grid.api.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
                    },
                    shown: function () {
                        return this.grid.options.enableFiltering;
                    }
                },
                {
                    title: 'Show filter',
                    icon: 'glyphicons filter success',
                    leaveOpen: true,
                    order: 0,
                    action: function ($event) {
                        this.grid.options.enableFiltering = !this.grid.options.enableFiltering;
                        this.grid.api.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
                    },
                    shown: function () {
                        return !this.grid.options.enableFiltering;
                    }
                }
            ];

You can see that doesn’t need to expose the grid to scope in a onRegisterApi block.

Documentation:
http://ui-grid.info/docs/#/tutorial/103_filtering
http://ui-grid.info/docs/#/tutorial/121_grid_menu

Leave a comment

Angular – Caching $http calls using $cacheFactory service

In this post I am going to explain how we can cache requets to REST backends in our angular applications.

Introduction to $cacheFactory
Angular $cacheFactory is a service that allows us to create and access Cache objects. Think on a Cache as a simple key value store with put, get, destroy methods.

var myCache = $cacheFactory('cacheId');
myCache.put('key', 'value');
console.log(myCache.get('key'));

The angular $http services could use that Cache objects to cache resonse data.

angular.module('app', [])
    .factory('MyService', function ($http, $cacheFactory) {
		var myCache = $cacheFactory('cacheId');
        return {
            getPerson: function (id) {
                $http
                    .get('//server.com/api/people/' + id + '/', {cache: myCache})
                    .then(function (result) {
                        console.log(result.data.name);
                    });
            }
        }
    });

It uses the request URL as a key to store values. In the previous example if we call getPerson for the same person twice it will perform a http request only the first time and will return directly from the cache the second time.

Caching in Swagger APIs
In my current apps I don’t use directly the $http service to interact with the backend APIs, instead I use swagger generated API services that abstract me from writing that code. But the generated services allows also to use cache functionality. The way that we should use it is passing a cache object as a parameter of the services methods.
For example, we have the API service CurrentUserApi and its method getCurrentUser.

var currentUserApi = new CurrentUserApi(RestDomains.myService);
currentUserApi.getCurrentUser();

And we want to use cache here to avoid hitting the backend multiple times. The only thing that we need to do is to pass a Cache object as a param of the getCurrentUser method and the API service will use it to cache requests. Again, notice that we don’t need to deal with the complexity of managing the cache ourselves.

var currentUserApi = new CurrentUserApi(RestDomains.myService);
var currentUserCache = $cacheFactory('currentUser');
currentUserApi.getCurrentUser({$cache: currentUserCache});

Using a CacheService
We can simplify the use of the cache in our services using the same cache object. For that we can create a singleton CacheService with a local cache created with $cacheFactory. It can be injected in our services and passed directly as the cache param.

angular
    .module('App')
    .factory('CacheService', ['$cacheFactory', function ($cacheFactory) {
        return $cacheFactory('CacheService');
    }]);
 
 
angular
    .module('App')
    .factory('UsersService', ['RestDomains', 'CacheService', 'CurrentUserApi', function (RestDomains, CacheService, CurrentUserApi) {
    var currentUserApi = new CurrentUserApi(RestDomains.myService);

    return {
        getCurrentUser: function () {
            return currentUserApi.getCurrentUser({$cache: CacheService});
        }
    };
}]);

Considerations
The use of caching in the angular services could reduce the number of requests that the single page application performs, improving performance and making the UI more responsive. But it is really important to choose properly the endpoints and resource to cache. Usully we want to cache resources that we now that are not going to change during the user “session”, resources like current user information, reference data, etc.

It is possible to use different implementations of the $cacheFactory services like angular-cache that provides Cache objects with timeouts or the possibility of caching using HTML5 local storage. The good thing of the angular’s built-in version is its simplicity.

Notice also that the use of Cache objects directly by the $http or the sagger APIs services it is a cleaner option that dealing direcly in our service with the cache of values.

Documentation:
https://docs.angularjs.org/api/ng/service/$cacheFactory
https://egghead.io/lessons/angularjs-cachefactory
http://jmdobry.github.io/angular-cache/
https://github.com/wcandillon/swagger-js-codegen

Leave a comment

Mock an Angular Service

When we unit test an angular controller we test it in isolation remplacing the services that the controller uses with test doubles (aka mocks). In Jasmine the kind of test double used are called Spies. (Read more: http://jasmine.github.io/2.0/introduction.html)

The next code example shows the most basic beforeEach initialization block for a controller test suit. In it we use the $controller service to instantiate the controller under test MyCtrl injecting a new clean $scope before each test execution.

beforeEach(inject(function ($rootScope, $controller) {
    scope = $rootScope.$new();
 
    $controller('MyCtrl', {
        $scope: scope // inject the stubbed scope
    });
}));

During the instantiation of the controller we can configure the mock services or stubbed data to inject. Notice that for all the dependencies that we don’t configure explicitily the unit test will use the real ones.
There are different ways to mock dependencies, I am going to show two alternatives here:

Replacing a service by a spy object

var stateSpy;
 
beforeEach(inject(function ($rootScope, $controller, MyService) {
    scope = $rootScope.$new();
    controller = $controller;
 
    stateSpy = jasmine.createSpyObj('$state', ['go']); // create a test double for a $state service with function called go
 
    $controller('MyCtrl', {
        $scope: scope,
        $state: stateSpy // inject the test double in the controller
    });
 
}));

Replacing the functions of a service by spies
Let’s say that MyCtrl makes use of a function getData() on a service called MyService. We can remplace that function with an spy and fake their response.

beforeEach(inject(function ($rootScope, $q, $controller, MyService) {
    scope = $rootScope.$new();
    q = $q;
    controller = $controller;
 
    spyOn(MyService, 'getData').and.callFake(function () {
        var deferred = $q.defer();
        deferred.resolve(TEST_DATA);
        return deferred.promise;
    });
 
    $controller('MyCtrl', {
        $scope: scope
    });
 
}));

With this approach we are replacing the functions of a service not the service itself. If the function to spy doesn’t exist in the service the test will fail.

Leave a comment

Angulartics custom plugin which uses an Angular service

Recently I started to use in my Angular projects Angulartics to deal with web analytics. It is a clean solution that could be directly used with multiple providers like Google Analytics or Piwik, see the list of plugins available.

If you want to use a different analytics or ussage tracking service, you can create your own vendor plugin. The project documentation explains how to do it and claims that

It’s very easy to write your own plugin

And indeed it’s easy, the only thing to do is write your code inside these two functions:

angular.module('angulartics.myplugin', ['angulartics'])
  .config(['$analyticsProvider', function ($analyticsProvider) {

  $analyticsProvider.registerPageTrack(function (path) {
    // your implementation here
  }

  $analyticsProvider.registerEventTrack(function (action, properties) {
    // your implementation here
  }

}]);

If you take a look to the existing plugins implementation all of them access to an external api defined in the global scope, for example the piwik plugin uses window._paq.

But what I want to do is call from these track methods an angular service that allow me to post usage resources to a REST API. In the angular way without use any global scope function.

The problem here is that we should write our plugin code is inside an angular config block. And from a config block angular doesn’t allow to instantiate services neither inject the instance $injector.

I solved that issue using this approach:

var $injector = angular.element(document.documentElement).injector();

it allows us to get a instance injector and with it instantiate any server that we need.

As an example this is the code for an angulartics custom plugin that uses $log and MyUsageTrackingService services:

(function (angular) {
    'use strict';

    /**
     * @name angulartics.customplugin
     * Custom Angulartics plugin that uses an Angular Service for the Usage Tracking.
     *
     * Implementation docs:
     * https://github.com/luisfarzati/angulartics/blob/master/README.md
     * http://stackoverflow.com/questions/26890042/how-to-inject-location-into-a-click-event-handler-defined-in-a-config-function
     */
    angular.module('angulartics.customplugin', ['angulartics'])

        .config(['$analyticsProvider', function ($analyticsProvider) {

            /**
             * Track Page
             */
            $analyticsProvider.registerPageTrack(function (path) {

                /* Instantiate $log service */
                var $log = instanceInjector().get('$log');

                /* Log Page */
                $log.debug('Page tracking: ', path);

            });

            /**
             * Track Event
             */
            $analyticsProvider.registerEventTrack(function (action, properties) {

                /* Instantiate services */
                var $log = instanceInjector().get('$log');
                var myUsageTrackingService = instanceInjector().get('MyUsageTrackingService');

                /* Track */
                $log.debug("Event tracking: ", action, properties);

                var event = {
                    "applicationCode": "MYAPP",
                    "eventType": action,
                    "message": properties.message,
                    "appData": properties.appData
                };

                myUsageTrackingService.trackEvent(event);
            });

            /**
             * Returns an instance injector to allow the injection of services inside config blocks.
             */
            function instanceInjector() {
                return angular.element(document.documentElement).injector();
            }

        }]);

})(angular);
2 Comments

Git Bash inside WebStorm

I think that the Git bash is the best bash emulation these days for Windows platform. As a Linux fan I prefer use bash and the unix tools like ls, grep, cat, vim, etc.

I’ve been using it for a long time configuring it in Console2. But recently I discover that is also possible and really easy to use it from WebStorm or other JetBrains IDE.

Using WebStorm 9 go to the Terminal preferences in “File > Settings > Tools > Terminal”
and change the Shell path to:

“C:\Program Files (x86)\Git\bin\sh.exe” –login -i

webstorm_terminal_git_bash

Enjoy ;-)

Follow

Get every new post delivered to your Inbox.