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

标签 javascript angularjs unit-testing jasmine

我正在尝试对一个指令进行单元测试,该指令使用一些 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");
    });
  });
});

这是指令:

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

这是标记:

<div>
  {{dropDownField.name}}
  <select ng-model="dropDownResponses[dropDownField.name]" ng-options="value.key as value.value for value in dropDownField.values"></select>
</div>

最后一个 it block 是这里所关心的。当我触发 change 事件时,模型上的值总是比预期值高 1。例如,在这种情况下,存储在 scope.dropDownResponses 中的值最终为 2。

有什么想法吗?

最佳答案

快到这个问题的第一个生日了,我发现为什么测试没有通过很有趣。

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

expect(scope.dropDownResponses[scope.dropDownField.name]).toBe("1");

应该是

expect(scope.dropDownResponses[scope.dropDownField.name]).toBe("2");

原因是存储在 scope.dropDownResponses 中的值实际上是提问者发现的 2。

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

<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>

它反射(reflect)了规范中数组中的第二项

{
  "key": "2",
  "value": "GA",
  "select": "false"
},

您可以在这个 jsfiddle 中看到实际效果console.log输出的地方

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

selected before = 
(index):98 selected after = GA
(index):100 selected Text value = GA
(index):102 2

关于javascript - 如何在 Jasmine/Angularjs 中对下拉列表进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22157164/

相关文章:

javascript - windows.onload 和 setInterval 仍然需要手动刷新才能工作

javascript - web worker 会被浏览器悄悄杀死吗? (pdf.js 问题)

android - 如何在不影响长度较小的数据的情况下减少html css中冗长数据的宽度?

javascript - 访问 Angular 模板元素

javascript - 在流程 : how to stub a method in mocha? 中编写规范

mongodb - Spring boot 嵌入式 MongoDb 数据预填充

javascript - 付费 Chrome 扩展是否需要请求身份许可才能提供免费试用?

javascript - Bootstrap carousel slide 褪色+滑动

javascript - 在 Angular Service 中获取数据并将其传递给另一个 Controller

javascript - 如何在 Jasmine 中编写 FileReader 测试?