Search code examples
polymerpromiseweb-component-tester

How do I test a Polymer element which should fail when it attaches


I am creating an element (a router - but that is not important), that is scanning the DOM soon after it has attached for particular other custom elements. I certain cases it needs to throw an error and I want to test for these.

The test I constructed is not failing - but as far as I can make out the test has already failed before my element gets attached. I suspect it is the asynchronous nature of things.

Here is the snippet of the test in question. The test fixture in question contains elements that will cause one of the elements to fail after a 'dom-change' event happens (which it has a listener for) when it then scans the dom for other things.

    it('should fail if two route elements both designate thenselves as home', function(done) {
      var t= document.getElementById('multiple_home');
      function multiple () {
        t.create();
      }
      expect(multiple).to.throw(Error);
      t.restore();
      done();
    });

I think the problem is related to the fact that the fixture is created in multiple, but hasn't yet failed by the time multiple exits. I am wondering if I can pass a Promise to expect - except I am not sure how to turn mulitple into a Promise to try it out.


Solution

  • I eventually found a way, but it requires instrumenting the element a bit to support this.

    In the elements "created" callback I create a Promise and store the two functions to resolve and reject it in "this" variables - thus:-

    this.statusPromise = new Promise(function(resolve,reject){
      this.statusResolver = resolve;
      this.statusRejector = reject;
    }.bind(this));
    

    In the DOM parsing section I use a try catch block like this

    try {
      //parse the dom throwing errors if anything bad happens
      this.statusResolver('Any useful value I like');
    } catch (error) {
      this.statusRejector(error);
    } 
    

    I then made a function that returns the promise

    domOK: function() {
      return this.statusPromise;
    }
    

    Finally in my test I was now able to test something like this (I load the fixture in each test, rather than a beforeEach, because I am using a different fixture for each test. I do clear it down again in an afterEach). Note the use of the .then and .catch functions from the Promise.

        it('should fail if two route elements declare the same path name',function(done){
          t = document.getElementById('multiple_path');
          t.create();
          r = document.getElementById('router')
          r.domOK().then(function(status){
            //We should not get here throw an error
            assert.fail('Did not error - status is: ' + status);
            done();
          }).catch(function(error){
            expect(error.message).to.equal('There are two nodes with the same name: /user');
            done();
          });