ReganPerkins
ReganPerkins

Reputation: 1665

Angular Test for Bootstrap $modal controller componant

Below is the code for part of a controller I am trying to unit test but I'm not having much luck. I keep getting the error message Error: spyOn could not find an object to spy upon for account().

Controller

    $scope.confirmDelete = function (account) {

        var modalInstance = $modal.open({
            templateUrl: '/app/accounts/views/_delete.html',
            controller: function (global, $scope, $modalInstance, account) {
                $scope.account = account;

                $scope.delete = function (account) {
                    global.setFormSubmitInProgress(true);
                    accountService.deleteAccount(global.activeOrganizationId, account.entityId).then(function () {
                        global.setFormSubmitInProgress(false);
                        $modalInstance.close();
                    },
                    function (errorData) {
                        global.setFormSubmitInProgress(false);
                    });

                };

                $scope.cancel = function () {
                    global.setFormSubmitInProgress(false);
                    $modalInstance.dismiss('cancel');
                };
            },
            resolve: {
                account: function () {
                    return account;
                }
            }
        });

        modalInstance.result.then(function (asset) {
            $scope.getAll(1, 100);
        }, function () {
            console.log('Modal dismissed at: ' + new Date());
        });
    };

the test

describe("confirmDelete() function", function () {
        var controller, scope;

        // sets scope of controller before each test
        beforeEach(inject(function ($rootScope, _$modal_) {
            scope = $rootScope.$new();
            controller = $controller('AccountsController',
                {
                    $scope: scope,
                    $stateParams: mockStateParams,
                    $state: mockState,
                    // below: in order to call the $modal have it be defined and send on the mock modal? 
                    $modal: _$modal_, 
                    //modalInstance: mockModalInstance,
                    global: mockGlobal,
                    accountService: mockAccountSrv
                });
        }));

        beforeEach(inject(function ($modal) {
            spyOn($modal, 'open');
            spyOn(scope.modalInstance, "account");
        }));

        it("make sure modal promise resolves", function () {
            scope.confirmDelete(mockAccountSrv.account);
            expect($modal.open).toHaveBeenCalled();
        });

    });

Upvotes: 0

Views: 986

Answers (1)

fracz
fracz

Reputation: 21249

The problem is that in the second beforeEach you are trying to spy on scope.modalInstance and such field does not exist. Thus, Jasmine cannot find object to spy upon.

Another problem is that you use the result promise of the modal so you have tell your mock to return it in order not to get TypeError.

beforeEach(inject(function ($modal, $q) {
    spyOn($modal, 'open').and.returnValue({
        result: $q.defer().promise
    });
)

Next step will be to return a promise that you can resolve in unit test so you can verify correct behavior when it is resolved or rejected. You can simulate modal window closing that way.

Read more about spies in the Jasmine docs.

Also note that you don't have to inject modal service into controller (I mean the $modal: _$modal_ line). Services are singletons. When you spy on any instance of it, it will spy it everywhere.

Upvotes: 3

Related Questions