Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing dynamically-rendered elements in Polymer

Overview

DOM elements that are dynamically-rendered within dom-if, dom-repeat <templates> seem to be rendered asynchronously thus making unit-testing a bit of a pain.


The Polymer Component

template(is='dom-if', if='{{!defaultPrintAll}}')
  template(is='dom-repeat', items='{{_pageBucketItems}}')
    button(type='button', class$='{{_computeDefaultClass(item)}}', on-tap='_togglePageClick') {{item}}

The Test

  test("Clicking 'Export All' to off, reveals board-selection tiles", function() {
    $("#export-pdf-checkbox-all").siblings(".checkbox").trigger("click");
    Polymer.dom.flush()
    expect($(".board-range__button")).to.be.visible;
  });

Why it seems to fail:

When clicking a button which triggers the dom-if/dom-repeat the elements don't render in a synchronous order.

  • The dom-if and it's subsequent/nested dom-repeat render asynchronously.

  • To make matters worse, the button itself get's it's class in a computed/binded manner (mind the class$= on the button).

So the question boils down to this:

Is it possible to force render the dom-if, dom-repeat, and the computed-binding of the class in a synchronous order after I simulate the click to the button which activates all 3 of those conditions?


Notes:

  • I'm using Polymer's official WCT as the test harness.
  • I'm also using chai-jquery.
  • I've also used Polymer.dom.flush() but it still doesn't, ahem.. flush.
  • I'm aware that I can use chai-as-promised.js instead but it adds unnecessary complexity to my tests for a trivial matter such as this, so I'd like to avoid it.
like image 245
nicholaswmin Avatar asked Dec 29 '15 23:12

nicholaswmin


1 Answers

Rather than using Polymer.dom.flush(), try using the flush function that WCT puts on the window. This will enqueue a callback function to be executed, in theory, after the template has rendered.

test("Clicking 'Export All' to off, reveals board-selection tiles", function(done) {
    $("#export-pdf-checkbox-all").siblings(".checkbox").trigger("click");
    flush(function () {
        expect($(".board-range__button")).to.be.visible;
        done();
    }
});

Important to notice: Asynchronous tests require the done function to be passed into the test callback, and require done to be called after your conditions have been evaluated.

like image 173
Dogs Avatar answered Nov 26 '22 05:11

Dogs