And, I'm back. I left off with some simple Karma and Jasmine testing of Polymer, so tonight, I try to pick back up with a similar question. How does interaction testing work with Polymer elements?
This question is part of the larger question of how do I test external mutation observers—specifically in the context of the chapter from Patterns in Polymer. I can feel myself sliding down a rabbit whole already with that one, so I set it aside for today. For now, I just want to test that user events like typing a name into an
<input>
field or pressing a button in a Polymer element has some kind of effect:I already know that I can query the
<h2>
element of this simple <hello-you>
Polymer with a Jasmine test along the lines of: describe('defaults', function(){
it('says an impersonal hello', function() {
var el = document.querySelector('hello-you');
var h2 = el.shadowRoot.querySelector('h2');
expect(h2.textContent).toEqual('Hello ');
});
});
So testing the expectation that the <h2>
tag is updated is trivial, but how do you “type” in a Jasmine test such that Polymer will see the changes?It turns out not to be a simple matter of updating the
value
of the <input>
: describe('typing', function(){
var el;
beforeEach(function(){
el = document.querySelector('hello-you');
var input = el.shadowRoot.querySelector('input');
input.value = 'Bob';
});
it('says an inpersonal hello', function() {
var h2 = el.shadowRoot.querySelector('h2');
expect(h2.textContent).toEqual('Hello Bob');
});
});
I am correctly targeting the proper <input>
field as debugger…ing(?) proves that the value is updated, though Polymer does not recognize it:I wind up having to create a Textinput event:
describe('typing', function(){
var el;
beforeEach(function(){
el = document.querySelector('hello-you');
var input = el.shadowRoot.querySelector('input');
// input.value = 'Bob';
var e = document.createEvent('TextEvent');
e.initTextEvent(
'textInput',
true,
true,
null,
'Bob'
);
input.dispatchEvent(e);
it('says an inpersonal hello', function() {
var h2 = el.shadowRoot.querySelector('h2');
expect(h2.textContent).toEqual('Hello Bob');
});
});
The initTextEvent()
arguments are the usual init-event suspects: the name of the event (“textInput”), if the event bubbles, if it is cancelable, the associated view, and the event data. In this case, I use the string “Bob” to indicate that a user has typed in the name Bob. After dispatching the event, I have:SUCCESS <hello-you> defaults says an impersonal hello SUCCESS <hello-you> typing says a friendly helloSo I have my passing test. And a new chain.
Day #1
Hm, interestingly this sometimes does not set the value in my tests. I see in the browser that the field doesn't change. Any ideas?
ReplyDeleteI've done this with success when I found similar issues:
DeletebeforeEach(function(done){
/* Init event as in the post... */
input.dispatchEvent(e);
setTimeout(done, 200);
});
Hope that helps!
-Chris