5

The controller I would like to test contains the following:

filterText: '',
filteredFoos: (Ember.A()),

filterFoosImpl: function() {
    console.log('filterFoos begin' );
    var filterText = this.get('filterText');
    var filteredFoos = this.forEach(function(foo) {
        return (foo.get(name).indexOf(filterText) >= 0);
    });
    this.set('filteredFoos', filteredFoos);
},

filterFoos: function() {
    Ember.run.debounce(this.filterFoosImpl.bind(this), 300);
}.observes('model', 'filterText'),

Now I would like to write a test that asserts that filteredFoos is updated when I set filterText.

To do this correctly, I will need to take into account Ember.run.debounce, and wait for that to occur before I perform my assertion. How can I do this?

bguiz
  • 27,371
  • 47
  • 154
  • 243
  • Honestly, I'd just stub debounce in the test to make it return immediately (synchronous) and add a test to make sure the stub was called. – steveax Jul 15 '14 at 01:39
  • @steveax Could you provide me with an example of that? – bguiz Jul 15 '14 at 02:05

2 Answers2

4

I was running into this problem as well and in order to stub out debounce, I did the following:

test('it triggers external action on a keyup event', function() {
    expect(1);

    // stub out the debounce method so we can treat this call syncronously
    Ember.run.debounce = function(target, func) {
      func.call(target);
    };

    var component = this.subject();
    var $component = this.append();

    var targetObject = {
      externalAction: function() {
        ok(true, 'external action called');
      }
    };

    component.set('keyUpAction', 'externalAction');

    component.set('targetObject', targetObject);

    $component.keyup();
});

The component I was testing looks like this:

export default Ember.TextField.extend({    
  triggerKeyUpAction: function() {
    this.sendAction('keyUpAction', event);
  },

  keyUp: function(/*event*/) {
    Ember.run.debounce(this, this.triggerKeyUpAction, 200);

    if(!this.get('value')){
      return;
    }

    this.set('value', String(this.get('value')).replace(/[^\d\.\,]/g, ''));
  }
});
Jason Buckner
  • 65
  • 1
  • 6
  • So basically stub out debounce. Anyone know if stubbing out debounce this way could harm test conditions? Should a reference to original debounce be stored? – Matt Jensen Aug 28 '15 at 17:04
  • You could backup the `debounce` method and restore it when you're done: `var origDebounce = Ember.run.debounce; Ember.run.debounce = function(target, func) { func.call(target); }; . . . Ember.run.debounce = origDebounce;` – Jason Buckner Sep 24 '15 at 19:29
1

Add

await settled();

Before your assertion

See https://guides.emberjs.com/v3.15.0/testing/testing-components/#toc_waiting-on-asynchronous-behavior it has a specific example for Ember debounce.

Took me a while to find this :).