Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test an AngularJS Controller with $setPristine

I have the following controller:-

appControllers.controller("TaskAddController", function ($scope, $timeout, taskService) {
    $scope.task = {};
    $scope.messages = {
        error: false
    };

    $scope.actions = {
        save : function() {
            if ($scope.frmAddTask.$valid) {
                taskService.insert($scope.task)
                    .then(
                        function() {
                            $scope.messages.success = true;
                            $scope.task = {};
                            $scope.frmAddTask.$setPristine();

                            $timeout(function() {
                                $scope.messages.success = false;
                            }, 3000);
                        },
                        function() {
                            $scope.messages.error = true;
                        }
                    );
            } else {
                $scope.messages.error = true;
            }
        }
    };
});

With this unit test:-

/// <reference path="../../../../src/tasks.web/scripts/angular-1.2.10.js" />
/// <reference path="../../../../src/tasks.web/scripts/angular-route-1.2.10.js" />
/// <reference path="../../../../src/tasks.web/scripts/app.js" />
/// <reference path="../../../../src/tasks.web/scripts/services.js" />
/// <reference path="../../../../src/tasks.web/scripts/controllers.js" />
/// <reference path="../lib/angular/angular-mocks.js" />

describe("TaskAddController", function() {
    var createController, scope, deferred, mockTaskService;

    beforeEach(function () {
        module('appControllers');
        module('appServices');

        inject(function ($rootScope, $q, taskService) {
            scope = $rootScope.$new();

            scope.frmAddTask = {
                $valid: true
            };

            deferred = $q.defer();
            mockTaskService = taskService;

            spyOn(mockTaskService, "insert").andReturn(deferred.promise);
        });

        inject(function ($controller) {
            createController = function () {
                return $controller("TaskAddController", {
                    $scope: scope,
                    taskService: mockTaskService
                });
            };
        });
    });

    it("when actions.save is called then messages.success should be true", function () {
        var task = {
            title: "Title",
            description: "Description"
        };

        createController();
        scope.task = task;
        scope.actions.save();

        deferred.resolve("insert");
        scope.$root.$digest();

        expect(scope.messages.success).toEqual(true);
    });
});

This errors with the message TypeError: 'undefined' is not a function (evaluating '$scope.frmAddTask.$setPristine()')

I assume this is because the unit test only tests the controller and $scope.frmAddTask only exists when the view is present. So my question is how do I unit test this properly?

like image 614
baynezy Avatar asked Nov 29 '25 16:11

baynezy


1 Answers

Yes, normally the $scope.frmAddTask object would be created by the ngForm directive. However, in this case, it is being created by you in your test:

scope.frmAddTask = {
  $valid: true
};

Since you're using this mock object anyway, I would suggest stubbing out the $setPristine method on it:

scope.frmAddTask = {
  $valid: true,
  $setPristine: function() {}
};
like image 144
alexsanford1 Avatar answered Dec 02 '25 04:12

alexsanford1