Reputation: 1093
I am about to give up on this. I have tried every which way to access the directive scope in a test.
'use strict';
angular.module('cmsModuleApp')
.directive('fileUpload', function () {
return {
scope: {},
template: '<input type="file" >',
restrict: 'E',
controller: function fileUploadCtrl (scope) {
//also tried scope.uploadFile here...
this.uploadFile = function (files) {console.log("please work...")};
},
link: function postLink(scope, element, attrs, Ctrl) {
element.uploadFile = function (files) {console.log("pleaseeeee")};
}
};
});
test::
'use strict';
describe('Directive: fileUpload', function () {
beforeEach(module('cmsModuleApp'));
var element;
var scope;
var files;
beforeEach(inject(function ($rootScope) {
scope = $rootScope.$new();
}));
it('should call a file upload method onchange event', inject(function ($compile) {
element = angular.element('<file-upload></file-upload>');
element = $compile(element)(scope);
//tried moving this around thinking maybe it had to render or update
scope.$digest();
//Im loggin the element's scope to explore the object a bit
console.log(element.scope());
spyOn(element.scope(), 'uploadFile')
element.triggerHandler('onchange');
expect(element.scope().uploadFile()).toHaveBeenCalled();
}));
});
What I am trying to test is that when this file input changes (is clicked and loaded up with files) it will execute the uploadFile()
method on the directive's scope. Once I get this working I was going to implement an $http
service.
However, the method does not exist or is undefined.. No matter what I seem to try.
Upvotes: 0
Views: 2922
Reputation: 3005
I think the issue might be that you are using an isolate scope scope: {}
. Here's an example of how I did a similar task:
describe('File Input Directive', function() {
var scope, element, isolateScope;
beforeEach(function() {
bard.appModule('appName');
bard.inject(this, '$compile', '$rootScope');
scope = $rootScope.$new();
var html = '<form><my-file-input /></form>';
var form = angular.element(html);
element = form.find('my-file-input');
var formElement = $compile(form)(scope);
scope.$digest();
isolateScope = element.isolateScope();
});
afterEach(function() {
scope.$destroy();
});
bard.verifyNoOutstandingHttpRequests();
describe('selectFile', function() {
it('triggers a click on the file input', function() {
var fileInput = $(element).find('.none')[0];
var mockClick = sinon.spy(fileInput, 'click');
isolateScope.selectFile();
scope.$digest();
expect(mockClick).calledOnce;
});
});
You can ignore all of the bard references - it's a helper library, which reduces some boilerplate. The important parts are creating the isolateScope
in the beforeEach
and referencing the directive's method (in this case, selectFile) on the isolateScope
in the test itself. Also, notice the scope.$digest()
after calling the method. Hope it helps!
Upvotes: 0
Reputation: 8167
Could you try to modify your test file like this?
I moved the variables declaration into the describe
and the test initilization into the beforeEach
. Then I created a spy on scope.uploadFile
.
fileUpload_test :
'use strict';
describe('Directive: fileUpload', function () {
var element;
var scope;
var files;
beforeEach(module('cmsModuleApp'));
beforeEach(inject(function ($rootScope) {
scope = $rootScope.$new();
element = angular.element('<file-upload></file-upload>');
element = $compile(element)(scope);
scope.$digest();
}));
afterEach(function() {
scope.$destroy();
});
it('should call a file upload method onchange event', function() {
scope.uploadFile = jasmine.createSpy();
element.triggerHandler('change');
expect(scope.uploadFile).toHaveBeenCalled();
}));
});
Upvotes: 1