I am having the hardest time mocking the server response to an iron-ajax component inside my custom component. Here is my code files.
custom-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>
custom-component-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>
You'll notice that I'm explicitly calling the iron-ajax generateRequest because if I didn't, then the request wouldn't even happen until after my test completed (and failed). When calling generateRequest explicitly, I am at least able to make the request happen, but (even though I am calling server.respond()) iron-ajax doesn't call _handleResponse until after the test completes. And, even when it does, it is not setting lastResponse because there is a line of code in iron-ajax that checks if (request === this.lastRequest) (which it isn't).
What am I doing wrong?
I guess a good night's sleep is what I needed.
I forgot to account for asynchronous requests. I have amended the code to now reflect the following:
I am now able to properly intercept the response, and the test is mostly working as expected. I still have the problem that the iron-ajax's lastResponse is not set, but that is a different question I think.
I have found a better solution to test the auto functionality of iron-ajax elements in my elements.
You need to add an event listener on the request of your ajax to fire your server response, no need for generateRequest and no need for setTimeout hacks.
here is an example:
As a component test I believe you should really be testing the component behaviour rather than sinon and/or the iron-ajax element internals. Your request will most probably update some property which will trigger some DOM updates.
I've also always hated
setTimeouts
in tests, and just found out WCT has aflush
method for those cases (it awaits for all async stuff to finish) - it's just not documented on the AJAX testing section, but on the DOM manipulation instead (https://www.polymer-project.org/1.0/docs/tools/tests#test-local-dom).As such, my approach is: