从innerHTML过滤HTML注释节点

时间:2014-01-04 11:17:08

标签: javascript html angularjs selenium

我想知道是否有办法过滤DOM的innerHTML只包含实际的HTML并丢弃所有注释节点?


实际上,我正在使用Angularjs并使用Selenium编写一些测试。 Angular在渲染的HTML中包含大量注释,例如:

<!-- ngSwitchWhen: join -->
<div data-ng-switch-when="leave">
  <!-- ngIf: isNow -->
  .
  .
  .
</div>

我目前正在尝试匹配结果:@client是WebDriver实例。

@client.findElement(By.xpath("//*[@id='log']/li")).getAttribute('innerHTML').then (innerHtml) ->
      html = innerHtml.trim()
      expect(html).to.equal """
        <div class="image"><i class="icon-refresh"></i></div>
        <div class="fade-6 content">Getting more activities...</div>
      """

当我尝试使用Mocha测试返回的DOM结构时,这会产生一个大问题。我该测试什么?我不可能在我的期望值中重复所有无用的评论,这将非常浪费。

有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

编写依赖innerHTML的测试根本不是一个好主意。

当您获取innerHTML时,浏览器会将DOM中的信息序列化为新的标记字符串,该字符串不一定与最初解析为制作DOM的标记相同。

标记详细信息,例如:

  • 中的订单属性
  • 是什么案例标签
  • 标签中有哪些空格
  • 用于分隔属性值的引号
  • 将哪些内容字符编码为实体或字符引用

未存储在DOM信息集中,因此不会保留。不同的浏览器可以并将产生不同的输出。在某些情况下,IE甚至会返回无效的标记,或者在解析时不会往返于同一信息集的标记。

+1 katspaugh的回答演示了如何从DOM中获取信息而不是依赖innerHTML,从而避免了这个问题。

但是,更一般地说,编写严格依赖于应用程序使用的确切标记的测试通常是个坏主意。这是测试要求与实现细节之间过于紧密的耦合。即使是琐碎的风格原因或文本更新,您对标记所做的任何微小更改都意味着您必须更新所有测试才能匹配。测试是一个有用的工具,可以捕捉你不想破坏的东西;每次更改时总会中断的测试都没有给出关于您是否破坏某些内容的反馈,因此无用。

虽然通常没有完全将测试与应用程序标记分开的灵丹妙药,但通常您应该将测试降低到满足用户要求的最小值,并添加信号以捕获这些情况。我不知道你的应用程序究竟在做什么,但我猜这个要求是这样的:“当用户点击'more'按钮时,一个忙碌的微调器应该让他们知道正在获取信息”。< / p>

为了对此进行测试,您可以进行检查,例如“具有id'log'的元素是否包含具有类'icon-refresh'的元素?”。如果你想更具体地说它是一个微调器来处理提取活动,你可以在“获取更多活动......”div中添加类似“refresh-activities”的类,并检测该类的元素而不是依赖在可能会改变的文本上(特别是如果你翻译你的应用程序)。

答案 1 :(得分:2)

注释节点是DOM节点,如您所知。您可以迭代所有节点并按其node type

过滤注释
recursivelyIterate(container, function (subNode) {
    if (subNode.nodeType == Node.COMMENT_NODE) {
        subNode.parentNode.removeChild(subNode);
    }
});

(我还没有包含recursivelyIterate函数的代码,但写一个代码应该是微不足道的。)


或者,留下他们的评论并且不使用DOM节点,使用DOM元素。 getElementsByTagNamequerySelectorAll和朋友。