Tuesday, December 17, 2013

Pub Serve Polymer Elements


OK. I know I'm doing something incredibly stupid, but... I still cannot get pub serve, the simple web server built into Dart's Pub package manager, to serve up Polymer Element resources.

I do not believe that I am doing any crazy though. I have a very simple, web-only application. The pubspec.yaml contains only the latest versions of Polymer and Polymer Elements:
name: flex
dependencies:
  polymer: any
  polymer_elements: any
dev_dependencies:
  unittest: any
I see no errors upon starting pub serve (though it does take a good 10 seconds to spin up). If I curl for similar resources, then everything works OK:
➜  dart git:(master) ✗ curl http://localhost:8080/packages/polymer_expressions/expression.dart
// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
...
But if I curl for Polymer Elements resources, I get nothing back:
➜  dart git:(master) ✗ curl http://localhost:8080/packages/polymer_elements/polymer_elements.dart
Nothing. The connection just hangs.

Pub's server can be run in verbose mode with pub serve -v (there are verbosity levels, but I just ask for everything here). With that, I find that the regular, working requests look like:
FINE: BarbackServer GET /packages/polymer_expressions/expression.dart
    | Loading polymer_expressions|lib/expression.dart
MSG : GET /packages/polymer_expressions/expression.dart → polymer_expressions|lib/expression.dart
FINE: BarbackServer GET /packages/polymer_expressions/expression.dart
    | Served polymer_expressions|lib/expression.dart
Whereas the failing request look like:
FINE: BarbackServer GET /packages/polymer_elements/polymer_elements.dart
    | Loading polymer_elements|lib/polymer_elements.dart
So the request is coming into the Pub server. It seems to parse it properly—the requests is for the lib/polymer_elements.dart file in the polymer_elements package. But then... nothing.

So I try using the GitHub repository for Polymer Elements instead. Perhaps it hold some insights into my woes:
name: flex
dependencies:
  polymer: any
  polymer_elements:
    git: https://github.com/ErikGrimes/polymer_elements
dev_dependencies:
  unittest: any
But trying a pub upgrade with that yields:
➜  dart git:(master) ✗ pub upgrade
Resolving dependencies.........................
Incompatible dependencies on 'polymer_elements':
- 'flex' depends on it from source git
- 'polymer_ui_elements' depends on it from source hosted
Why on earth is Polymer Elements trying to pull in Polymer UI elements anyway.

I do the usual GitHub upstream dance and use my repository instead:
name: flex
dependencies:
  polymer: any
  polymer_elements:
    git: https://github.com/eee-c/polymer_elements
dev_dependencies:
  unittest: any
And before I realize my mistake, I pub upgrade and pub serve and find that I can now curl for Polymer Element resources:
➜  dart git:(master) ✗ curl http://localhost:8080/packages/polymer_elements/polymer_elements.dart
// needed as entry point for dartdoc generation
/**
 * Polymer Elements
 */
library polymer_elements;
// ...
My mistake is pointing my pubspec.yaml dependencies at my fork of Polymer Elements as it exists on GitHub, not as it exists locally. But at least I know a change in the code since then has affected things. A git diff --stat <SHA1> where <SHA1> points to a0717db12 (my last commit) reveals that there have been a lot of code changes in the meantime. I tend to doubt code changes are my problem here. Instead, I think the problem is in the changes to the project's pubspec.yaml:
➜  polymer_elements git:(master) gd a0717db12 pubspec.yaml
diff --git a/pubspec.yaml b/pubspec.yaml
index 398337d..7df61fd 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: polymer_elements
-version: 0.0.13
+version: 0.1.2
 authors:
 - Erik Grimes 
 - Günter Zöchbauer 
@@ -11,8 +11,11 @@ documentation: http://erikgrimes.github.io/polymer_elements/docs/index.html
 environment:
   sdk: ">=1.0.0 <2.0.0"
 dependencies:
-  polymer: ">=0.9.0 <0.10.0"
-#  polymer_ui_elements: 0.0.13
+  polymer: ">=0.9.2+3 <0.10.0"
+  polymer_ui_elements: ">=0.1.1 <0.2.0"
+#dependency_overrides:
+#  polymer_ui_elements: 
+#    path: ../polymer_ui_elements  
 dev_dependencies:
   unittest: ">=0.9.0 <0.10.0"
 transformers:
