Polymer.js Web组件测试程序无法查找本地DOM元素

时间:2016-05-27 19:44:27

标签: javascript polymer polymer-1.0 web-component-tester

这是我的财产声明:

  properties: {

    size: {
      type: String,
      value: ''
    }, 

    sizeName: {
      type: String,
      value: ''
    }
  }

我的CSS:

<style>
  :root {
    --width: 20px;
    --height: 20px;
    --border-color: black;
    --font-size: 16px;
  }
  :host {
    display: inline-block;
    box-sizing: border-box;
    height: var(--height);
    width: var(--width);
  }
  #icon {
    position: relative;
    display: block;
    width: var(--width);
    height: var(--height);
    border-radius: 50%;
    border: 1px solid var(--border-color);
    font-size: var(--font-size);
    @apply(--size-icon);
  }
  #icon:before {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 100%;
    content: '?';
    text-align: center;
    @apply(--size-icon--before);
  }
  #icon.small:before {content: 's';}
  #icon.medium:before {content: 'm';}
  #icon.large:before {content: 'l';}

  #name {
    font-size: var(--font-size);
    @apply(--size-name);
  }

  .hidden {
    display: none;
  }
</style>

我有一个测试夹具如下:

<test-fixture id="hasWrongSize">
  <template>
    <size-icon size="asdf"></size-icon>
  </template>
  <template>
    <size-icon size=""></size-icon>
  </template>
</test-fixture>

使用如下测试套件:

  suite('when no icon size or incorrect icon size is provided', function() {
    var el;
    setup(function() {
      el = fixture('hasWrongSize');
    });
    test('when the "size" property is incorrect the inner html equals "?"', function(done) {
      flush(function() {
        var domEl = Polymer.dom(el.root).querySelector('#icon:before');
        expect(domEl.innerHTML).to.equal('?');
        done();
      });
    });
  });

自定义元素的Local DOM如下:

<template>
  <template is="dom-if" if="{{ !sizeName }}">
    <span id="icon" class$="{{size}}"></span>
  </template>
  <span id="name">{{ sizeName }}</span>
</template>

我正在尝试获取ID为:before的{​​{1}}伪元素,但WCT无法找到它,并且测试套件中的#icon等同于{{ 1}}。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

更新 问题已更新,其中包含test-fixture的完整代码,其中显示了根本原因。

正如你在自己的回答中所说:

  
      
  1. 我有两个模板标签,因此它不知道要定位哪个元素。
  2.   

仅此就是问题的原因,而伪元素实际上与它无关。您会发现,如果您从test-fixture中删除其中一个模板,那么您的原始代码就会起作用(并且会比您现在拥有的IMO更清晰)。

test-fixture应该只包含一个 template,并将自定义元素的固定状态作为测试的基线(最常见的分母)。在这种情况下,该基线是单个size-icon,但似乎您为每个可能的测试用例添加template,但该设置应该在测试脚本中真正发生,如下所示: / p>

<test-fixture id="basic">
  <template>
    <size-icon></size-icon>
  </template>
</test-fixture>

<script>
  suite('size-icon', function() {
    var el;

    setup(function() {
      el = fixture('basic');
    });

    function expectIconEquals(done, contents) {
      flush(function() {
        var domEl = Polymer.dom(el.root).querySelector('#icon');
        expect(domEl.innerHTML).to.equal(contents);
        done();
      });
    }

    test('when the "size" property is empty, the inner html equals "?"', function(done) {
      el.size = "";
      expectIconEquals(done, '?');
    });

    test('when the "size" property is invalid, the inner html equals "?"', function(done) {
      el.size = "asdf";
      expectIconEquals(done, '?');
    });

    test('when the "size" property is valid, the inner html equals "<some valid content>"', function(done) {
      el.size = "12%";
      expectIconEquals(done, '<some valid content>');
    });
  });
</script>

回答原始问题:

在您的代码中,span#icon元素仅在sizeName不是undefined时标记为空。绑定评估类似于that of computed bindings(即使未针对非计算绑定明确说明):

  

在定义所有相关属性(!=undefined)之前,不会调用计算函数。因此,每个依赖属性都应该具有在属性中定义的默认值(或者以其他方式初始化为非undefined值)以确保计算函数值。

要解决此问题,请在刷新模板之前将sizeName设置为测试中的空字符串。

suite('when no icon size or incorrect icon size is provided', function() {
  var el;
  setup(function() {
    el = fixture('hasWrongSize');
  });
  test('when the "size" property is incorrect the inner html equals "?"', function(done) {

    // #icon exists only when sizeName is empty string
    el.sizeName = "";

    flush(function() {
      var domEl = Polymer.dom(el.root).querySelector('#icon');
      expect(domEl).to.not.be.null;
      expect(domEl.innerHTML).to.equal('?');
      done();
    });
  });
});

或者,您可以在sizeName

中初始化dom-module
Polymer({
  is: 'size-icon',
  properties: {
    sizeName: {
      type: String,
      value: function() { return ""; }
    }
  }
});

答案 1 :(得分:0)

我解决了这个问题。我使用':before'元素来填充#icon范围的内容。在尝试选择它时,我遇到了两个问题:

  1. 我有两个模板标签,因此它不知道要定位哪个元素。
  2. 我错误地选择了一个伪元素。
  3. 以下是我用来正确选择和测试伪元素的content属性的代码。

      var getBeforeText = function(el) {
        return window.getComputedStyle(
          getIcon(el), ':before'
        ).getPropertyValue('content').replace(/"/g, "").replace(/'/g, "");
      };
    
      var getIcon = function(el) {
        return Polymer.dom(el.root).querySelector('#icon');
      };
    
      suite('when no icon size or incorrect icon size is provided', function() {
        var el;
        setup(function() {
          el = fixture('hasWrongSize');
        });
        test('when the "size" property is incorrect the inner html equals "?"', function(done) {
          flush(function() {
            expect(getBeforeText(el)).to.equal('?');
            done();
          });
        });
      });
    

    伪元素不能用普通JS直接选择,因为它们不是DOM的一部分。