I am building the scaffolding for my new polymer project, and am considering unit tests. I think I will be using the karma/jasmine combination. There is an interesting post at http://japhr.blogspot.co.uk/2014/03/polymer-page-objects-and-jasmine-20.html which I understand enough to get me started, but the key question I will have to address and haven't found any standard way to do it is how do I mock the ajax calls.
When I was using jasmine, standalone, on a JQuery Mobile project, I was able to directly use the Jasmine SpyOn ability to mock the JQuery.ajax call. Is there something similar for Polymer?
I came across an element <polymer-mock-data>
but there is no real documentation for it, so I couldn't figure out if they might help
Instead of importing core-ajax/core-ajax.html
, create your own core-ajax element.
<polymer-element name="core-ajax" attributes="response">
<script>
Polymer('core-ajax', {
attached: function() {
this.response = ['a', 'b', 'c'];
}
});
</script>
</polymer-element>
Obviously, this is just an example, the actual implementation depends on the desired mocking behavior.
This is just one way to solve it, there are many others. I'm interested to hear what you find (in)convenient.
It turns out that Jasmine2.0 has an Jasmine-ajax plugin that will mock the global XMLHttpRequest. core-ajax uses this under the hood, so I can directly get at the call.
It works well, in a beforeEach
function at the top the suite you call jasmine.Ajax.install
and in the afterEach
function you call jasmine.Ajax.uninstall
, and it automatically replaces the XMLHttpRequest.
Timing is also crucial, in that you need to ensure you have mocked the Ajax call before the element under test uses it. I achieve that using a separate function to specifically load the fixture which contains the element under test, which is called after jasmine.Ajax.install
has been called. I use a special setup script thus
(function(){
var PolymerTests = {};
//I am not sure if we can just do this once, or for every test. I am hoping just once
var script = document.createElement("script");
script.src = "/base/components/platform/platform.js";
document.getElementsByTagName("head")[0].appendChild(script);
var POLYMER_READY = false;
var container; //Used to hold fixture
PolymerTests.loadFixture = function(fixture,done) {
window.addEventListener('polymer-ready', function(){
POLYMER_READY = true;
done();
});
container = document.createElement("div");
container.innerHTML = window.__html__[fixture];
document.body.appendChild(container);
if (POLYMER_READY) done();
};
//After every test, we remove the fixture
afterEach(function(){
document.body.removeChild(container);
});
window.PolymerTests = PolymerTests;
})();
The only point to note here is that the fixture files have been loaded by the karma html2js pre-processor, which loads them into the window.__html__
array, from where we use the code to add to the test context
My test suite is like so
describe('<smf-auth>',function(){
beforeEach(function(done){
jasmine.Ajax.install();
PolymerTests.loadFixture('client/smf-auth/smf-auth-fixture.html',done);
});
afterEach(function(){
jasmine.Ajax.uninstall();
});
describe("The element authenticates",function(){
it("Should Make an Ajax Request to the url given in the login Attribute",function(){
var req = jasmine.Ajax.requests;
expect(req.mostRecent().url).toBe('/football/auth_json.php'); //Url declared in our fixture
});
})
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With