如何使用文件上传和onchange事件测试Angular JS指令

时间:2014-02-14 09:44:58

标签: javascript angularjs karma-runner directive

我即将放弃这一点。我已经尝试了在测试中访问指令范围的每种方法。

'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")};
      }
    };
  });

试验:

'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();

  }));
});

我要测试的是,当此文件输入发生更改(单击并加载文件)时,它将在指令的作用域上执行uploadFile()方法。一旦我开始工作,我将实施$http服务。

然而,该方法不存在或未定义。无论我似乎尝试。

2 个答案:

答案 0 :(得分:1)

您可以尝试像这样修改测试文件吗?

我将变量声明移动到describe并将测试初始化​​移动到beforeEach。然后我在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();
  }));
});

答案 1 :(得分:0)

我认为问题可能是您使用隔离范围scope: {}。以下是我如何执行类似任务的示例:

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;
    });
  });

你可以忽略所有的bard引用 - 它是一个帮助库,它减少了一些样板。重要的部分是在isolateScope中创建beforeEach并在测试本身的isolateScope上引用指令的方法(在本例中为selectFile)。另外,在调用方法后请注意scope.$digest()。希望它有所帮助!