如何在Jasmine/Angularjs中对下拉列表进行单元测试

Dan*_*ane 8 javascript unit-testing jasmine angularjs

我正在尝试单元测试一个指令,该指令使用一些JSON来生成下拉列表以指定列表的详细信息.该指令工作正常,但我在尝试对其进行单元测试时遇到问题.

这是测试:

/* global inject, expect, angular */

define(function(require){
  'use strict';
  require('angular');
  require('angularMock');
  require('reporting/js/directives/app.directives');
  require('reporting/js/directives/drop.down.field.directive');

  describe("drop down field", function() {
    // debugger;
    var directive, scope;
    beforeEach(module('app.directives'));
    beforeEach(inject(function($compile, $rootScope) {
      scope = $rootScope;

      scope.dropDownResponses = {};
      scope.dropDownField = {
        "name": "Test Drop Down",
        "type": "dropdown",
        "hidden": "false",
        "defaultValue": "None",
        "values": [
          {
            "key": "1",
            "value": "FL",
            "select": "true"
          },
          {
            "key": "2",
            "value": "GA",
            "select": "false"
          },
          {
            "key": "3",
            "value": "TX",
            "select": "false"
          }
        ],
        "validation": null
      };
      directive = angular.element('<div drop-down-field="dropDownField" drop-down-responses="dropDownResponses"></div>');
      $compile(directive)(scope);
      scope.$digest();
    }));
    it("should build three dropdown choices", function() {
      expect(directive.find('option').length).toBe(4);
    });
    it('should have one dropdown', function() {
      expect(directive.find("select").length).toBe(1);
    });
    it('should update the model when a new choice is selected', function() {
      angular.element(directive.find("select")[0]).val('1');
      angular.element(directive.find("select")[0]).change();
      expect(scope.dropDownResponses[scope.dropDownField.name]).toBe("1");
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

这是指令:

define(function(require) {
  'use strict';

  var module = require('reporting/js/directives/app.directives');
  var template = require('text!reporting/templates/drop.down.field.tpl');

  module.directive('dropDownField', function () {
    return {
      restrict: 'A',
      replace: true,
      template:template,
      scope: {
        dropDownField : "=",
        dropDownResponses : "="
      }
    };
  });

  return module;
});
Run Code Online (Sandbox Code Playgroud)

这是标记:

<div>
  {{dropDownField.name}}
  <select ng-model="dropDownResponses[dropDownField.name]" ng-options="value.key as value.value for value in dropDownField.values"></select>
</div>
Run Code Online (Sandbox Code Playgroud)

最后一块是这里关注的问题.当我触发更改事件时,模型上的值总是比预期的更多.例如,在这种情况下,scope.dropDownResponses中存储的值最终为2.

有任何想法吗?

Nic*_*ray 5

它迎来了这个问题的第一个生日,我发现它为什么测试没有通过是有趣的.

我得出结论,测试的前提是错误的测试

expect(scope.dropDownResponses[scope.dropDownField.name]).toBe("1");
Run Code Online (Sandbox Code Playgroud)

应该

expect(scope.dropDownResponses[scope.dropDownField.name]).toBe("2");
Run Code Online (Sandbox Code Playgroud)

这样做的原因是,在提问者找到的范围内,存储在scope.dropDownResponses中的值实际上是2.

当您通过val('1')选择时,您正在select元素中选择第二个选项

<select ng-model="dropDownResponses[dropDownField.name]" ng-options="value.key as value.value for value in dropDownField.values" class="ng-valid ng-dirty">
  <option value="0" selected="selected">FL</option>
  <option value="1">GA</option>
  <option value="2">TX</option>
</select>
Run Code Online (Sandbox Code Playgroud)

这反映了规范中数组中的第二项

{
  "key": "2",
  "value": "GA",
  "select": "false"
},
Run Code Online (Sandbox Code Playgroud)

你可以在这个控制台.log输出的jsfiddle中看到这个

it('should update the model when a new choice is selected', function() {
  console.log(angular.element(directive.find("select")));
  console.log('selected before = ' + angular.element(directive.find("select option:selected")).text());
  angular.element(directive.find("select")[0]).val(1);
  console.log('selected after = ' + angular.element(directive.find("select option:selected")).text());
  angular.element(directive.find("select")[0]).change();
  console.log('selected Text value = ' + angular.element(directive.find("select option:selected")).text());
  expect(scope.dropDownResponses[scope.dropDownField.name]).toBe("2");
  console.log(scope.dropDownResponses[scope.dropDownField.name]);
  //console.log('selectedIndex=' + angular.element(directive.find("select")).selectIndex());
  console.log(angular.element(directive.find("select"))[0]);
});
Run Code Online (Sandbox Code Playgroud)

selected before = 
(index):98 selected after = GA
(index):100 selected Text value = GA
(index):102 2
Run Code Online (Sandbox Code Playgroud)