And indeed, if I remove the Polymer UI Elements dependencies from my local fork of Polymer Elements, then I can pub upgrade without error and, more importantly, successfully curl after starting pub serve. In fact, I can now serve my flex-layout web page:
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Flex Test</title>
    <!-- Load component(s) -->
    <link rel="import" href="/packages/polymer_elements/polymer_flex_layout/polymer_flex_layout.html">
    <script type="application/dart">export 'package:polymer/init.dart';</script>
    <script src="packages/browser/dart.js"></script>
  </head>
  <body>
     <polymer-flex-layout isContainer>
       <div>Left</div>
       <div align=center flex>Main</div>
       <div>Right</div>
     </polymer-flex-layout>
  </body>
</html>
And see the results in Dartium:

I suspect that my problems have to do with circular dependencies in Polymer Elements and Polymer UI Elements. I am still not certain that either needs to depend on the other. Regardless, pub serve probably ought to deal with this situation better. PRs and bug reports to come…

Day #968

Monday, December 16, 2013

Not-So Flex Polymer


To date, my exploration of Polymer for Patterns in Polymer has been decidedly UI-less. Now that the book has seen its initial Alpha release, it seems a good time to start exploring some of the UI features, starting with some of the built-in <polymer-*> elements.

I do not expect to include much <polymer-*> usage in the book. Still, exploring these element so far has been a bonanza of inspiration for me—both in exposure to solid Polymer coding styles and in generating other ideas. Tonight, I look at the Polymer flex layout. I start with the usual pubspec.yaml:
name: flex
dependencies:
  polymer: any
  polymer_elements: any
dev_dependencies:
  unittest: any
After a Dart Pub install
$ pub get
Resolving dependencies....................................
Downloading polymer_elements 0.1.1 from hosted...
Downloading polymer 0.9.3+1 from hosted...
Downloading unittest 0.9.2 from hosted...
Downloading polymer_ui_elements 0.1.1 from hosted...
Got dependencies!
But when I try to run pub serve things break down—the web server never responds to requests for any polymer elements:
$ curl http://localhost:8080/packages/polymer_elements/polymer_file/polymer_file.html
$ ls packages/polymer_elements/polymer_file/polymer_file.html
packages/polymer_elements/polymer_file/polymer_file.html
Stumped for now, but wanting to make some progress, I switch to JavaScript. I bower install the flex layout Polymer:
bower install Polymer/polymer-flex-layout
bower polymer-flex-layout#*     cached git://github.com/Polymer/polymer-flex-layout.git#0.1.1
bower polymer-flex-layout#*   validate 0.1.1 against git://github.com/Polymer/polymer-flex-layout.git#*
bower polymer#0.1.1         not-cached git://github.com/Polymer/polymer.git#0.1.1
bower polymer#0.1.1            resolve git://github.com/Polymer/polymer.git#0.1.1
bower polymer#0.1.1           download https://github.com/Polymer/polymer/archive/0.1.1.tar.gz
bower polymer#0.1.1            extract archive.tar.gz
bower polymer#0.1.1           resolved git://github.com/Polymer/polymer.git#0.1.1
bower platform#0.1.1        not-cached git://github.com/Polymer/platform.git#0.1.1
bower platform#0.1.1           resolve git://github.com/Polymer/platform.git#0.1.1
bower platform#0.1.1          download https://github.com/Polymer/platform/archive/0.1.1.tar.gz
bower platform#0.1.1           extract archive.tar.gz
bower platform#0.1.1          resolved git://github.com/Polymer/platform.git#0.1.1
bower polymer-flex-layout#~0.1.1          install polymer-flex-layout#0.1.1
bower polymer#0.1.1                       install polymer#0.1.1
bower platform#0.1.1                      install platform#0.1.1

polymer-flex-layout#0.1.1 bower_components/polymer-flex-layout
└── polymer#0.1.1

polymer#0.1.1 bower_components/polymer
└── platform#0.1.1

