I feel like my grip on reality is slightly less than it was yesterday. I can make a Polymer pass, but I have no idea why this makes it pass.
I have a very simply
<x-double> Polymer element that takes the input of one attribute and doubles it on another attribute:<polymer-element name="x-double" attributes="in out">
  <template></template>
  <script>
    Polymer("x-double", {
      ready: function(){
        this.inChanged();
      },
      inChanged: function(){
        this.out = parseInt(this.in) * 2;
      }
    });
  </script>
</polymer-element>I have a correspondingly simple Karma / Jasmine test that tries to verify the element behaves as expected:  it('works', function(){
    // Container element
    var container = document.createElement('div');
    // Polymer element for testing
    var el = document.createElement('x-double');
    el.setAttribute('out', '');
    el.setAttribute('in', '42');
    container.appendChild(el);
    document.body.appendChild(container);
    // Wait for the Polymer element to update itself...
    var done = false;
    waitsFor(function(){ return done; });
    el.async(function(){ done = true; });
    // Check expectations...
    runs(function(){
      expect(el.getAttribute('out')).toEqual('84');
    });
  });Well, maybe not that simple, but it ought to work based on all of the research that I have done for Patterns in Polymer. So, naturally, the test fails:Expected '' to equal '84'.
        Error: Expected '' to equal '84'.
            at null.<anonymous> (/home/chris/repos/angular-bind-polymer/test/BindingSpec.js:20:38)
As I mentioned, I can make this pass, but only if I add a hack that I do not understand. I change the inChanged() watcher method to set the out attribute in addition to setting the out property:      inChanged: function(){
        this.out = parseInt(this.in) * 2;
        this.setAttribute('out', parseInt(this.in) * 2);
      }But why is that necessary? Setting the property should set the attribute. Or am I crazy? I go back to read the documentation and, yes, “property values are reflected back into their attribute counterpart.” So what absolutely stupid thing am I doing tonight to prevent that from happening?Well, it turns out that what I am doing was not absolutely stupid, but it was certainly a little stupid. I failed to read the mailing list which including a message about a breaking change to—you guessed it—attribute binding. It seems that binding like this, is not a typical use-case. It is still supported, but it is opt-in now. I can live with that (though it would be nice if the docs were updated).
Anyhow, I remove the explicit setting of the attribute, and instead opt-in for property reflection. To do so, I add
reflect: true to the published definition for my element:<polymer-element name="x-double" attributes="in out">
  <template></template>
  <script>
    Polymer("x-double", {
      publish: {
        out: {value: 0, reflect: true}
      },
      ready: function(){
        this.inChanged();
      },
      inChanged: function(){
        this.out = parseInt(this.in) * 2;
      }
    });
  </script>
</polymer-element>With that, I have my test passing. And a little of my sanity restored.Day #43
No comments:
Post a Comment