Project #1: Todo App with MEAN Stack (Update)

I fell down the rabbit hole of testing and didn’t get near what I wanted to get done on this! But honestly, I’m okay with that. I feel that if I don’t have a handle on testing, I don’t have any business moving forward. And to keep to my challenge’s parameters, I’m going to have to leave the project as is for now and move on to the next.

Testing AngularJS (Front End)

After completing the Scotch.io tutorial, I jumped through a few other tutorials and a bunch of documentation on testing AngularJS. I quickly got some tests (yay!) but I’m uncomfortable with one thing — I didn’t find a way to test the success() function. I’m sure there must be a way, I just haven’t found it yet. (Pardon the formatting, I need to get a better way to display this…)

Example:

// todoController.spec.js
describe(‘Todo Controller’, function() {
var $controller, $scope, todoController, todoService;var todoList = [
{ id: ‘1’, text: ‘Buy a pony’ },
{ id: ‘2’, text: ‘Win Bingo’ },
{ id: ‘3’, text: ‘Dive into the ocean’ }
];beforeEach(angular.mock.module(‘ui.router’));
beforeEach(angular.mock.module(‘components.todoController’));
beforeEach(angular.mock.module(‘components.todoService’));

beforeEach(inject(function(_$controller_, _Todos_) {
$controller = _$controller_;
todoService = _Todos_;

var fakeHttpPromise = {
success: function(data) {
}
};

spyOn(todoService, ‘get’).and.returnValue(fakeHttpPromise);
spyOn(todoService, ‘create’).and.returnValue(fakeHttpPromise);
spyOn(todoService, ‘delete’).and.returnValue(fakeHttpPromise);

$scope = {};
todoController = $controller(‘todoController’, { $scope: $scope, Todos: todoService });
}))

it(‘should be defined’, function() {
expect(todoController).toBeDefined();
});

it(‘should initialize with a call to Todos.get()’, function() {
expect(todoService.get).toHaveBeenCalled();
})

it(‘should call Todos.create()’, function() {
$scope.formData = {
text: ‘Buy a pony’
};
$scope.createTodo();
expect(todoService.create).toHaveBeenCalled();
});

it(‘should not call Todos.create() if formData is null’, function() {
$scope.formData = null;
$scope.createTodo();
expect(todoService.create).not.toHaveBeenCalled();
});

it(‘should not call Todos.create() if formData is empty’, function() {
$scope.formData = {
};
$scope.createTodo();
expect(todoService.create).not.toHaveBeenCalled();
});

it(‘should call Todos.delete()’, function() {
$scope.deleteTodo(‘1’);
expect(todoService.delete).toHaveBeenCalled();
});
});

// todoController.js
angular.module(‘components.todoController’, [])

.controller(‘todoController’, function($scope, $http, Todos) {
$scope.formData = {};

// when landing on the page, get all todos and show them
Todos.get()
.success(function(data) {
$scope.todos = data;
});

// when submitting the add form, send the text to the node API
$scope.createTodo = function() {
if (!$.isEmptyObject($scope.formData)) {
Todos.create($scope.formData)
.success(function (data) {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.todos = data;
});
}
};

// delete a todo after checking it
$scope.deleteTodo = function(id) {
Todos.delete(id)
.success(function(data) {
$scope.todos = data;
});
};

});

Testing Node.js (Back End)

Hoo boy. So again, did a bunch of jumping around and reading, and I thought I would give testing Node.js with Jasmine a try, since I’d already picked up its basic syntax, and impatient me wanted to get on to developing new things. Long story short, this didn’t work for me. It seems to be because I have Karma installed and its butting up against some of its functionality, even after I installed Grunt to run my Node.js Jasmine tests. It may be that it’s possible to test both the front end and back end with Jasmine, but digging out the exact setup goes a bit deeper than I wanted to with this project, so I switched over to Mocha. I ended up using supertest to test my routes, but my week was up, and I forced myself to move on to the next project.

Future Plans

I really want to dig back into this and stretch it out to my original idea of a fuller todo-list app, just for the exercise, but it will have to wait for the new year.