Tuesday 19 February 2013

Blog moved to onekilo79.wordpress.com

I have moved this blog to http://onekilo79.wordpress.com as I could not stand the lack of first class support for syntax highlighting.

Monday 28 January 2013

Angularjs multiple services and Jasminejs unit testing a beginners guide

Angularjs using multiple services and Unit testing services with jasminejs 

(update: 29/01/12) I have moved away from angular.module('ServiceName', value( 
and instead use myServices.factory('ServiceName', function(){ as I found  it did not do as I expected to.

Services are a bit harder to unit test and get configured than controllers.
Most examples have a single service or 2 services in a single file.
This is harder to maintain with source control as multiple people could be making changes on the same file.  Here is how to set up and use services in different files.

I have also included some example code on how to Unit test your angularjs service with jasperjs.

/app/app.js

Add a new module myApp.services do your app.js and then reference it inside your angular.module [] brackets.  The deceleration of the 'myApp.services' allows you then to use this module in the services. 

var myServices = angular.module('myApp.services', []);
var myApp = angular.module('myApp', ['myApp.services'])
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'views/my-controller.html',
        controller: 'MyCtrl'
      });
  }]); 

/app/index.html

Add 2 services to your index.html so they are included in your app.
 
<script src="scripts/services/first-service.js" ></script> 
<script src="scripts/services/second-service.js" ></script> 

/app/services/first-service.js

Here is a example service containing one value and one function.

'use strict';

myServices.factory('FirstService', function(){
  var firstService = {};
  firstService.aValue = 'one';
  firstService.next = function (param1) {
    return this.aValue+ ' two';
  };
  return firstService;
}); 

/app/services/second-service.js

Second service does nothing special just a value an a method also.

myServices.factory('SecondService', function(){
  var sercondService = {};
  secondService.animal = 'penguin';
  secondService.whereDoTheyLive = function () {
    return this.aValue+ ' live in the Antarctic NOT in the Arctic.  The Arctic is for the Polar Bears.';
  };
  return secondService;
}); 

How to do it wrong

/app/services/first-service.js  
angular.module('myApp.services',[]).value('FirstService',
...
); 

/app/services/second-service.js

angular.module('myApp.services',[]).value('SecondService',
...
);
 

The problem with the above

The problem is the first-service is the first called by the inclusion in the index.html first.

You cannot add 2 or more services onto the myApp.services where both use the [] notation.  
I found it is best to assign the myApp.services in the /app/app.js and then just reference it in all the other services you are going to create.

Testing using Jasperjs

CoffeeScript

The below code will setup the first service for testing and importantly the inject will use the global service var as the service so we can run the methods and values upon it.

describe 'FirstService', ->
  service = {}
  beforeEach module('clientApp.services')

  beforeEach inject (FirstService) ->
    service = FirstService

  describe 'the first service', ->
    it 'should have a value',  ->
      expect(service.aValue).toEqual('one')

Javascript

The generated javascript that will be run by the jasperjs.

// Generated by CoffeeScript 1.4.0
(function() {
  describe('FirstService', function() {
    var service;
    service = {};
    beforeEach(module('myApp.services'));
 
    beforeEach(inject(function(FirstService) {
      return service = FirstService;
    }));
    return describe('the first service', function() {
      it('should have a value', function() {
        expect(service.aValue).toEqual('one');
      });
    });
  });

}).call(this);

Friday 18 January 2013

Angularjs and URL routing and adding a controller for beginners

Angularjs and Url routing and adding a controller for beginners

Intro

Just started working with Angularjs.
This is the basis of adding a new controller and wiring it into angularjs.

Awesome tutorial from angularjs. AngularJS tutorial

Summary:

tl;dr
  1. add a when to the app.js. under the $routeProvider.
  2. create the controller-weva.js file and name the controller the same as the when block.
  3. create the weva-view.html same name as in the when block to receive the controller call.
  4. add the controller-weva.js script named in the when block to the index.html
  5. visit the url from the when block.  May have to restart. 

Routing file - /app/js/app.js

The routing of Angularjs is done in the /app/js/app.js file.
App.js from the tutorial project

Here is the contents:
angular.module('phonecat', ['phonecatFilters', 'phonecatServices']).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider.
      when('/phones', {templateUrl: 'partials/phone-list.html',   controller: PhoneListCtrl}).
      when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
      otherwise({redirectTo: '/phones'});
}]);

phonecat matches the angular-app from the index.html file.
PhoneListCtrl is the name of the controller to use for this request.
/phones the url mapping that will map to the PhoneListCtrl.
partials/phone-list.html is the location of the html file to receive the angularjs call after the controller.  The folder name is not required to be named partial.  Maps to /app/partials/phone-list.html.
phone-list.html from tutorial

Header file: /app/index.html

Index is the starting point for your angularjs project.

The module 'phonecat' from the app.js matches the index ng-app tag in index.html of the project.

<html lang="en" ng-app="phonecat">

index.html from the Angularjs tutorial

The controllers are added via adding a script like following snippet. 

<script src="js/controller.js"></script>

Controller "example" file: /app/js/controllers.js

controllers.js from the tutorial project

Snippet of the controllers.js:

function PhoneListCtrl($scope, Phone) {}

The tutorial has 2 controllers in it but you can have separate files which makes it easier to source control.

Friday 23 December 2011

Unit testing Grails 2.0 Controllers withForm to handle duplicate submits

The documentation is a bit out of date for Grails 2.0.0 for testing controllers with the withForm { } closure to stop double submits.
New in Grails 2.0.0 is that it is more strict with its unit testing when using the withForm method
Add the following in to allow the form token to allow your method to get into the withForm{} block of your code
setup(){ 
    def serverUrl = "http://localhost:80"
    org.codehaus.groovy.grails.web.servlet.mvc.SynchronizerTokensHolder 
    tokenHolder = SynchronizerTokensHolder.store(session)
    def token = tokenHolder.generateToken(serverUrl)
    params[SynchronizerTokensHolder.TOKEN_KEY] = token
    params[SynchronizerTokensHolder.TOKEN_URI] = serverUrl
}