Testing asynchronous UI
If the UI under test initializes asynchronously, or a method you're testing finishes asynchronously, your test must also be asynchronous.
One way to ensure a test runs at the appropriate time is to provide a Promise
the test can hook onto, e.g.
CrSettingsPrefs.initialized
.
Otherwise, pay attention to the flavor of asynchronicity involved. If you're using mocha, you can combine these techniques with the done() callback or returning a Promise from a test.
Macrotask timing
Tasks scheduled for the next event loop:
setTimeout
/setInterval
,
user interaction.
Testing: call setTimeout
and test UI in the callback.
Microtask timing
Tasks scheduled for the end of the current event loop:
Newly queued microtasks are processed in the current event loop. E.g., Promises will call chained resolve/reject handlers before a setTimeout callback, even if setTimeout was called before the chain of Promises was created.
Testing: create a Promise (or call setTimeout
) and test the UI in the
callback. Return a Promise from mocha tests.
Polymer microtask timing
Microtasks generated by Polymer are special*, and can be executed immediately via Polymer.dom.flush()
. This is a useful alternative to nesting setTimeouts in tests to ensure the DOM under test is up to date.
-
Templates:
dom-if
, andsort
/filter
ondom-repeat
-
Some elements, including: iron-list, paper-slider, paper-tabs,
paper-slider, paper-slider
-
Animations, focus, tab order, some key bindings
-
[myElement.async](http://polymer.github.io/polymer/#methods)
-
myElement.debounce
-
`[Polymer.dom(el).observeNodes](https://www.polymer-project.org/1.0/docs/devguide/local-dom.html#observe-nodes)`
Testing: prefer Polymer.dom.flush() over asynchronous callbacks.
*Polymer queues would-be microtasks and schedules them at the last
possible moment. Flushing this queue runs the tasks. If the queue is not
flushed, the microtasks are scheduled (strangely, via a MutationObserver
).
Synchronous
Some Polymer methods are explicitly synchronous:
-
Lifecycle callbacks.
created
andready
are calledimmediately when creating the element, and `attached` is called immediately after the element is added to the DOM.
-
Events dispatched dynamically.
el.fire('click')
,`MockInteractions.tap(el)`