Skip to content

Instantly share code, notes, and snippets.

@jsheridanwells
Created February 1, 2018 21:19
Show Gist options
  • Save jsheridanwells/aad7f7b71b577e265192dfdc736d2cc6 to your computer and use it in GitHub Desktop.
Save jsheridanwells/aad7f7b71b577e265192dfdc736d2cc6 to your computer and use it in GitHub Desktop.
Testing an AngularJS app with Karma and Jasmine

From this tutorial

Setup

Install basic structure

$ mkdir meet-irl && cd meet-irl
$ touch server.js
$ mkdir app && cd app
$ touch index.html app.js app.css

Start npm: $ npm init. (Make sure entry point is server.js)

Install Express: $ npm install express body-parser morgan path --save

Add the following to server.js:

var express = require('express'),
    app = express(),
    bodyParser = require('body-parser'),
    morgan = require('morgan'),
    path = require('path');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(function(req, res, next) {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, content-type, Authorization');
  next();
});

app.use(morgan('dev'));

app.use(express.static(__dirname + '/app'));

app.get('*', function(req, res) {
  res.sendFile(path.join(__dirname + '/index.html'));
});

app.listen(8080);
console.log('meet-irl is running on 8080');

Add the following to app.js:

(function() {
  'use strict';

  angular.module('meetIrl', [
    'ui.router'
  ])
  .config(function($urlRouterProvider) {
    $urlRouterProvider.otherwise("/");
  });
})();

Run server: $ nodemon server.js

Set up Karma

Install Karma plugins:

$ npm install karma karma-jasmine jasmine-core karma-chrome-launcher --save-dev

Install Angular dependencies:

npm install angular angular-ui-router angular-mocks --save-dev

Run $ karma init and set up Karma configs

First Test

Set up files:

$ mkdir -p app/services/users
$ touch app/services/users/{users.js,users.spec.js}

In users.spec.js, set up test suite:

describe('Users factory', function() {
  it('has a dummy spec to test 2 + 2', function() {
    // An intentionally failing test. No code within expect() will never equal 4.
    expect().toEqual(4);
  });
});

Add all necessary files to karma.conf.js:

files: [
    './node_modules/angular/angular.js',                             // angular
    './node_modules/angular-ui-router/release/angular-ui-router.js', // ui-router
    './node_modules/angular-mocks/angular-mocks.js',                 // loads our modules for tests
    './app/services/users/users.js',                                 // our Users factory
    './app/app.js',                                                  // our angular app
    './app/services/users/users.spec.js'                             // our test file for our Users factory
  ],

Modify the users.spec.js spec:

describe('Users factory', function() {
  var Users;

  // Before each test load our api.users module
  beforeEach(angular.mock.module('api.users'));

  // Before each test set our injected Users factory (_Users_) to our local Users variable
  beforeEach(inject(function(_Users_) {
    Users = _Users_;
  }));

  // A simple test to verify the Users factory exists
  it('should exist', function() {
    expect(Users).toBeDefined();
  });
});

Create Users factory:

(function() {
  'use strict';

  // Creating the module and factory we referenced in the beforeEach blocks in our test file
  angular.module('api.users', [])
  .factory('Users', function() {
    var Users = {};

    // Users.method = function() {};

    return Users;
  });
})();

//ETC...//

Final users.spec.js:

'user strict';

describe('Users factory', function() {
  let Users;

  let userList = [
    {
      id: '1',
      name: 'Jane',
      role: 'Designer',
      location: 'New York',
      twitter: 'gijane'
    },
    {
      id: '2',
      name: 'Bob',
      role: 'Developer',
      location: 'New York',
      twitter: 'billybob'
    },
    {
      id: '3',
      name: 'Jim',
      role: 'Developer',
      location: 'Chicago',
      twitter: 'jimbo'
    },
    {
      id: '4',
      name: 'Bill',
      role: 'Designer',
      location: 'LA',
      twitter: 'dabill'
    }
  ];

  let singleUser = {
    id: '2',
    name: 'Bob',
    role: 'Developer',
    location: 'New York',
    twitter: 'billybob'
  }

  beforeEach(angular.mock.module('api.users'));
  beforeEach(inject(function(_Users_){
    Users = _Users_;
  }));

  it('should exist', () => {
    expect(Users).toBeDefined();
  });

  describe('.all()', () => {
    it('should exist', () => {
      expect(Users.all).toBeDefined();
    });
    it('should return a list of users', () => {
      expect(Users.all()).toEqual(userList);
    });
  });

  describe('.findById()', () => {
    it('should exist', () => {
      expect(Users.findById).toBeDefined();
    });
    it('should return one user object if it exists', () => {
      expect(Users.findById('2')).toEqual(singleUser);
    });
    it('should return undefined if the user cannot be found', () => {
      expect(Users.findById('ABC')).not.toBeDefined();
    });
  });
});

Final users.js:

(function() {

  'use strict';

  angular.module('api.users', [])
  .factory('Users', () => {
    let Users = {};

    let userList = [
      {
        id: '1',
        name: 'Jane',
        role: 'Designer',
        location: 'New York',
        twitter: 'gijane'
      },
      {
        id: '2',
        name: 'Bob',
        role: 'Developer',
        location: 'New York',
        twitter: 'billybob'
      },
      {
        id: '3',
        name: 'Jim',
        role: 'Developer',
        location: 'Chicago',
        twitter: 'jimbo'
      },
      {
        id: '4',
        name: 'Bill',
        role: 'Designer',
        location: 'LA',
        twitter: 'dabill'
      }
    ];

    Users.all = () => userList;

    Users.findById = (id) => userList.find((user) => user.id === id);

    return Users;
  });

})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment