使用 wct 测试含铁-ajax 的聚合物 1.0 组件
Testing polymer 1.0 components with iron-ajax using wct
我在模拟服务器对我的自定义组件中的 iron-ajax 组件的响应时遇到了最困难的时刻。这是我的代码文件。
自定义-component.html:
<link rel="import" href="/iron-ajax/iron-ajax.html">
<link rel="import" href="/internal-component/internal-component.html">
<dom-module id="custom-component">
<template>
<iron-ajax url="staticFile.json" auto handle-as="json" last-response={{ajaxResponse}}></iron-ajax>
<template is="dom-repeat"
items={{ajaxResponse}}
sort="_sort"
id="gridRow">
<internal-component var1={{item.var1}}
var2={{item.var2}}>
</internal-component>
</template>
</template>
</dom-module>
<script>(some cool scripts that are working...)</script>
自定义组件-tests.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/web-component-tester/browser.js"></script>
<script src="/test-fixture/test-fixture-mocha.js"></script>
<link rel="import" href="/test-fixture/test-fixture.html" />
<link rel="import" href="/polymer/polymer.html">
<link rel="import" href="/polymer-ts/polymer-ts.html">
<link rel="import" href="custom-component.html">
</head>
<body>
<test-fixture id="testElement">
<template>
<custom-component></custom-component.>
</template>
</test-fixture>
<script>
suite('<custom-component>', function () {
var testElement;
var server;
var responseHeaders = {
json: { 'Content-Type': 'application/json' },
plain: { 'Content-Type': 'text/plain' }
};
setup(function () {
replace('custom-component').with('fake-custom-component');
server = sinon.fakeServer.create();
server.respondWith('GET', /staticFile\.json/, [
200,
responseHeaders.json,
'[{"var1": "9a","var2": "17n"}]'
]);
testElement = fixture("testElement");
});
teardown(function () {
server.restore();
});
suite('testSuite', function () {
test('test1', function () {
var ajax = testElement.getElementsByTagName('iron-ajax')[0];
ajax.lastResponse = null;
ajax.generateRequest();
server.respond();
assert(ajax.lastResponse.hour === "9a");
});
});
});
</script>
</body>
</html>
您会注意到我明确调用了 iron-ajax generateRequest,因为如果我不这样做,那么在我的测试完成(并失败)之前请求甚至不会发生。当显式调用 generateRequest 时,我至少能够使请求发生,但是(即使我正在调用 server.respond())iron-ajax 直到测试完成后才调用 _handleResponse。而且,即使它这样做了,它也没有设置 lastResponse 因为在 iron-ajax 中有一行代码检查是否 (request === this.lastRequest) (它不是)。
我做错了什么?
我想我需要睡个好觉。
我忘了考虑异步请求。我修改了代码以反映以下内容:
suite('<custom-component>', function () {
var testElement;
var server;
var responseHeaders = {
json: { 'Content-Type': 'application/json' },
plain: { 'Content-Type': 'text/plain' }
};
setup(function () {
replace('custom-component').with('fake-custom-component');
server = sinon.fakeServer.create();
server.respondWith('GET', /staticFile\.json/, [
200,
responseHeaders.json,
'[{"var1": "9a","var2": "17n"}]'
]);
testElement = fixture("testElement");
});
teardown(function () {
server.restore();
});
suite('testSuite', function () {
// note that I added the "done" as a parameter on my test function
test('test1', function (done) {
var ajax = testElement.getElementsByTagName('iron-ajax')[0];
ajax.generateRequest();
server.respond();
// note that I added an async event listener here, and moved my test inside.
ajax.addEventListener('response', function(e) {
assert(e.target.lastResponse.var1 === "9a");
done();
}
});
});
});
我现在能够正确拦截响应,并且测试大部分都按预期工作。我仍然有 iron-ajax 的 lastResponse 未设置的问题,但我认为这是另一个问题。
我找到了一个更好的解决方案来测试元素中 iron-ajax 元素的自动功能。
您需要根据 ajax 的请求添加一个事件侦听器来触发您的服务器响应,不需要 generateRequest 也不需要 setTimeout hacks。
这里有一个例子:
test('test with ajax element', function (done) {
var ajax = Polymer.dom(myElement.root).querySelector("#ajax_element");
ajax.addEventListener('request', function (e) {
server.respond('GET', '/CALLED_URL', dataResponse);
});
ajax.addEventListener('response', function (e) {
//DO YOUR EXPECTS HERE
done();
});
});
作为组件测试,我相信您真的应该测试组件行为而不是 sinon and/or iron-ajax 元素内部。您的请求很可能会更新一些 属性,这将触发一些 DOM 更新。
我也一直讨厌 setTimeouts
在测试中,只是发现 WCT 有一个 flush
方法来处理这些情况(它等待所有异步的东西完成)——只是没有记录在 AJAX 测试部分,但在 DOM 操作上(https://www.polymer-project.org/1.0/docs/tools/tests#test-local-dom)。
因此,我的做法是:
suite('testSuite', function () {
test('test1', function (done) {
// assuming iron-ajax with auto
server.respond();
flush(function () {
expect(el.myObject).to.deep.equal(responseObj);
// in case you're binding the last response to a property
expect(el.lastResponse).to.deep.equal(responseObj);
done();
})
});
});
我在模拟服务器对我的自定义组件中的 iron-ajax 组件的响应时遇到了最困难的时刻。这是我的代码文件。
自定义-component.html:
<link rel="import" href="/iron-ajax/iron-ajax.html">
<link rel="import" href="/internal-component/internal-component.html">
<dom-module id="custom-component">
<template>
<iron-ajax url="staticFile.json" auto handle-as="json" last-response={{ajaxResponse}}></iron-ajax>
<template is="dom-repeat"
items={{ajaxResponse}}
sort="_sort"
id="gridRow">
<internal-component var1={{item.var1}}
var2={{item.var2}}>
</internal-component>
</template>
</template>
</dom-module>
<script>(some cool scripts that are working...)</script>
自定义组件-tests.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/web-component-tester/browser.js"></script>
<script src="/test-fixture/test-fixture-mocha.js"></script>
<link rel="import" href="/test-fixture/test-fixture.html" />
<link rel="import" href="/polymer/polymer.html">
<link rel="import" href="/polymer-ts/polymer-ts.html">
<link rel="import" href="custom-component.html">
</head>
<body>
<test-fixture id="testElement">
<template>
<custom-component></custom-component.>
</template>
</test-fixture>
<script>
suite('<custom-component>', function () {
var testElement;
var server;
var responseHeaders = {
json: { 'Content-Type': 'application/json' },
plain: { 'Content-Type': 'text/plain' }
};
setup(function () {
replace('custom-component').with('fake-custom-component');
server = sinon.fakeServer.create();
server.respondWith('GET', /staticFile\.json/, [
200,
responseHeaders.json,
'[{"var1": "9a","var2": "17n"}]'
]);
testElement = fixture("testElement");
});
teardown(function () {
server.restore();
});
suite('testSuite', function () {
test('test1', function () {
var ajax = testElement.getElementsByTagName('iron-ajax')[0];
ajax.lastResponse = null;
ajax.generateRequest();
server.respond();
assert(ajax.lastResponse.hour === "9a");
});
});
});
</script>
</body>
</html>
您会注意到我明确调用了 iron-ajax generateRequest,因为如果我不这样做,那么在我的测试完成(并失败)之前请求甚至不会发生。当显式调用 generateRequest 时,我至少能够使请求发生,但是(即使我正在调用 server.respond())iron-ajax 直到测试完成后才调用 _handleResponse。而且,即使它这样做了,它也没有设置 lastResponse 因为在 iron-ajax 中有一行代码检查是否 (request === this.lastRequest) (它不是)。
我做错了什么?
我想我需要睡个好觉。
我忘了考虑异步请求。我修改了代码以反映以下内容:
suite('<custom-component>', function () {
var testElement;
var server;
var responseHeaders = {
json: { 'Content-Type': 'application/json' },
plain: { 'Content-Type': 'text/plain' }
};
setup(function () {
replace('custom-component').with('fake-custom-component');
server = sinon.fakeServer.create();
server.respondWith('GET', /staticFile\.json/, [
200,
responseHeaders.json,
'[{"var1": "9a","var2": "17n"}]'
]);
testElement = fixture("testElement");
});
teardown(function () {
server.restore();
});
suite('testSuite', function () {
// note that I added the "done" as a parameter on my test function
test('test1', function (done) {
var ajax = testElement.getElementsByTagName('iron-ajax')[0];
ajax.generateRequest();
server.respond();
// note that I added an async event listener here, and moved my test inside.
ajax.addEventListener('response', function(e) {
assert(e.target.lastResponse.var1 === "9a");
done();
}
});
});
});
我现在能够正确拦截响应,并且测试大部分都按预期工作。我仍然有 iron-ajax 的 lastResponse 未设置的问题,但我认为这是另一个问题。
我找到了一个更好的解决方案来测试元素中 iron-ajax 元素的自动功能。
您需要根据 ajax 的请求添加一个事件侦听器来触发您的服务器响应,不需要 generateRequest 也不需要 setTimeout hacks。
这里有一个例子:
test('test with ajax element', function (done) {
var ajax = Polymer.dom(myElement.root).querySelector("#ajax_element");
ajax.addEventListener('request', function (e) {
server.respond('GET', '/CALLED_URL', dataResponse);
});
ajax.addEventListener('response', function (e) {
//DO YOUR EXPECTS HERE
done();
});
});
作为组件测试,我相信您真的应该测试组件行为而不是 sinon and/or iron-ajax 元素内部。您的请求很可能会更新一些 属性,这将触发一些 DOM 更新。
我也一直讨厌 setTimeouts
在测试中,只是发现 WCT 有一个 flush
方法来处理这些情况(它等待所有异步的东西完成)——只是没有记录在 AJAX 测试部分,但在 DOM 操作上(https://www.polymer-project.org/1.0/docs/tools/tests#test-local-dom)。
因此,我的做法是:
suite('testSuite', function () {
test('test1', function (done) {
// assuming iron-ajax with auto
server.respond();
flush(function () {
expect(el.myObject).to.deep.equal(responseObj);
// in case you're binding the last response to a property
expect(el.lastResponse).to.deep.equal(responseObj);
done();
})
});
});