Simplest AngularJS Service and a Jasmine unit test

The syntax for creating an AnguarJS service is rather alien to me as a Java developer, so I struggled to get this right, despite looking at and trying a number of different examples from different articles and howtos.

I think I’ve got this distilled to a simplest possible example now, so for future reference, this is a bare minimum service:


angular.module('AppName.services', [])
.factory('exampleService', function () {

  var serviceImpl = {};

  //methods on service here

  return serviceImpl;
  });

The syntax for implementing methods on the Service is like this (insert into where the comment is in the above example:


return {
exampleMethod: function (exampleParam1) {
  var result;

  //do something here

  return result;
  }
};

A simple Jasmine test for a Service looks like this:


describe('Example service', function () {
var exampleService;

  it("Should be something here", function () {

    var $injector = angular.injector([ 'AppName.services' ]);

    exampleService = $injector.get( 'exampleService' );
    var result = exampleService.exampleMethod(1);
    expect(result).toBe(1);
 });

});

(Page views: 11)

Using mocks with Jasmine tests for AngularJS

I’m not entirely sure I understand exactly what is going on here or how this is working, but posting to refer back to later.

I have a controller that’s using $interval. Rather than coding a delay into my test in order to let time pass in real time before I do my assertions, a better approach would be to mock out $interval so you can move elapsed time forward programmatically, which is a much better approach.

Luckily the ngMock package provides mocks for most things, including $interval. To move time, you call $interval.flush(millis);


describe('Test variable date timer', function () {

it('Runs for 1 iteration, 30min interval, adds 30 mins', function () {
  var $scope = {};
  angular.mock.inject(function ($controller, _$interval_) {
  $interval = _$interval_;
  controller = $controller('VariableRateDateCtrl', {$scope: $scope, $interval: $interval});

  });

  $scope.iterations = 1;
  $scope.timeInterval = 30;
  $scope.date = moment();
  startDate = $scope.date.clone();

  $scope.start();
  $interval.flush(1000 * $scope.iterations);

  endDate = $scope.date;
  expectedEndDate = startDate.clone().add($scope.timeInterval, 'minutes');
  expect(endDate.isAfter(startDate)).toEqual(true);
  expect(endDate).toEqual(expectedEndDate);
});

(Page views: 22)

Setting up Karma and Jasmine unit testing for an AngularJS app

There’s probably easier ways to do this (using angular-seed as a starting point?) but I like to get an understanding of what it takes to do something from scratch, so here’s some notes on adding karma and jasmine to an existing AngularJS project (leave me a comment with suggestions or corrections). My references to getting this working:

Assuming you already have node.js, use npm to install the karma and dependencies:
sudo npm install -g karma
sudo npm install -g karma-jasmine
sudo npm install -g karma-chrome-launcher
sudo npm install -g karma-cli

Karma config file – in the files section, list all dependent libraries, controllers being tested, and path/pattern to the test js to be executed:

module.exports = function (config) {
  config.set({
  basePath: '.',
  files: [
    'app/bower_components/angular/angular.min.js',
    'app/bower_components/angular-mocks/angular-mocks.js',
    'app/js/controller2.js',
    'test/*.js'
    ],
  exclude: [
  ],
  autoWatch: true,
  frameworks: [
    'jasmine'
  ],
  browsers: [
    'Chrome'
  ],
  plugins: [
    'karma-chrome-launcher',
    'karma-jasmine'
  ]
});
};

Starting karma:

karma start karma.conf.js

Example skeleton Jasmine test:

describe('ExmapleCtrl', function() {
  beforeEach(module('ExampleApp'));

var $controller;

beforeEach(inject(function(_$controller_){
// The injector unwraps the underscores (_) from around the parameter names when matching
  $controller = _$controller_;
}));

describe('test suite name', function() {
  it('description of test', function() {
    var $scope = {};
    var controller = $controller('ExampleCtrl', { $scope: $scope });

    //setup values
    $scope.somevalue = 1;

    //call method on controller
    $scope.examplemethod();
    expect(someValue).toEqual(exampleValue));
    });
  });
});

(Page views: 28)

Getting Started with AngularJS (pt 3): understanding $scope

I’m working through a number of sources to help me get up to speed with AngularJS:

Looking at each of these different learning sources is interesting because they all take a slightly different approach, and focus on different key areas. It’s interesting which areas they cover first, and which they leave to later.

Pro AngularJS for example spends half the book walking you through building a complete app end to end, explaining basics as it goes, but then doesn’t get into details until the second half of the book where it digs deeper into each topic area.

The official AngualrJS online tutorial takes a similar approach, walking you building an app step by step with minimal explanation as it goes, but it seems to cover the key basics. Interestingly this tutorial bakes in unit testing and end to end testing right from the start, which I though was very interesting to cover the test tools as an integrated part of development, whereas Pro AngularJS doesn’t get to cover unit testing until the last chapter of the book, which is my only criticism of the book so far.

$scope

The topic I wanted to cover in this post is $scope. As it allows you to create your domain model properties and functions and share between the view templates and your controllers, it seems a rather critical topic, although I don’t think the official tutorial really describe how where it is used controls the visibility between different controllers, and similarly the Pro AngularJS book doesn’t get into details until chapter 13.

On the otherhand, the Beginner to Expert in 7 Steps gets into a great explanation of it’s usage in Step 2. I’m not going to try and summarize their article here as they do a great job, so if you’re like me and learning AngularJS and wondering exactly how $scope is used to control scope… go and take a read of part 2 of their series.

 

(Page views: 38)

Getting Started with AngularJS (pt 2): views and ngRoute

Second part of my notes learning AngularJS (first part is here).

Angular handles multiple views in your Single Page Application by adding the ng-view directive at the point where you want your views inserted, e.g.

<div ng-view></div>

The logic to handle URL hash fragments is implemented using $routeProvider to map view template and controller pairs with each hash fragment that your app recognizes. For example:

var simpleApp = angular.module('SimpleApp',
  [
    "ngRoute",
    "SimpleControllers"
  ]);

simpleApp.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
    when('/', {
      templateUrl: 'page1.html',
      controller: 'Page1Controller'
    }).
    when('/page2', {
      templateUrl: 'page2.html',
      controller: 'Page2Controller'
    }).
    when('/page3', {
      templateUrl: 'page3.html',
      controller: 'Page3Controller'
    }).
    otherwise({
      redirectTo: '/'
    });
  }]);