platform#0.1.1 bower_components/platform
Then make my page:
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Flex Test</title>
    <!-- 1. Load Polymer before any code that touches the DOM. -->
    <!-- <script src="scripts/polymer/polymer.js"></script> -->
    <script src="scripts/platform/platform.js"></script>
    <!-- 2. Load component(s) -->
    <link rel="import" href="scripts/polymer-flex-layout/polymer-flex-layout.html">
    <link rel="import" href="scripts/polymer-flex-layout/polymer-flex-panel.html">
  </head>
  <body>
     <polymer-flex-layout isContainer>
       <div>Left</div>
       <div align=center flex>Main</div>
       <div>Right</div>
     </polymer-flex-layout>
  </body>
</html>
Which does the trick:



Even the JavaScript version is not without its difficulties. I am unable to get the vertical layout working properly—a flexed body does not occupy the entire page. But compared to the Dart version, that is small potatoes. Tomorrow, it seems that I really need to dig into my pub serve problems. Thankfully I have a working JavaScript example in my pocket once I figure that out.



Day #967

Sunday, December 15, 2013

Async Polymer Tests (JS)


After a minor inconvenience testing an asynchronous Dart Polymer element, I wonder how it works to do the same with JavaScript?

The answer is that it works surprisingly difficultly.

I am somewhat surprised as I already have a testing chapter in Patterns in Polymer, so I thought I had this figured out. I am still using Karma as the test runner with Jasmine as the testing framework. I have to perform some hackery to get the Polymer library and my custom Polymers loaded in the proper order. Still, I though I had this sussed out.

The list of files in my Karma configuration is:
    /**
     * Don't include Polymer HTML and JS because Polymer is very
     * particular about the order in which they are added. Serve them,
     * but defer loading to the test setup. Include test HTML
     * fixtures.
     */
    // list of files / patterns to load in the browser
    files: [
      'test/PolymerSetup.js',
      {pattern: 'scripts/**', included: false, served: true},
      'test/**/*Spec.js'
    ],
