Search code examples
ember.jsember-data

How to test computed property that returns PromiseArray in Ember


I have a computed property that asks server for user data and then the other one that computes number of users. To propagate changes into the template, I'm using DS.PromiseArray wrapper. With this wrapper, I can't find an easy way to test this property.

  // model
  users: computed('name', function () {
    let name = get(this, 'name');
    return DS.PromiseArray.create({
      promise: this.store.query('user', { name })
    });
  }),

  numberOfUsers: computed('users', function () {
    return get(this, 'users.length') || 0;
  }),

  // ....

  test('numberOfUsers returns correct number', function (assert) {
    let model = this.subject({
      store: EmberObject.create({
        query() {
          return Promise.resolve([
            { name: 'Thomas' },
            { name: 'Thomas' },
            { name: 'Thomas' },
          ]);
        }
      }),
      name: 'Thomas',
    });

    assert.equal(model.get('numberOfUsers'), 3);
  });

This test fails with 0 !== 3. Any ideas?


Solution

  • Since model.get('users') is a promise, model.get('numberOfUsers') will not be 3 until the Promise resolves. In your test, you're immediately calling model.get('numberOfUsers'), and that is using the initial value of model.get('users'), which is an unresolved promise.

    To get it to work, you could call users and put your assert inside the then of that returned promise:

    model.get('users').then((user) => {
      assert.equal(model.get('numberOfUsers'), 3);
    })
    

    A couple of side notes:

    It is conventional in Ember to do your data fetching in the Route's model hook, not in a component like this.

    Also, there's no need to manually create a PromiseArray in your application code, because an Ember Data query returns a type of Promise Array already. So you can just return this.store.query('user', { name }); (If you do this, you'll have to change your test query stub to generate a PromiseArray).