1

I have below code:

vm.data = [{name: 'test-1'},{name: 'test-2'}];

function addRecords(data) {
    vm.data.push(data);
}

function openPopup() {

    $uibModal.open({
        templateUrl: 'modal-popup/modal-popup.html',
        controller: 'ModalPopupController',
        controllerAs: 'vm',
        resolve: {
            id: _.constant('123')
        }
    }).result.then(addRecords);
}

Trying to mock this, Below are the declarations:

let allData = [{name: 'test-1'},{name: 'test-2'}];
let data = {name: 'test-3'};

    beforeEach(inject(function (_$q_, _$rootScope_, _$componentController_, _$uibModal_) {
        $q = _$q_;
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        controller = _$componentController_;
        $uibModal = _$uibModal_;

        spyOn($uibModal, 'open').and.returnValue({
            result: function() {
                return $q.when(data);
            }
        });

        vm = controller('bvcListings', {
            $q,
            data: allData,
            $uibModal
        });

        $scope.$apply();
    }));

    describe('openPopup', function () {
        it('should add records on modal results', function () {
            vm.openPopup();
            expect($uibModal.open).toHaveBeenCalled();
        });
    });

Expectation is, it should add: {name: 'test-3'} as result to existing array.

Spy on modal open is working fine, but after results fetched, its not entering addRecords function. What am i doing wrong?

What changes need to be done here to get inside callback function after results retrieved.

Kostas Siabanis
  • 2,989
  • 2
  • 20
  • 22
Mithun Shreevatsa
  • 3,588
  • 9
  • 50
  • 95

3 Answers3

2

.result.then callback method will get call only when you call modalInstance.close method, also don't forgot to pass data from close method something like modalInstance.close(data).

Before proceeding to test you need to do one change inside openPopup function. It should return $uibModal.open which basically returns newly created modal's instance. Thereafter you can easily have a control over modal to call dismiss/close method whenever needed.

function openPopup() {
    vm.modalInstance = $uibModal.open({
        templateUrl: 'modal-popup/modal-popup.html',
        controller: 'ModalPopupController',
        controllerAs: 'vm',
        resolve: {
            id: _.constant('123')
        }
    });

   vm.modalInstance.result.then(addRecords);
}

Spec

$uibModal = _$uibModal_;
var data = {name: 'test-3'};
//creating fake modal which will help you to mock 
var fakeModal = {
    result: {
        then: function(confirmCallback) {
            //Store the callbacks
            this.confirmCallBack = confirmCallback;
        }
    },
    close: function( item ) {
        //The user clicked OK on the modal dialog
        this.result.confirmCallBack( item );
    }
};
spyOn($uibModal, 'open').and.returnValue(fakeModal);

describe('It should data to vm.data when popup closed', function () {
    it('should add records on modal results', function () {
       vm.data = [{name: 'test-1'},{name: 'test-2'}];
       let data = {name: 'test-3'};
       vm.openPopup();
       expect($uibModal.open).toHaveBeenCalled();
       vm.modalInstance.close(data);
       expect(vm.data.length).toBe(4);
       expect(vm.data[3]).toBe(data);
    });
});

Note: fakeModal has been referred from this post

Mithun Shreevatsa
  • 3,588
  • 9
  • 50
  • 95
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
1

Continuing with @Pankajs answer.

Here is a tweak which i made and got that worked.

function openPopup() {
    vm.modalInstance = $uibModal.open({
        templateUrl: 'modal-popup/modal-popup.html',
        controller: 'ModalPopupController',
        controllerAs: 'vm',
        resolve: {
            id: _.constant('123')
        }
    }).result.then(addRecords);
}

Spec

describe('modalpopup', function () {
    it('should add records on modal results', function () {
        vm.data = [{name: 'test-1'},{name: 'test-2'}];
        let data = {name: 'test-3'};
        vm.openPopup();
        expect($uibModal.open).toHaveBeenCalled();
        vm.modalInstance.close(data);
        expect(vm.data.length).toBe(4);
        expect(vm.data[3]).toBe(data);
    });
});

Worked like charm for me. And i consier Pankajs answer as well which was almost 90% gave solution to my problem.

Mithun Shreevatsa
  • 3,588
  • 9
  • 50
  • 95
0

add $rootScope.$digest(); to resolve promises (like $q.when())

vm.openPopup();
expect($uibModal.open).toHaveBeenCalled();
$rootScope.$digest(); >> triggers your callback
Petr Averyanov
  • 9,327
  • 3
  • 20
  • 38