我正在创建一个名为“价格文本”的聚合物元素,它显示货币价值和一些与之相关的文本。当“交换”属性存在时,我还添加了反转它们的位置的能力。尽管能够在浏览器演示中成功使用 swap 属性来反转跨度的顺序(内部显示“价格文本”)。
我只能在 wct 打开浏览器运行测试时观察到错误。这是我在浏览器中看到的错误:
Error: the string "console.error:Error stamping [object HTMLUnknownElement] TypeError: Unable to get property 'parentNode' of undefined or null reference" was thrown, throw an Error :)
在 wct 完成所有的任务后,它仍然会向终端返回“Tests Passed”。
我已经确定setup函数会运行,只要调用test函数就会出现错误。为了重申我的目标,我希望能够使用 wct 在这个套件中通过两个简单的“预期”测试,其中跨度改变位置。
这是测试夹具。
<test-fixture id="price-text-swapd">
<template>
<price-text price="6.99" text="meal" swap></price-text>
</template>
</test-fixture>
这是与此测试夹具关联的脚本。
suite('price and text are swapd', function() {
var el;
var priceTextLineEl;
setup(function() {
el = fixture('price-text-swapd');
priceTextLineEl = Polymer.dom(el.root).querySelector("#price-text-line");
});
test('defines the swap property', function(done) {
flush(function() {
expect(el.swap).to.be.a('boolean');
expect(el.swap).to.equal(true);
done();
});
});
});
这是价格文本元素。
<span id="price-text-line">
<span id="price" class="left border">{{_formattedPrice}}</span><span id="text" class="right">{{_formattedText}}</span>
</span>
这是控制影子 DOM 中跨度的函数
_swapPriceText: function() {
var textEl = document.getElementById("text");
var priceEl = document.getElementById("price")
if (this.swap) {
textEl.parentNode.insertBefore(textEl, textEl.parentNode.firstChild);
textEl.classList.add("left");
textEl.classList.remove("right");
priceEl.classList.add("right");
priceEl.classList.remove("left");
}
}
我已在以下片段中完整地发布了测试和元素文件。
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../polymer/polymer.html">
<!--
Variable price and text sparated by a border.
Example:
<price-text price="6.99" text="meal"></price-text>
@demo demo/index.html
@hero hero.svg
-->
<dom-module id="price-text">
<template>
<style>
:root {
--font-family: 'Helvetica', arial;
--font-size: 32px;
--text-font-size: 21px;
--price-padding-left: 0;
--price-padding-right: 4px;
--price-border-right: 1px solid #000;
--price-border-left: 1px solid #000;
--text-padding-left: 8px;
--text-padding-right: 0;
}
:host {
display: inline-block;
box-sizing: border-box;
}
#price-text-line {
font-family: var(--font-family);
@apply(--price-text-line);
}
#price {
display: inline-block;
font-size: var(--font-size);
@apply(--price-text-line--price);
}
#text {
display: inline-block;
font-size: var(--text-font-size);
@apply(--price-text-line--text);
}
.left {
padding-left: var(--price-padding-left);
padding-right: var(--price-padding-right);;
@apply(--price-text-line--left);
}
.right {
padding-left: var(--text-padding-left);
padding-right: var(--text-padding-right);
@apply(--price-text-line--right);
}
.border.right {
border-left: var(--price-border-right);
}
.border.left {
border-right: var(--price-border-left);
}
</style>
<span id="price-text-line">
<span id="price" class="left border">{{_formattedPrice}}</span><span id="text" class="right">{{_formattedText}}</span>
</span>
</template>
<script>
Polymer({
is: 'price-text',
properties: {
/**
* `price` accepts input in the form of numbers and passes the data to the `formatCurrency()` method.
*
* @type {{price: Number}}
*/
price: {
type: Number,
value: 0,
observer: '_formatCurrency'
},
/**
* `formattedPrice` accepts formatted data from the `formatCurrency()` method to be displayed in .price.
*
* @type {{formattedPrice: String}}
*/
_formattedPrice: {
type: String,
value: ""
},
/**
* `text` accepts input in the form of strings and passes the data to the `formatText()` method.
*
* @type {{text: String}}
*/
text: {
type: String,
value: "",
observer: '_formatText'
},
/**
* formattedText accepts formatted data from the `formatText()` method to be displayed in .text.
*
* @type {{formattedText: String}}
*/
_formattedText: {
type: String,
value: ""
},
swap: {
type: Boolean,
observer: '_swapPriceText'
}
},
/**
* `formatCurrency()` accepts data from `price`, checks to see if it is a number greater than zero, rounds the number to two decimal places, and passes the data to `formattedPrice`. If the data is not a number it will set `formattedCurrency` to an empty string.
*
*/
_formatCurrency: function() {
if (this.price > 0) {
this._formattedPrice = '$' + (this.price).toFixed(2);
} else {
this._formattedPrice = '';
}
},
/**
*`formatText()` accepts data from `text`, checks to see if it is not a number, and passes the data to `formattedText`. If the data is a number, it will set `formattedText` to an empty string.
*
*/
_formatText: function() {
if (isNaN(this.text)) {
this._formattedText = this.text;
} else {
this._formattedText = '';
}
},
/**
*`swapPriceText` swaps the position of the spans containing the `price` and `text` data.
*
*/
_swapPriceText: function() {
var textEl = document.getElementById("text");
var priceEl = document.getElementById("price")
if (this.swap) {
textEl.parentNode.insertBefore(textEl, textEl.parentNode.firstChild);
textEl.classList.add("left");
textEl.classList.remove("right");
priceEl.classList.add("right");
priceEl.classList.remove("left");
} else {
priceEl.parentNode.insertBefore(priceEl, priceEl.parentNode.firstChild);
textEl.classList.add("right");
textEl.classList.remove("left");
priceEl.classList.add("left");
priceEl.classList.remove("right");
}
}
});
</script>
</dom-module>
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../web-component-tester/browser.js"></script>
<!-- Step 1: import the element to test -->
<link rel="import" href="../price-text.html">
</head>
<body>
<!-- You can use the document as a place to set up your fixtures. -->
<test-fixture id="has-price-and-text">
<template>
<price-text price="6.99" text="meals"></price-text>
</template>
</test-fixture>
<test-fixture id="has-price-not-text">
<template>
<price-text price="42.42"></price-text>
</template>
</test-fixture>
<test-fixture id="has-text-not-price">
<template>
<price-text text="sandwich"></price-text>
</template>
</test-fixture>
<test-fixture id="has-wrong-price-data">
<template>
<price-text price="shake" text="fries"></price-text>
</template>
</test-fixture>
<test-fixture id="has-wrong-text-data">
<template>
<price-text price="42.00" text="0.42"></price-text>
</template>
</test-fixture>
<test-fixture id="price-text-undefined">
<template>
<price-text></price-text>
</template>
</test-fixture>
<test-fixture id="price-text-swapd">
<template>
<price-text price="6.99" text="meal" swap></price-text>
</template>
</test-fixture>
<script>
suite('define price and text', function() {
var el;
var priceEl;
var textEl;
setup(function() {
el = fixture('has-price-and-text');
priceEl = Polymer.dom(el.root).querySelector('#price');
textEl = Polymer.dom(el.root).querySelector('#text')
});
test('defines the price property', function() {
expect(el.price).to.be.a('number');
expect(el.price).to.equal(6.99);
});
test('defines the text properly', function() {
expect(el.text).to.be.a('string');
expect(el.text).to.equal('meals');
});
test('is price displaying properly', function() {
expect(priceEl.innerHTML).to.equal('$6.99');
});
test('is text displaying properly', function() {
expect(textEl.innerHTML).to.equal('meals')
});
});
suite('define price but not text', function() {
var el;
var priceEl;
var textEl;
setup(function() {
el = fixture('has-price-not-text');
priceEl = Polymer.dom(el.root).querySelector('#price');
textEl = Polymer.dom(el.root).querySelector('#text');
});
test('defines the price property', function() {
expect(el.price).to.be.a('number');
expect(el.price).to.equal(42.42);
});
test('defines the text property', function() {
expect(el.text).to.be.a('string');
expect(el.text).to.equal('');
});
test('is price displaying properly', function() {
expect(priceEl.innerHTML).to.equal('$42.42');
});
test('is text displaying properly', function() {
expect(textEl.innerHTML).to.equal('')
});
});
suite('price data is wrong', function() {
var el;
var priceEl;
var textEl;
setup(function() {
el = fixture('has-wrong-price-data');
priceEl = Polymer.dom(el.root).querySelector('#price');
textEl = Polymer.dom(el.root).querySelector('#text');
});
test('defines the price property', function() {
expect(el.price).to.be.a('number');
expect(isNaN(el.price)).to.be.ok;
});
test('defines the text property', function() {
expect(el.text).to.be.a('string');
expect(el.text).to.equal('fries');
});
test('is price displaying properly', function() {
expect(priceEl.innerHTML).to.equal('');
});
test('is text displaying properly', function() {
expect(textEl.innerHTML).to.equal('fries')
});
});
suite('define text but not price', function() {
var el;
var priceEl;
var textEl;
setup(function() {
el = fixture('has-text-not-price');
priceEl = Polymer.dom(el.root).querySelector('#price');
textEl = Polymer.dom(el.root).querySelector('#text');
});
test('defines the price property', function() {
expect(el.price).to.be.a('number');
expect(el.price).to.equal(0);
});
test('defines the text property', function() {
expect(el.text).to.be.a('string');
expect(el.text).to.equal('sandwich');
});
test('is price displaying properly', function() {
expect(priceEl.innerHTML).to.equal('');
});
test('is text displaying properly', function() {
expect(textEl.innerHTML).to.equal('sandwich')
});
});
suite('text data is wrong', function() {
var el;
var priceEl;
var textEl;
setup(function() {
el = fixture('has-wrong-text-data');
priceEl = Polymer.dom(el.root).querySelector('#price');
textEl = Polymer.dom(el.root).querySelector('#text');
});
test('defines the price property', function() {
expect(el.price).to.be.a('number');
expect(el.price).to.equal(42.00);
});
test('defines the text property', function() {
expect(el.text).to.be.a('string');
expect(!isNaN(el.text)).to.be.ok;
});
test('is price displaying properly', function() {
expect(priceEl.innerHTML).to.equal('$42.00');
});
test('is text displaying properly', function() {
expect(textEl.innerHTML).to.equal('')
});
});
suite('price and text are not defined', function() {
var el;
var priceEl;
var textEl;
setup(function() {
el = fixture('price-text-undefined');
priceEl = Polymer.dom(el.root).querySelector('#price');
textEl = Polymer.dom(el.root).querySelector('#text');
});
test('defines the price property', function() {
expect(el.price).to.be.a('number');
expect(el.price).to.equal(0);
});
test('defines the text property', function() {
expect(el.text).to.be.a('string');
expect(el.text).to.equal('');
});
test('is price displaying properly', function() {
expect(priceEl.innerHTML).to.equal('');
});
test('is text displaying properly', function() {
expect(textEl.innerHTML).to.equal('')
});
});
suite('price and text are swapd', function() {
var el;
var priceTextLineEl;
setup(function() {
el = fixture('price-text-swapd');
priceTextLineEl = Polymer.dom(el.root).querySelector("#price-text-line");
});
/*
test('defines the swap, price, and text properties', function(done) {
flush(function() {
expect(el.swap).to.be.a('boolean');
expect(el.swap).to.equal(true);
expect(el.price).to.be.a('number');
expect(el.price).to.equal(6.99);
expect(el.text).to.be.a('string');
expect(el.text).to.equal('meal');
done();
});
});*/
/* test('is swap displaying properly', function() {
expect(priceTextLineEl.innerHTML).to.equal('<span id="text" class="right">meal</span><span id="price" class="left border">meal</span>');
});
*/
});
</script>
</body>
</html>