I need to test the controller my directive is using. but could not reference the controller.
directive.js
(function () {
'use strict';
angular
.module('myModule')
.directive('cabinet', function () {
return {
restrict: 'E',
replace: true,
controller: CabinetThumbnails,
controllerAs: 'ctrl',
bindToController: true,
templateUrl: 'app/components/capture/cabinet.directive.html',
scope: {
thumbnail: '='
}
};
});
function CabinetThumbnails($uibModal, cabinetService, SweetAlert,
spinner, $state, $window) {
var vm = this;
vm.showImage = showImage;
vm.deleteThumbnail = deleteThumbnail;
function showImage() {
if (vm.thumbnail.FileCategoryName === 'OpenDocument') {
$window.open(vm.thumbnail.FileUrl);
}
else {
$uibModal.open({
animation: true,
templateUrl: 'app/components/capture/cabinet.pop-up.html',
controller: ModalCtrl,
controllerAs: 'ctrl',
size: 'lg',
resolve: {
thumbnailData: function () {
return vm.thumbnail;
}
}
});
}
}
function deleteThumbnail() {
//show the popup confirmation
SweetAlert.swal({
title: 'Are you sure to delete ?',
text: 'You will not be able to recover the file once deleted !',
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: 'Delete',
closeOnConfirm: true
},
function (isConfirm) {
if (isConfirm) {
spinner.show();
//call the service to delete here
cabinetService.deleteCabinetFile(vm.thumbnail.CabinetFileID)
.then(function (data) {
//validate the response
if (data != null && data.returnVal === -1) {
SweetAlert.swal('You do not have access to delete ' +
'the screen shot',
'Please contact the owner of the screen shot!',
'error');
} else {
//load all the Thumbnails by reloading the page
$state.reload();
}
})
.catch(function (err) {
SweetAlert.swal('Something went wrong !',
'Please try again later !', 'error');
})
.finally(spinner.hide);
}
});
}
}
function ModalCtrl($scope, $uibModalInstance, thumbnailData,
logger, cabinetService) {
var ctrl = this;
ctrl.thumbnailData = thumbnailData;
ctrl.save = save;
ctrl.cancel = cancel;
//call this method to get executed while the directive loads to open the pop-up
getComments();
function getComments() {
cabinetService
.getComments(thumbnailData)
.then(function (data) {
ctrl.comments = data;
})
.catch(function (err) {
logger.error('Unable to get comments, Please try later !',
{ttl: 20000});
});
}
}
}());
MytestSpec.js:
'use strict';
describe('cabinet', function () {
var el,
CabinetThumbnailsController,
scope;
beforeEach(bard.appModule('myModule', bard.fakeLogger));
// Initialize the controller and a mock scope
beforeEach(function () {
bard.inject('$controller', '$compile', '$rootScope', '$q', '$uibModal',
'cabinetService', 'SweetAlert', 'spinner', '$state',
'$window');
scope = $rootScope.$new();
el = angular.element('<div cabinet></div>', {$scope: scope});
$compile(el)(scope);
//CabinetThumbnailsController = el.controller('cabinet');
CabinetThumbnailsController = $controller('CabinetThumbnails', {$scope: scope});
$rootScope.$apply();
});
it('should be initialized', function () {
expect(el).toBeDefined();
});
//controller testing
it('CabinetThumbNails controller to be initialized', function () {
expect(CabinetThumbnailsController).toBeDefined();
});
it('CabinetThumbNails controller showImage method to be called', function () {
expect(CabinetThumbnailsController.showImage).toHaveBeenCalled();
});
});
both the following statements are not working
CabinetThumbnailsController = el.controller('cabinet');
CabinetThumbnailsController = $controller('CabinetThumbnails', {$scope: scope});
and hence calling the controller methods as follows is failing too:
expect(CabinetThumbnailsController.showImage).toHaveBeenCalled();
Separated my controller to a different file and tested the Controller independently. Couldn't get an approach to test the controller along with the directive.
Related
I have correctly setup my angular modal, now I want to pass my modal data back to my controller. I am using the below code.
First my controller calls my factory service that creates the modal popup:
$scope.mymodal = myService.openModal(data);
My service is as:
function openModal (data) {
var uData = null;
if (data) {
uData = {
userName : data.setName,
gender : data.gender
}
}
var modalInstance = $modal.open({
templateUrl: 'modal.html',
controller: 'ModalController',
backdrop: 'static',
keyboard: false,
resolve: {
data: function () {
return uData;
}
}
});
modalInstance.result.then(function () {
return;
}, function () {
});
return modalInstance;
}
See my jsfiddle here for this: http://jsfiddle.net/aman1981/z20yvbfx/17/
I want to pass name & gender that i select on my modal back to my controller, which then populates my page. Let me know what is missing here.
I updated AboutController, ModalController and myService with comments.
Main idea is return data from ModalController with close method. Fiddle
var app = angular.module('myApp', ['ui.router','ui.bootstrap']);
app.controller('IndexController', function($scope, $log) {
});
app.controller("AboutController", ['$location', '$state', '$scope', '$filter','myService', function($location, $state, $scope, $filter, myService) {
var data = "";
$scope.mymodal = myService.openModal(data);
// after modal is close, then this promise is resolve
$scope.mymodal.then(function(resp){
console.log(resp);
})
}]);
app.controller("ModalController", function($location, $state, $scope, $filter, $modalInstance) {
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
$state.go('index');
};
$scope.done = function () {
// return data on close modal instance
$modalInstance.close({genger:$scope.gender,userName:$scope.userName});
};
});
app.factory('ApiFactory', function ($http) {
var factory = {};
return factory;
});
app.factory("myService",[ "$state", "$modal", "ApiFactory",
function ($state, $modal, factory) {
var service = {
openModal: openModal
};
function openModal (data) {
var uData = null;
if (data) {
uData = {
userName : data.setName,
gender : data.gender
}
}
var modalInstance = $modal.open({
templateUrl: 'modal.html',
controller: 'ModalController',
backdrop: 'static',
keyboard: false,
resolve: {
data: function () {
return uData;
}
}
});
// on close, return resp from modal
modalInstance.result.then(function (resp) {
return resp;
}, function () {
});
// return modal instance promise
return modalInstance.result;
}
return service;
}
]);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/index');
$stateProvider
.state('index', {
url: '^/index',
templateUrl: 'index.html',
controller: "IndexController"
})
.state('about', {
url: '^/about',
templateUrl: 'about.html',
controller: "AboutController"
})
}]);
In my controller there is a function ......
function showDesktopPreview() {
var self = this;
this.$uibModal.open({
templateUrl: 'app/templates/modals/desktopPreview/template.desktopPreview.html',
controller: 'TemplateDesktopPreviewModalController',
controllerAs: 'vm',
size: 'xl',
resolve: {
previewUrl: function previewUrl() {
return self.getFrameUrl();
}
}
});
}
}
Now I write down the Karma test script as below ....
describe('When calling the showDesktopPreview function', () => {
let modalOptions;
let previewUrl;
beforeEach(() => {
TemplatesCreateController = createController();
//previewUrl = TemplatesCreateController.getFrameUrl();
modalOptions = {
templateUrl: 'app/templates/modals/desktopPreview/template.desktopPreview.html',
controller: 'TemplateDesktopPreviewModalController',
controllerAs: 'vm',
size: 'x1',
resolve: {
previewUrl: (value) => {
return value() === TemplatesCreateController.previewUrl();
}
}
};
console.log(modalOptions.resolve.previewUrl);
TemplatesCreateController.showDesktopPreview();
});
it('should instantiate the $uibModal service ', () => {
expect(TemplatesCreateController.$uibModal).to.not.be.an('undefined');
});
it('should call $uibModal.open with correct params', () => {
scope.$apply();
expect(TemplatesCreateController.$uibModal.open).to.have
.been.called
.and.be.calledWithMatch({modalOptions});
});
});
This is giving error as
assertionError: expected open to have been called with arguments matching
Please help me to resolve this issue.
I'm using angular-ui-bootstrap in my project and working with bootstrap modal. But I'm having a problem with my modal when I submit I can't call to scope and I got a error "$scope.testAlert is not a function"
controller:
$scope.open = function () {
$uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'userModal.html',
controller: function ($scope, $uibModalInstance, user) {
$scope.user = user;
$scope.save = function () {
var editUser = userService.updateUser($scope.user);
editUser.then(function () {
getAllUsers();
$scope.testAlert();
})
$uibModalInstance.close();
}
},
resolve: {
user: function () {
return $scope.user;
}
}
});
}
$scope.testAlert = function () {
alert("Blah blah");
}
$scope.testAlert is on the $scope of the main controller rather than the modal controller. You need to move it like this:
$scope.open = function() {
$uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'userModal.html',
controller: function($scope, $uibModalInstance, user) {
$scope.user = user;
$scope.save = function() {
var editUser = userService.updateUser($scope.user);
editUser.then(function() {
getAllUsers();
$scope.testAlert();
})
$uibModalInstance.close();
$scope.testAlert = function() {
alert("Blah blah");
}
}
},
resolve: {
user: function() {
return $scope.user;
}
}
});
}
The docs for the $modal service say
The scope associated with modal's content is augmented with 2 methods:
-$close(result)
-$dismiss(reason)
Those methods make it easy to close a modal window without a need to create a dedicated controller.
I'm wondering how to access this scope without creating a dedicated controller.
Try this:
$scope.openModal=function(){
$scope.modalInstance=$modal.open({
templateUrl: 'xyz.html',
scope:$scope
});
}
$scope.close=function(){
$scope.modalInstance.dismiss();
};
now you can use ng-click="close()" in your temnplate file.
ı used this code.
module.service('ModalService', function ($modal) {
var modalOptions = {
backdrop: true,
keyboard: true,
modalFade: true,
templateUrl: null
};
this.show = function (customModalDefaults) {
var tempModalOptions = {};
angular.extend(tempModalOptions, modalOptions, customModalDefaults);
if (!tempModalOptions.controller) {
tempModalOptions.controller = function ($scope, $modalInstance) {
$scope.modalOptions.ok = function (result) {
$modalInstance.close(result);
};
$scope.modalOptions.close = function (result) {
$modalInstance.dismiss('cancel');
};
};
}
return $modal.open(tempModalOptions).result;
};
});
call:
var modalOptions = {
backdrop: true,
modal: true,
size: scope.options.size || 'lg',
templateUrl: '/Apps/inekle/views/common/include_modal.html?v=1',
controller: [
"$scope", "$modalInstance", function ($scope, $modalInstance) {
$scope.model = {
template: scope.options.template,
title: scope.options.title
};
$scope.close = function () {
$modalInstance.dismiss('close');
};
}
]
};
ModalService.show(this.options).then(function (model) {},function (error) { });
I have this service:
angular.module('taskModule').service('myService', ['$modal', '$q', myService]);
function myService($modal, $q) {
this.displayModal = function(data) {
return $q(function(resolve, reject) {
$modal.open({
templateUrl: 'taskModule/taskModule/modal.tpl.html',
controller: function() {
this.datas = data;
this.buttonAction = function(id) {
console.log(id);
};
},
controllerAs: 'myCtrl'
});
});
};
}
What should I add to this code to see in console
You clicked the button ok
OR
You clicked the button Cancel
When I call this modal with this code:
myService.displayModal({
title: "This is a modal window",
message: "Please click a button.",
buttons: [{
id: 'ok',
label: 'OK'
}, {
id: 'cancel',
label: 'Cancel'
}, ]
}).then(function(buttonId) {
console.log('You clicked the button', buttonId);
});
Maybe I should use $q.defer(); but I'm novice in AngularJS.
The $modal.open function returns a modal instance which already has a promise that resolves/rejects when the modal is closed/dismissed, so you can just return that promise instead of creating a new one.
To return a value with a promise, you can call close/dismiss with that value - updated below.
function myService($modal, $q) {
this.displayModal = function(data) {
var modalInstance = $modal.open({
templateUrl: 'taskModule/taskModule/modal.tpl.html',
controller: function() {
this.datas = data;
this.buttonAction = function(id) {
console.log(id);
modalInstance.close(id);
};
},
controllerAs: 'myCtrl'
});
return modalInstance.result;
};
}