Установка значения представления в поле ввода в модульном тесте директивы угловой формы

У меня есть директива, которая создает форму:

app.directive('config', function() {
  return {
    restrict: 'E',
    scope: {
      data: '='
    },
    template: '<form name="configForm">' +
      '<input type="number" max="10" ng-model="config.item" name="configItem"/>' +
      '<div class="form-error" ng-show="configForm.$error.max">Error</div>' + 
      '</form>',
    controller: 'ConfigDirectiveController',
  };
});

Что я хочу сделать, так это проверить с помощью модульного теста, что сообщение об ошибке будет отображаться с учетом некоторого ввода. С angular 1.2 я мог бы изменить $scope.config.item, и он обновил бы значение представления и показал ошибку.

Насколько я могу судить, с angular 1.3, если модель не проходит проверку, значение представления не обновляется... поэтому мне нужно изменить значение представления, чтобы убедиться, что отображается сообщение об ошибке.

Как я могу получить доступ к вводу «configItem», чтобы я мог установить значение представления, чтобы убедиться, что сообщение об ошибке появится?

Отредактировано для отображения модульного теста

Я вижу, что значение установлено правильно, но к тегу по-прежнему применяется ng-hide. Когда я просматриваю страницу и вручную изменяю входное значение, ng-hide будет удален, и ошибка будет отображаться, если я введу что-то большее, чем 10.

  beforeEach(inject(function($compile, $rootScope) {
      element = angular.element('<config data="myData"></config>');
      $scope = $rootScope.$new();
      $scope.myData = {};
      element = $compile(element)($scope);
    }));

    it('should warn that we have a large number', function() {
      var input = element.find('[name="configItem"]')[0];
      $scope.$apply(function() {
        angular.element(input).val('9000000001');
      });
      errors = element.find('[class="form-error ng-binding"]');
      expect(errors.length).toBe(1);
    })

person nathasm    schedule 15.10.2014    source источник


Ответы (2)


Вот как я проводил модульное тестирование своих директив, основанных на вводе (большое количество кода опущено для ясности!) Важная строка, которую вы ищете:

angular.element(dirElementInput).val('Some text').trigger('input');

Вот полный модульный тест:

  it('Should show a red cross when invalid', function () {

    dirElement = angular.element('<ng-form name="dummyForm"><my-text-entry ng-model="name"></my-text-entry></ng-form>');

    compile(dirElement)(scope);
    scope.$digest();

    // Find the input control: 
    var dirElementInput = dirElement.find('input');

    // Set some text!
    angular.element(dirElementInput).val('Some text').trigger('input');
    scope.$apply();

    // Check the outcome is what you expect! (in my case, that a specific class has been applied)
    expect(dirElementInput.hasClass('ng-valid')).toEqual(true);
  });
person Ben Heymink    schedule 15.10.2014
comment
Я отмечу это как отвеченное, так как это на полпути. Он изменяет элемент ввода, но не запускает проверку. Скорее, это не приводит к тому, что configForm.$error.max помечается как истина... поэтому моя ошибка все еще скрыта. - person nathasm; 16.10.2014
comment
Это может быть связано с тем, что вы не используете скомпилированный вывод директивы. В ваших примерах вы перезаписываете ввод директивы скомпилированным выводом (элемент var), иногда нет (dirElement). Если вы используете скомпилированный результат, вы должны приблизиться к реальному поведению угловой формы. - person Zero Distraction; 14.01.2015
comment
обратите внимание, что в этом примере используется .trigger(), что предполагает, что вы используете Angular с jQuery. Если вы используете реализацию jqlite, вам нужно будет вручную отправить ошибку с чем-то вроде angular.element(dirEelementInput)[0].dispatchEvent(new Event('input'));. - person Matt Richards; 26.03.2015
comment
также может быть `scope.configForm.configItem.$setViewValue(какое-то значение, правда); область. $ применить(); ` обработчики запуска второго параметра - person VitVad; 01.06.2016
comment
также важно сделать scope.$apply()! - person drtf; 24.08.2017

Предыдущий ответ верен, если вы используете Angular с jQuery, но для Angular без jQuery (с использованием jqlite) вместо этого вы можете использовать triggerHandler (см. здесь полный API)

it('foos to the bar', function() {
  el.val('Foo').triggerHandler('input');

  // Assuming el is bound to scope.something using ng-model ...
  expect(scope.something).toBe('Foo');
});
person OrganicPanda    schedule 08.07.2015