【问题标题】:How to test dynamically named inputs inside ng-repeat using $setViewValue()如何使用 $setViewValue() 在 ng-repeat 中测试动态命名的输入
【发布时间】:2013-11-25 15:25:01
【问题描述】:

我正在尝试测试一个使用 ng-repeat 将表单输入动态添加到页面的指令。该代码在浏览器中运行良好,但尝试使用 Jasmine 对其进行测试,我发现(对我而言)似乎是 Angular 中的一个错误或至少是奇怪的行为。

我希望能够在输入上设置视图值

form.questions.answer1.$setViewValue();

但是在我的测试中,当我控制台记录 form.questions 对象时,我得到了这个:

form.questions.answer{{ question.questionId }} 

即对象的索引没有被解析(虽然html输出正确)。

还有其他触发 ng-change 事件的方法吗?我尝试使用 jQuery(在我的测试中)设置输入的值,但是虽然它成功更改了值,但它不会触发 ng-change 事件。

plunker(检查控制台的内容以了解我的意思。)。

我的代码:

<!-- language: lang-js -->
app.directive('repeatedInputs', function(){
  var template ='<div  ng-form name="questions">'+
  '<div ng-repeat="(key, question) in questions" >' +                                                   
    '<span id="question{{ question.questionId }}">{{ question.questionText }}</span>'+
    '<span><input type="text" name="answer{{ question.questionId }}"' +
     ' id="answer{{question.questionId}}"' +                                                                  
    '  ng-model="question.answer" ng-change="change()"/></span>' +
  '</div>' +
  '</div>';

  return {                                                                                                                             
      template: template,
      scope: {
        answers: '=',
        singleAnswer: '='
      },

      /**                                                                                                                                
       * Links the directive to the view.                                                                                                
       *                                                                                                                                 
       * @param {object} scope                                                                                                           
       * Reference to the directive scope.                                                                                               
       *                                                                                                                                 
       * @param {object} elm                                                                                                             
       * Reference to the directive element.                                                                                             
       */                                                                                                                                
      link: function (scope, element) {                                                                                                  

        scope.questions = [
          {
            questionId: '1',
            questionText: 'What is your name?',
            answer: null
          },
          { 
            questionId: '2',
            questionText: 'What is your quest?',
            answer: null
          },
          { 
            questionId: '3',
            questionText: 'What is your favourite colour?',
            answer: null
          }
        ];

        scope.change = function () {
          for (var i in scope.questions) {
            scope.answers[i] = scope.questions[i].answer;
          }
        };
      }
   };
});

这是我的规范文件:

<!-- language: lang-js -->
describe('repeating inputs directive', function () {                           

  var element, scope, $compile;                                                                     

  beforeEach(function(){
    module('plunker');
    inject(function ($rootScope, _$compile_) {                   

      scope = $rootScope.$new();                                                  
      scope.theAnswers = [];
      scope.singleAnswer = null;

      element = angular.element(                                                  
        '<form name="form">'
        +'<div repeated-inputs answers="theAnswers" single-answer="singleAnswer">'
        +'</div></form>'                 
      );                                                                          
      $compile = _$compile_;
      $compile(element)(scope);
      scope.$apply();
    })
  });

  it('should store the input from the answers in the parent scope',             
      function () {                                                             

    // I want to do this
    //scope.form.questions.answer1.$setViewValue('Ben');

    // but inside the object, the answers name field is not being parsed
    // I am expecting the path to the answer to look like this:
    // scope.form.questions.answer1
    // instead it looks like this:
    // scope.form.questions.answer{{ question.questionId }}
    console.log(scope.form.questions);

    expect(scope.theAnswers[0]).toEqual('Ben');

  }); 
});  

【问题讨论】:

    标签: angularjs angularjs-directive jasmine angularjs-ng-repeat karma-runner


    【解决方案1】:

    所以我发现我正在尝试做的事情目前在 Angular 中是不可能的。对此进行测试的唯一方法是使用网络浏览器 - 我现在对这项功能进行了量角器测试。

    目前不支持插值名称(用于 ngModel)。

    【讨论】:

      【解决方案2】:

      你必须这样做:

      elementScope = $compile(element)(scope).isolateScope();
      ...
      expect(elementScope.theAnswers[0]).toEqual('Ben');
      

      由于以下原因将为指令创建一个隔离范围:

       scope: {
              answers: '=',
              singleAnswer: '='
            }
      

      【讨论】:

      • 问题实际上是不会触发更改事件,除非您在表单输入上使用“$setViewValue”。您可以直接在范围内设置值,但您无法使用单元测试来测试验证等内容,而无法以编程方式触发更改事件。
      猜你喜欢
      • 2016-04-16
      • 2020-06-29
      • 1970-01-01
      • 2012-08-16
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多