An example working app is here: https://github.com/kevinhooke/SimpleAngularJSExample-ngRoute

(Page views: 34)

Getting started with AngularJS (notes)

Sharing some personal notes from getting started with and learning AngularJS (from working through the AngularJS Tutorial).

AngularJS is added to an HTML template with the ng-app directive. Where placed in the html means it’s applied to that element and it’s children:

<html ng-app="appname">

Reference to controller:

<body ng-controller="ExampleCtrl">

Reference values from Controller in HTML template:

{{ variablename }}

Iteration directive – repeats the element, e.g. on an <li>:

<li ng-repeat="item in items">

Text-based filter on matching items – only includes text matches on value of query:

<li ng-repeat="phone in phones | filter:query">

Skeleton Controller:

var exampleApp = angular.module('exampleApp', []);
exampleApp.controller('ExampleCtrl', function ($scope) {

//$scope is passed as arg and can be referenced here
//e.g. this sets var example on $scope to be referenced in template
$scope.example = "hello";
});

Sample, simplest case AngularJS app: https://github.com/kevinhooke/SimpleAngularJSExample

(Page views: 53)

angular-seed and node.js http-server for local development

Angular-seed is a skeleton AngularJS project with a recommended folder structure and configuration including all the recommended development tools, jasmine and karma for unit tests, Protractor for end-to-end tests, and node.js for your dev server. Check out the project here.

If you’ve already installed node.js then you may notice in the readme for angular-seed it mentions that they have configured a test webserver using node, but you can also install this as a global module and use it elsewhere. This is a useful and quick way to spin up a test server in a given directory to support development testing. Install the server globally with:

sudo npm install -g http-server

and then start it up in a directory that you want to be the root, with:

http-server

(Page views: 102)

Installing Nvidia drivers on Linux Mint 17.1

Booting the Mint Live DVD on a HP Pavilion with an AMD Phenom quadcore, I get to the desktop but it starts lagging, and is barely responsive. Selecting the compatibility mode boot option gets me to a lower res desktop but without the lagging issue. After I installed to my hd using compatibility mode, when booting up for the first time I ran into exactly the same issue.

At the Grub menu, if I edit the boot option and add nomodeset, then again, I can boot into a low res with no lag. This desktop has a Nvidia graphics card, so I tried following the instructions here, but I couldn’t get these steps to work, every time I ran the Nvidia installer, it kept telling me that the nouveau drivers were still loaded.

This page suggested to install via ‘sudo apt-get install nvidia-304′ – this approach seemed to download all the deps, build local, install, setup and configure, all in one go. When I rebooted, all looked good, and no need to manually add the nomodeset at the grub menu. Success! So far very impressed with the slickness of the Mint Cinnamon desktop!

 

(Page views: 59)