The entry that is causing me grief is the middle one. When I check that glob on the filesystem, it includes my parent.html Polymer (along with the Polymer library and the child.html Polymer):
s -1 scripts/**
scripts/child.html
scripts/parent.html
scripts/polymer.min.js
scripts/polymer.min.js.map
But when I try to run my tests, I find that my parent.html is 404ing:
➜  parent_child git:(master) ✗ karma start
INFO [karma]: Karma v0.10.4 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 32.0.1700 (Linux)]: Connected on socket bnd9TqMfxiLeUMXYog0b
WARN [web-server]: 404: /base/scripts/parent.html
...
Hunh?

This worked previously. Otherwise, how could I have written a chapter on the subject? After a time, I realize that the only difference between my earlier, working Karma configuration and this new one is that the former also has a preprocessor entry that matches my text fixtures:
    preprocessors: {
      'test/*.html': 'html2js'
    },
I have no test fixtures for this test, so I had not included the setting.

If I do include it in my karma.conf.js file this time, it also works. But I have no idea why this would be. The file pattern for the html2js preprocessor does not match the missing scripts/parent.html file. In fact, if I include just the preprocessor setting with no value, then it still works:
    // Without this, Karma will not serve HTML files :-\
    preprocessors: null,
Ultimately, I can find no useful explanation as to why this would behave this way.

Stumped, I move on to the actual tests which, thanks to Jasmine's asynchronous testing support are fairly easy. I need to wait for a timer in the Polymer update itself the counter. If I wait for 1500 milliseconds, then check my expectation, then the test ought to pass:
  it('updates the parent', function() {
    waits(1500);
    runs(function(){
      expect(el.shadowRoot.textContent).toContain('Count: 1');
    });
  });
And that works fine. After doing the same for the child element, I have two passing JavaScript tests to mirror the two passing Dart tests. I am a little bummed about the preprocessor requirement, though I can live with it. Especially given the other hackery that I include in my Polymer test setup for JavaScript, that is barely a cause for concern. Still, I would like to understand that better, so mental note made for a possible follow-up post.

Day #966

Saturday, December 14, 2013

Dynamically Created Polymers and Bound Variables (Dart)


I now have my parent Polymer talking to my child polymer. I can update the value in the parent, display it, pass it to the child, which displays the same value:



I am doing this in Dart the same way that I did it in JavaScript—by binding parent variables to child attributes:
<link rel="import" href="child.html">
<polymer-element name="x-parent">
  <template>
    <div>
      <h2>Parent</h2>
      <p>Count: {{parent_count}}</p>
      <x-child count="{{parent_count}}"></x-child>
    </div>
  </template>
  <script type="application/dart" src="parent.dart"></script>
</polymer-element>
This seems to work, but nothing really works in this business if you can't test it.

I start with the page context for my web tests. As I have found in Patterns in Polymer, this page needs to import the Polymer being tested and the test script:
<head>
  <!-- Load component(s) -->
  <link rel="import" href="packages/parent_child/parent.html">
  <script type="application/dart" src="test.dart"></script>
</head>
I do not start Polymer, instead I leave that to the test script:
library parent_child_test;
import 'package:unittest/unittest.dart';
import 'dart:html';
import 'dart:async';
import 'package:polymer/polymer.dart';

main() {
  initPolymer();
  // Test here...
}
The test setup that I have been using creates an element, storing it in a variable so that it can be torn down, and adds it to the document. The only thing complicating this is Dart's insistence on sanitizing HTML tags. Since the whole point of Polymer is to create non-standard HTML tags, I have to use a non-sanitizing createElement() helper. Altogether, this looks like:
main() {
  initPolymer();
  var _el;
  setUp((){
    _el = createElement('<x-parent></x-parent>');
    document.body.append(_el);
  });
  tearDown((){
    _el.remove();
  });

  // Test here...
}

createElement(String html) =>
  new Element.html(html, treeSanitizer: new NullTreeSanitizer());

class NullTreeSanitizer implements NodeTreeSanitizer {
  void sanitizeTree(node) {}
}
The tests themselves are straight-forward. I create a timer that waits for the timer in the Polymer itself so that I can test that the Polymer content is being updated:
    solo_test('updates the parent', (){
      new Timer(
        new Duration(milliseconds: 1500),
        expectAsync0((){
          expect(
            query('x-parent').shadowRoot.text,
            contains('Count: 1')
          );
        })
      );
    });
That ought to work. Of course it does not:
FAIL: [updates] updates the parent
  Expected: contains 'Count: 1'
    Actual: '\n'
    '    \n'
    '      Parent\n'
    '      Count: 0\n'
    '      \n'
    '    \n'
    '  '
Regardless of the delay, I find that “Count” text is not updating. In fact, if I do not remove the test element in the teardown, I find that it is not being updated in the browser either. In the end, I find that variable binding does not work unless the element is added before polymer is initialized:
main() {
  _el = createElement('<x-parent></x-parent>');
  document.body.append(_el);
  initPolymer();
  _el.remove();
  // Test here...
}
I am sure that there must be some underlying reason for this. I am just as sure that there is some more direct way of ensuring that bound variables are updated in the UI. But this works. And working in tests is usually good enough. If I ever need this in actual code, I will revisit. But, hopefully, if I do ever need this, the problem will be fixed or better understood. For now, I have two decent tests and am ready to start writing another chapter.


Day #965

Friday, December 13, 2013

Wait a Second, I Know This…


Sometimes there is no substitute for a small test case. I begrudge every minute that I have to work on small test cases instead of the actual task at had, but often there is nothing for it but to break down and write that small test case. Unless someone does it for you that is.

That someone in this case is James Hurford. Having witnessed my meltdown in yesterday's post on Polymer.dart, he (like me) thought, “that should work.” And so, he wrote a small test case that proved it worked. Having no luck in my own code, I switched to his and gave it whirl.

And it still did not work.

So clearly James is wrong and I'm right… right? Long time readers of this blog already know the answer is that I'm wrong. To prove myself wrong, I converted James' test case into simpler named <x-parent> and <x-child> tags. The parent needs to communicate to the child. In the parent template, I bind the <x-parent>'s observable count variable with the <x-child>'s attribute of the same name:
<link rel="import" href="child.html">
<polymer-element name="x-parent">
  <template>
    <div>
      <h2>Parent</h2>
      <span>(item count: {{count}})</span>
      <x-child count="{{count}}"></x-child>
    </div>
  </template>
  <script type="application/dart" src="parent.dart"></script>
</polymer-element>
With that, whenever the observable count instance variable in <x-parent> changes, the attribute/instance variable in <x-child> should change as well.

Adapting James' code, my <x-child> backing class is where I make changes to the doubly bound variable:
import 'package:polymer/polymer.dart';
import 'dart:async';

@CustomTag('x-child')
class Child extends PolymerElement {
  @published int count = 0;

  Child.created() : super.created();

  @override
  void enteredView() {
    super.enteredView();
    new Timer.periodic(
      new Duration(milliseconds: 900),
      (t){
        count++;
        print(count.toString());
      }
    );
  }
}
Every 900 milliseconds, the count is incremented and should be reflected in both parent and child element. Except it is not:



Just as I saw yesterday, the actual value is be changed, as evidenced by the console output on the right. And just as yesterday, the actual bound variables are not being updated.

So I try this with just the <x-child> element and no bound variables thinking that perhaps there is a bug in data binding. And it still does not work.

It is at this point that something from deep within the recessed of my brain stirs. This is bound variables not updating. I know this. In fact, I submitted the damn bug not 7 days ago. Happily, I included a workaround in that bug. After following my own advice, and downgrading the observable package in my pubspec.yaml:
name: parent_child
dependencies:
  polymer: any
  observe: "0.9.0+1"
dev_dependencies:
  unittest: any
After a pub upgrade (downgrade?), it works:



I cannot believe that I have now run into the same extremely annoying problem twice and failed to recognize it the second time. And yes, downgrading the observe package in last night's code (and removing a ton of debug code) fixed the problem.

My own shame aside, I have successfully identified the Polymer way of communicating between parent and child. As long as a buggy version of Dart's observe package is not used, this data binding approach works just as well in Dart as it did previously in the JavaScript version of the code. And I would not have been able to prove this without James' help. So thanks James!


Day #964

Thursday, December 12, 2013

Communicating with Child Polymers Redux


I love learning new stuff. I don't mean just playing with new stuff. Or even bending new stuff my will. I mostly enjoy really learning new stuff—how it wants to be used. Really, there is not a ton to be gained just playing with stuff. And bending it to my will is just another way of saying that I'm using a new tool with an old mentality. But when I really learn a new thing, my mentality changes. Then I really have a new tool to use for new and old problems alike.

This is one of the reasons that I am enjoying writing a book on Polymer in JavaScript and Dart. When I think that I have a solution the way that Polymer wants to be used, I can try it out in the other language to see if it still works. I found last night that one approach I took to communicating to child Polymers was not right. It worked in Polymer.dart, but not the JavaScript version of the library.

After a bit more experimentation in the JavaScript version of my code, I found another promising approach. To communicate the initial load value from my parent <store-changes> element down to the child <store-changes-load>, I bound an instance variable in the template that references the child:
<link rel="import" href="store-changes-load.html">
<polymer-element name="store-changes">
  <template>
    <store-changes-load current="{{_initial}}"></store-changes-load>
    <content></content>
  </template>
  <script>
    Polymer('store-changes', {
      // ...
      _fetchCurrent: function() {
        this.record = this.store.value;
        this._initial = this.record;
      },
      // ...
    });
  </script>
</polymer-element>
When the initial value is loaded in _fetchCurrent(), the _initial value is updated. Since that same instance variable is bound in the Polymer's <template>, the <store-changes-load> element can see the new value. This feels like a good solution—not because it works, but because I need to do so little work. It feels like I am using the framework, not fighting it.

And indeed, Polymer provides observer helpers that can watch attribute in the child element to make this kind of thing easy:
<polymer-element name="store-changes-load" attributes="current">
  <script>
    Polymer('store-changes-load', {
      // ...
      currentChanged: function(oldValue, newValue) {
        console.log('old: '+ oldValue);
        console.log('new: '+ newValue);
      },
      // ...
    });
  </script>
</polymer-element>
To see if this really is the Polymer way, I switch back to Dart. I start with the Polymer definition:
<polymer-element name="store-changes">
  <template>
    <store-changes-load current="{{initial}}"></store-changes-load>
    <content></content>
  </template>
  <script type="application/dart" src="store_changes.dart"></script>
</polymer-element>
I am binding the public initial value because private variables do not seem to work in Polymer.dart data binding.

Then, in the backing class, I declare initial as a string with a dummy initial value:
@CustomTag('store-changes')
class StoreChangesElement extends PolymerElement {
  String initial = 'THIS SHOULD CHANGE!!!';
  // ...
  void _fetchCurrent() {
    stores.forEach((store) {
      store.fetch().then((_r) {
        record = _r;
        initial = record['current'];
        print('initial: $initial');
      });
    });
  }
  // ...
}
Just as in the JavaScript version, I set the initial value when the change history record is retrieved from the data store. Updating the value of initial in the object updates the value in the <template>, which in turns updates the value of <store-change-load>'s current attribute. At least that is what it ought to do.

Unfortunately, when I make the attribute changes in <store-changes-load>:
@CustomTag('store-changes-load')
class StoreChangesLoadElement extends PolymerElement {
  @published String current = '';
  // ...
  StoreChangesLoadElement.created(): super.created();
  // ...
  _listenForLoad() {
    new Timer(
      new Duration(milliseconds: 900),
      (){
        if (current == null || current == '') return;
        print('current: $current');
        editable.innerHtml = current;
      }
     );
  }
  // ...
}
I am still seeing the default value:



Judicious print() statements verify that the initial value is being set correctly and that the current attribute is being used after the data is loaded:
initial: 
          <h1>Change 08</h1>
        
current: THIS SHOULD CHANGE!!!
But the child element just does not see the change.

Darn it. I really thought I had this licked. Back to the drawing board? Maybe, or it may be time to dig into the Polymer.dart source code. I really think this ought to work.


Day #963

Wednesday, December 11, 2013

Can't Listen for Events on Parent Shadow Root


One of the things that I hope to gain by writing Patterns in Polymer in both JavaScript and Dart is a deeper understanding of what Polymer really is. Not just how I can bend it to my will, but how it really wants me to code it.

To that end, I have a solution for communicating from parent Polymers to descendant Polymers (which might possibly reside in a shadow DOM). The solution involved the following DOM structure:
    <store-changes>
      #shadowRoot
      <store-changes-load></store-changes-load>
      <div contenteditable>
        <!-- actual changes occur here -->
      </div>
    </store-changes>
The <store-changes> element fires events on its shadowRoot and the <store-changes-load> element listens to that same shadowRoot. That seemed to work, at least when working with Polymer.dart. But what about in regular Polymer?

I run into a few minor issues converting my Dart Polymers over to JavaScript. Mostly, I find that, where I could hook into the ready() lifecycle callback in Dart, I need to use enteredView() in JavaScript:
<polymer-element name="store-changes-load">
  <script>
    Polymer('store-changes-load', {
      enteredView: function() {
        this._findElements();
        this._listenForLoad();
      },
      // ...
    });
  </script>
</polymer-element>
With ready() in JavaScript, the shadowRoot is undefined, which, I suppose makes some sense. Mental note made.

Unfortunately, that is not all that I find. I verify that the shadowRoot from the parent <store-changes> element is the same thing as the parentNode from the <store-changes-load child element. Despite this, I cannot listen for events on that parent node. When I listen for events, even events created in the same <store-changes-load> child element, I see nothing:
<polymer-element name="store-changes-load">
  <script>
    Polymer('store-changes-load', {
      // ...
      _listenForLoad: function() {
        this.parentNode.addEventListener('store-changes-load', function(e){
          // I see nothing in here
          console.log('yo');
          var current = e.detail['current'];
          console.log(current);
        });

        // Dispatching this should show hte event above///
        var e = new CustomEvent('store-changes-load', { 'detail': {current: 'foo'} });
        this.parentNode.dispatchEvent(e);
      },
      // ...
    });
  </script>
</polymer-element>
Doing the same in the parent <store-changes> parent Polymer works fine. So it would seem that, at least in the JavaScript version of Polymer that there is no way for a child element to listen for (or generate) events on the document fragment that serves as the shadow root.

So it seems that it's back to the drawing board on how best to communicate from parent to child in the shadow DOM.

Day #962