Polymer.js Web组件测试程序未能找到本地DOM元素



这是我的属性声明:

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

自定义元素的本地DOM如下所示:

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

我试图获得ID为#icon:before伪元素,但WCT找不到它,并且测试套件中的domEl等于null

我做错了什么?

UPDATE 问题已更新为包含test-fixture的完整代码,从而揭示了根本原因

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

  1. 我有两个模板标记,所以它不知道要针对哪个元素

这就是问题的原因,而伪元素实际上与此无关。你会发现,如果你从test-fixture中删除其中一个模板,你的原始代码就会工作(并且会比现在的IMO更干净)。

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

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

原始问题的答案:

在代码中,只有当sizeName不是undefined并且为空时,才会对span#icon元素进行标记。绑定评估与计算绑定的评估类似(尽管对于非计算绑定没有明确说明):

在定义所有相关属性之前,不会调用计算函数(!=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();
});
});
});

或者,您可以在dom-module:中初始化sizeName

Polymer({
is: 'size-icon',
properties: {
sizeName: {
type: String,
value: function() { return ""; }
}
}
});

我解决了这个问题。我使用了一个":before"元素来填充#icon跨度的内容。当尝试选择它时,我遇到了两个问题:

  1. 我有两个模板标签,所以它不知道要针对哪个元素
  2. 我错误地选择了一个伪元素

这是我用来正确选择和测试伪元素的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的一部分。

最新更新