dimanche 29 mai 2016

Unit test a polymer web component that uses firebase

I have been trying to configure offline unit tests for polymer web components that use the latest release of Firebase distributed database. Some of my tests are passing, but others—that look nigh identical to passing ones—are not running properly.

I have set up a project on github that demonstrates my configuration, and I'll provide some more commentary below.

Sample: http://ift.tt/1qVjHu0

In that project, there are two suites of tests that work fine. The simplest is offline-test, which doesn't use web components at all. It simply shows that it's possible to use the firebase database's offline mode to run some unit tests. The heart of this trick is the in the suiteSetup method shown below—a trick I picked up from nfarina's work on firebase-server.

suiteSetup(function() {
  app = firebase.initializeApp({
      apiKey: 'fake',
      authDomain: 'fake',
      databaseURL: 'http://ift.tt/1X6dtGb',
      storageBucket: 'fake'
  });
  db = app.database();

  db.goOffline();
});

All the tests in offline-test pass.

The next suite is wct-firebase-demo-app_test.html, which test the eponymous web component. This suite contains a series of unit tests that are set up like offline-test and that pass. Following the idea of dependency injection, the wct-firebase-demo-app component has a database attribute into which is passed the firebase database reference, and this is used to make all the firebase calls. Here's an example from the suite:

  test('offline set string from web component attribute', function(done) {
    element.database = db;
    element.database.ref('foo').set('bar');
    element.database.ref('foo').once('value', function(snapshot) {
      assert.equal(snapshot.val(), 'bar');
      done();
    });
  });

I have some very simple methods in the component as well, in my attempt to triangulate toward the broken pieces I'll talk about in a moment. Suffice it to say that this test passes:

test('offline push string from web component function', function(done) {
    element.database = db;
    let resultRef = element.pushIt('foo', 'bar');
    element.database.ref('foo').once('value', function(snapshot) {
      assert.equal(snapshot.val()[resultRef.key], 'bar');
      done();
    });
  });

and is backed by this implementation in wct-firebase-demo-app:

  pushIt: function(at, value) {
    return this.database.ref(at).push(value);
  },

Once again, these all pass. Now we get to the real quandary. There's a suite of tests for another element, x-element, which has a method pushData:

  pushData: function(at, data) {
    this.database.ref(at).push(data);
  }

The test for this method is the only test in its suite:

  test('pushData has an effect', function(done) {
    element.database = db;
    element.pushData('foo', 'xyz');
    db.ref('foo').once('value', function(snapshot) {
      expect(snapshot.val()).not.to.be.empty;
      done();
    });
  });

This test does not pass. While this test is running, the console comes up with an error message:

    Your API key is invalid, please check you have copied it correctly.

By setting some breakpoints and walking through the execution, it seems to me that this error comes up after the call to once but before the callback is triggered. Note, again, this doesn't happen with the same test structure described above that's in wct-firebase-demo-app.

That's where I'm stuck. Why do offline-test and wct-firebase-demo-app_test suites work fine, but I get this API key error in x-element_test? The only other clue I have is that if I copy in a valid API key into my initializeApp configuration, then I get a test timeout instead.

Aucun commentaire:

Enregistrer un commentaire