Thursday, May 1, 2014

Problems Binding Angular to Polymer in Test.


It just doesn't work.

I have all my pieces seemingly in place to test angular-bind-polymer. I have the Karma and Jasmine setup in place nicely. I can dynamically add my custom Polymer element to the test DOM. I can inject the necessary dependencies into the test for my AngularJS code to update.

It all works save for the thing that I am actually trying to test—that the angular-bind-polymer directive can watch changes to Polymer attributes so that the values can be bound in Angular code. For instance, applying the bindPolymer directive in the following:
<x-double bind-polymer in="{{in}}" out="{{doubled}}"></x-double>
Will bind doubled in Angular's scope such that any changes from my Polymer element's out attribute will update Angular doubled. The other way around, Angular pushing changes into my custom element work out of the box—changes to Angulur's in will update the Polymer element's in attribute without any work from me.

And this does work in a smoke test page:
<p>
        in:<br>
        <input type=text value="6" ng-model=in>
      </p>
      <p>
        out:
        <pre ng-bind="doubled"></pre>
      </p>
      <x-double bind-polymer in="{{in}}" out="{{doubled}}"></x-double>
When I update the text field in Angular, my extremely simple <x-double> custom element doubles the value that it now sees on its in attribute, places the result on its out attribute, which then updates my Angular code's doubled thanks to angular-bind-polymer:



So it seemingly works. Only I cannot test it. My setup creates an Angular scope with associated compile object and establishes the Polymer custom element and the bound angular element:
  beforeEach(inject(function(_$compile_, _$rootScope_, $document) {
    $compile = _$compile_;
    $scope = _$rootScope_;

    container = document.createElement('div');
    $document[0].body.appendChild(container);

    var html1 = '<p ng-bind="answer"></p>';
    var html2 = '<x-double bind-polymer in="2" out="{{answer}}"></x-double>';

    boundElement = angular.element(html1);
    polymerElement = angular.element(html2);

    container.appendChild(boundElement[0])
    container.appendChild(polymerElement[0])

    $compile(boundElement)($scope);
    $compile(container)($scope);
    $scope.$digest();
  }));
But the test always sees an empty value for the ng-bind=answer element when I set the expectation:
  it('sees values from polymer', function(){
    expect(polymerElement[0].getAttribute('out')).toEqual('4');
    expect(boundElement[0].outerHTML).toEqual('4');
  });
And I just cannot figure this one out. The Polymer element is updated properly, but the binding is not flowing through back to the Angular scope.

Update: I am able to dig down into my directive to see that, somehow, the element that is injected into the directive is not the Polymer element. Well, it is but it isn't. I see the updated values of the attributes as if the internals of the Polymer element have updated things, but the element itself is not decorated with Polymer properties. Since my directive waits on those properties before establishing observers, my directive is effectively not doing anything—at least not in test.

I am unsure why this would be the case in test, but not in an actual page. I will have to investigate that tomorrow.

Day #51


No comments:

Post a Comment