Wednesday 25 March 2015

Adobe Omniture Debugger configuration for tracking events on Webpage

1.Go to  http://blogs.adobe.com/digitalmarketing/analytics/meet-the-new-digitalpulse-debugger/

2.Just create a simple bookmark or favorite in your browser of choice (we’ve tested in IE, Firefox, Safari, and—your developer’s favorite—Chrome). Then, replace the URL of the bookmark with the following code (and make sure you get all of the code!):
  javascript:void(window.open(%22%22,%22dp_debugger%22,%22width=600,height=600,location=0,menubar=0,status=1,toolbar=0,resizable=1,scrollbars=1%22).document.write(%22%3Cscript%20language=\%22JavaScript\%22%20id=dbg%20src=\%22https://www.adobetag.com/d1/digitalpulsedebugger/live/DPD.js\%22%3E%3C/%22+%22script%3E%22));

Tuesday 10 March 2015

Setting up Karma-Jasmine to run unit tests in PhantomJS and Chrome

Setting up Karma to run unit tests in PhantomJS and Chrome

Install NodeJS 
Node packages to install:
npm install -g karma-cli 
npm install -g karma --save-dev 
npm install -g phantomjs 
npm install -g karma-jasmine --save-dev 
npm install -g karma-phantomjs-launcher --save-dev 
npm install -g karma-chrome-launcher --save-dev
Install the last one only if you plan to run your unit tests using Chrome; you don’t need it if you prefer running them only in PhantomJS. Now, create the karma configuration file.
karma init karma.conf.js
To run karma: karma start karma.conf.js
For code coverage:

npm install -g karma-coverage
Example Unit test:
With Jasmine, we first describe our test suite, and then use it function to give our test case specification. In the spec, we expect the behaviors of our testing target. We also use beforeEachand afterEach to setup or tear down test environment for our spec.

Test Simple Controller

The best way to learn is to practice. Let's start with a very simple AngularJS controller, for my Aboutpage.
'use strict';

angular.module('jiwhizWeb').controller('AboutController',
['$rootScope', '$scope',
function($rootScope, $scope) {
    $rootScope.activeMenu = {
        'home' : '',
        'blog' : '',
        'about' : 'active',
        'contact' : '',
        'admin' : ''
    };
    $rootScope.showTitle = true;

    $rootScope.page_title = 'About Me';
    $rootScope.page_description = 'Here is my story.';
}
]);
This is the simplest page in my blog application, and no complex logic in the controller code. It only sets the active menu item, shows the title and sets page title with description.
The unit test for this controller will be also simple. We expect the page to do exactly what we designed, which are to set the "About" menu item as active, to show the title, and to have correct page title and description.
'use strict';

describe('Controller: public/AboutController', function() {

    var $rootScope, $scope, $controller;

    beforeEach(module('jiwhizWeb'));

    beforeEach(inject(function(_$rootScope_, _$controller_){
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        $controller = _$controller_;

        $controller('AboutController', {'$rootScope' : $rootScope, '$scope': $scope});
    }));

    it('should make about menu item active.', function() {
        expect($rootScope.activeMenu.about == 'active');
    });

    it('should show title.', function() {
        expect($rootScope.showTitle == true);
    });

    it('should have correct page title.', function() {
        expect($rootScope.page_title).toEqual('About Me');
    });

    it('should have correct page description.', function() {
        expect($rootScope.page_description).toEqual('Here is my story.');
    });
});
In unit test code, we call Jasmine function describe for our test suite, and we pass the suite title string and function of our test suite. And inside this suite function, we call Jasmine function it for our test specs, and we also pass the spec title string and spec function. Inside our spec functions, we call expect function with actual value, which is chained with a Matcher function, which takes the expected value. Here I used toEqual matcher function. See Jasmine Documentation for more matcher functions and how to define your custom matcher functions.
The first beforeEach is to load our application module - jiwhizWeb. And the secondbeforeEach is to inject dependencies from AngularJS, like $rootScope. Since we want to use same variable name "$rootScope" in our suite function, and let $rootScopebe used by our spec functions, we have to apply a trick, that is to use underscore to wrap the in-coming parameter_$rootScope_, and AngularJS Mock will correctly resolve it to the reference to actual$rootScope. We can use it to create our suite variable $scope by $scope = $rootScope.$new();. Last, we use $controller to initialize our AboutController and inject all dependencies.

Test Controller with Promise

OK, the AboutController is too simple. Let's try another more complicated controller,BlogListController, which uses promise to Consume RESTful API With Angular-HAL.
'use strict';

angular.module('jiwhizWeb').controller('BlogListController',
['$rootScope', '$scope', '$timeout', 'WebsiteService',
function($rootScope, $scope, $timeout, WebsiteService) {
    $rootScope.activeMenu = {
        'home' : '',
        'blog' : 'active',
        'about' : '',
        'contact' : '',
        'admin' : ''
    };
    $rootScope.showTitle = true;

    $rootScope.page_title = 'My Personal Blog';
    $rootScope.page_description = 'Some of my thoughts and experiences.';

    var setup = function( pageNumber ) {
        WebsiteService.load()
            .then( function( websiteResource ) {
                return websiteResource.$get('blogs', {'page': pageNumber, 'size':10, 'sort':null});
            })
            .then( function( resource )
            {
                $scope.page = resource.page;
                $scope.page.currentPage = $scope.page.number + 1;
                return resource.$get('blogPostList');
            })
            .then( function( blogPostList )
            {
                $scope.blogs = blogPostList;
                blogPostList.forEach( function( blog ) {
                    blog.contentFirstParagraph = getFirstSection(blog.content);

                    // load author profile
                    blog.$get('author').then(function(author) {
                        blog.author = author;
                    });

                });

            })
            ;

    };

    setup(0);

    $scope.selectBlogPage = function(pageNumber) {
        setup(pageNumber-1); //Spring HATEOAS page starts with 0
    };
}
]);
Here we have setup function to load list of blogs for specific page, and load each blog author. The challenge is how to test those chain of promises, which are asynchronous JavaScript operations. By searching Stack Overflow and reading other developers' blog, I found the way to use AngularJS$q.defer() to resolve the promise in unit test.
'use strict';

describe('Controller: public/BlogListController', function() {
    var $rootScope, $scope;
    var $controller, service;

    var mockWebsite = {
        $get: function(rel) {}
    };

    var mockResource = {
        page: {
            size: 10,
            totalElements: 100,
            totalPages: 4,
            number: 0
        },
        $get: function(rel) {}
    };

    var mockBlogPostList = [
        {
            title: 'Test Blog',
            content: '<p>This is first paragraph.</p> Other parts...',
            $get: function(rel) {}
        },
        {
            title: 'Another Blog',
            content: '<p>I came second.</p>',
            $get: function(rel) {}
        }
    ];

    var mockAuthor = {
        displayName: 'author'
    };

    beforeEach(module('jiwhizWeb'));

    beforeEach(inject(function(_$rootScope_, _$controller_, _$q_, _WebsiteService_) {
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        $controller = _$controller_;
        service = _WebsiteService_;

        var websiteDeferred = _$q_.defer();
        websiteDeferred.resolve(mockWebsite);
        spyOn(service, 'load').andReturn(websiteDeferred.promise);

        var blogsDeferred = _$q_.defer();
        blogsDeferred.resolve(mockResource);
        spyOn(mockWebsite, '$get').andReturn(blogsDeferred.promise);

        var blogListDeferred = _$q_.defer();
        blogListDeferred.resolve(mockBlogPostList);
        spyOn(mockResource, '$get').andReturn(blogListDeferred.promise);

        var authorDeferred = _$q_.defer();
        authorDeferred.resolve(mockAuthor);
        spyOn(mockBlogPostList[0], '$get').andReturn(authorDeferred.promise);
        spyOn(mockBlogPostList[1], '$get').andReturn(authorDeferred.promise);

        $controller('BlogListController',
            {'$rootScope' : $rootScope, '$scope': $scope, 'WebsiteService': service});
        $rootScope.$apply(); // promises are resolved/dispatched only on next $digest cycle
    }));

    it('should make Blog menu item active.', function() {
        expect($rootScope.activeMenu.blog == 'active');
    });

    it('should have selectBlogPage() function.', function() {
        expect($scope.selectBlogPage).toBeDefined();
    });

    describe('BlogListController setup(pageNumber) function', function() {

        it('should have currentPage set to 1.', function() {
            expect($scope.page.currentPage).toBe(1);
        });

        it('should have two blogs and first one is Test Blog.', function() {
            expect($scope.blogs.length).toEqual(2);
            expect($scope.blogs[0].title).toEqual('Test Blog');
        });

        it('should have first blog with title "Test Blog" and author "author"', function() {
            expect($scope.blogs[0].title).toEqual('Test Blog');
            expect($scope.blogs[0].author.displayName).toEqual('author');
        });

        it('should have second blog with title "Another Blog" and author "author"', function() {
            expect($scope.blogs[1].title).toEqual('Another Blog');
            expect($scope.blogs[1].author.displayName).toEqual('author');
        });

    });
});
The trick is to use AngularJS deferred object by calling $q.deferred(), and use deferred APIresolve(value) to return our mock resources. Then use Jasmine spyOn() function to stub our resource function and return promise object associated with the deferred object. After we setup all the mock up resources along the chain of promises, and initialize BlogListController, we have to do a final step $rootScope.$apply(); to trigger AngularJS $digest cycle programmatically, so our promises can be resolved.

Conclusion

Writing unit test is not easy. But it is so important, because writing unit test can actually make you think hard to write clean and elegant code.
With behavior-driven development, we can describe our test cases in a more understandable way, and it helps better communication between developers and business. Business can tell user stories, and developer can translate those stories into unit test, so when requirements change, we can easily find out what part of code we need to change as well.
My experience with BDD and Jasmine is very pleasant.