测试自定义角度指令是不是显示/隐藏元素

Posted

技术标签:

【中文标题】测试自定义角度指令是不是显示/隐藏元素【英文标题】:Test if custom angular directive shows/hides element测试自定义角度指令是否显示/隐藏元素 【发布时间】:2015-07-02 03:18:48 【问题描述】:

我有一个自定义指令,它根据另一个服务的值显示/隐藏一个元素。我尝试创建一个测试,看看指令是否做了应该做的事情。一开始我再次测试了 ":visible" 选择器,但即使我知道元素实际上正在显示,它也总是返回 false。

it('Should show element if logged', function () 
    element = angular.element('<p hc-auth>Some Text</p>');
    AuthService.Logged = true;
    scope = $rootScope.$new();
    scope.$apply(function () 
        $compile(element)(scope);
    );
    expect(element.is(":visible")).toBeTruthy();
);

经过一些调试,我意识到在测试执行期间,即使将显示设置为阻塞,元素的宽度和高度也为 0,因此 ":visible" 选择器总是返回 false。我将其更改为检查显示选择器,现在它可以正确测试元素,但这似乎过于依赖于如何显示元素的实现。

it('Should show element if logged', function () 
    element = angular.element('<p hc-auth>Some Text</p>');
    AuthService.Logged = true;
    scope = $rootScope.$new();
    scope.$apply(function () 
        $compile(element)(scope);
    );
    expect(element.css('display')).toBe('block');
);

解决这种情况的最佳方法是什么?

【问题讨论】:

【参考方案1】:

你的问题让我想知道如何进行角度测试 ngHidengShow,这是他们规范文件中的一个 sn-p:

it('should show if the expression is a function with a no arguments', function() 
  element = jqLite('<div ng-show="exp"></div>');
  element = $compile(element)($scope);
  $scope.exp = function() ;
  $scope.$digest();
  expect(element).toBeShown();
);

看起来很整洁。起初我认为他们一定是在使用jquery-jasmine,它确实暴露了一个toBeHidden 匹配器(尽管事实证明不是toBeShown),实际上他们编写了自己的custom matcher 来确定可见性:

// [jtrussell] Custom Jasmine Matcher
toBeShown: function() 
  this.message = valueFn(
      "Expected element " + (this.isNot ? "" : "not ") + "to have 'ng-hide' class");
  return !isNgElementHidden(this.actual);


// [jtrussell] ...

// [jtrussell] The helper from elsewhere in same file
function isNgElementHidden(element) 
  // we need to check element.getAttribute for SVG nodes
  var hidden = true;
  forEach(angular.element(element), function(element) 
    if ((' '  + (element.getAttribute('class') || '') + ' ').indexOf(' ng-hide ') === -1) 
      hidden = false;
    
  );
  return hidden;

所以我猜他们有点作弊...检查.ng-hide 类的存在以确定可见性。但我想他们曾经站在你的立场上,并认为这是最好的路线,因为 angular 已经支持这个类名。

由于我们已经在使用 Angular,也许您可​​以考虑使用 .ng-hide 类来设置可见性并编写类似的帮助器。

编辑:

作为旁注,我会说添加/删除 .ng-hide 以设置可见性将有利于免费获得模块用户已经为该类设置的任何 ngAnimations。

【讨论】:

我会说这是正确的方法。从 Angular 1.2 开始,ngShowngHide 指令都应用 ng-hide 类,而不是将 display 属性更改为 noneblock。所以我认为在测试ngHidengShow 时检查该类是安全的。 是的,实际上我最终改变了我的实现以添加/删除 ng-hide 类并在测试中检查它,就像你说的那样,我想这是最好的方法。谢谢!【参考方案2】:

由于元素 可见 是一个加载项,而 :visible 不是真正的 CSS 选择器,因此没有灵丹妙药。

这里有一些可能性

    在 Jasmine 中使用 not

    expect(element.css('display')).not.toBe('hidden');

但这不包括元素显示但不可见的情况,因为它没有不透明度或位于另一个元素后面。

    获取元素的getBoundingClientRect()。然后检查每个角的document.elementFromPoint 是否没有返回您希望隐藏的元素。

【讨论】:

以上是关于测试自定义角度指令是不是显示/隐藏元素的主要内容,如果未能解决你的问题,请参考以下文章

Vue之自定义指令

Vue 自定义指令 - 对象属性未定义

(尚016)Vue指令(11个自带指令+自定义指令)

记录 vue自定义指令 实现展示搜索记录,点击其他区域隐藏

数字输入的角度自定义指令需要访问父反应表单 - FormGroup 和 FormContols

具有相同自定义指令 vuejs 的多个元素