Unit Testing ... how to STOP if Observer/CP fires


#1

I have really only recently started invested in unit tests for my Ember projects (yes I’m a bad person) but now that I’m doing it I need a little help. I have unit test that looks like this:

test('observing a property change in items', function(assert) {
  assert.expect(6);
  var done = assert.async();
  var component = this.subject({
    _propertyChangedCallback: (property) => {
      assert.equal(component.get('content.0.foo'),'Food', "the 'content' array should have the updated value from 'items'");
      assert.equal('foo', property, 'the changed property "foo" was detected');
      done(); 
    }
  });
  assert.ok(component._propertyChangedCallback, 'change callback appears to exist');
  assert.equal(typeOf(component._propertyChangedCallback), 'function',  'callback is a valid function');
  component.set('items', [
    Ember.Object.create({when: 2, foo: "Groceries", bar: "hungry, hungry, hippo", icon: "shopping-cart", badge: 1}),
    Ember.Object.create({when: 3, foo: "Hospital", bar: "visit sick uncle Joe", icon: "ambulance", badge: 6})
  ]);
  assert.equal(component.get('items.0.foo'), 'Groceries', 'initial value of foo is correct');
  component.set('items.0.foo','Food');
  assert.equal(component.get('items.0.foo'), 'Food', 'changed value of foo (in items) is correct');
  var later = run.later( () => {
    assert.equal(component.get('content.0.foo'),'Food', "the 'content' array should have the updated value from 'items'");
    assert.ok(false,"failed to observe change to 'foo' property");
    done();
  },50);
});

The test passes – meaning that the observer fires when the Ember.set is made but in order to account for failure scenarios I included the run.later({ ... }) logic. Great but unfortunately it still fires when I have achieved success and called QUnit’s assert.async() method. I also tried cancelling the run.later() with run.cancel() but that didn’t work and I started guessing that there is probably an easier way to do this.

Is there?


#2

BTW, I did sort of solve it but it feels VERY hacky:

On the callback the observer calls I added this.done = true;

var component = this.subject({
  _propertyChangedCallback: (property) => {
    assert.equal(component.get('content.0.foo'),'Food', "the 'content' array should have the updated value from 'items'");
    assert.equal('foo', property, 'the changed property "foo" was detected');
    this.done = true;
    done(); 
  }
});

Then on the run.later loop I added the if conditional:

var later = run.later( () => {
  if(!this.done) {
    assert.equal(component.get('content.0.foo'),'Food', "the 'content' array should have the updated value from 'items'");
    assert.ok(false,"failed to observe change to 'foo' property");
    done();      
  }
},50);