How do a test promise isFulfilled in integration tests?


#1

Hi I’m quite new to promises and definitely promises in Ember. I’m using EMber 2.18

I have a component with the following conditional:

{{#if totalAmount.isFulfilled}}
    <p data-test-total-amount>{{numeral-format (if totalAmount.count totalAmount.count 0)}}</p>
{{/if}}

If the promise is fulfilled then a value will show and I want to test that it shows correctly, otherwise is should show zero.

SO I have this component, where uniqueInteractions is the result of an ajax request : {{ui-circle-section totalAmount=uniqueInteractions}}

And just to test that I can use a promise and have it produce a value when fulfilled I tried:

var uniqueInteractions = new Promise(function(resolve) {
  return resolve("459");
});

await this.set('uniqueInteractions', uniqueInteractions);

But, that just doesn’t work. What’s the “ember” pattern for doing this?


#2

isFulfilled is not a feature of Promises in general. It’s a feature of PromiseProxy. You’re probably getting a PromiseProxy because that’s what ember-data returns.

If you want, in your test you can also make a PromiseProxy, so that the test acts like the real usage. The page I just linked starts with a code snippet showing how.

Alternatively, there are a couple other patterns that I think are less confusing and easier to test.

  • the most Emberish idiom is to try to keep as much data loading as possible in your Routes. I wrote a lot more about that topic here.

  • or you can use ember-promise-helpers in order to make your template deal correctly with any Promise (without requiring a PromiseProxy). It could look something like

    {{#with (await totalAmount) as |resolvedAmount|}}
       <p data-test-total-amount>{{numeral-format (if resolvedAmount.count resolvedAmount.count 0)}}</p>
    {{{/with}}
    

Also, this is a tangential suggestion but it may be helpful since you’re learning about Promises. This:

var uniqueInteractions = new Promise(function(resolve) {
  return resolve("459");
});

Can be said like this instead:

var uniqueInteractions = Promise.resolve("459");

It’s not Ember-specific, it’s a native Javascript Promise feature.


#3

Thank you so much for your answer gonna try to get that working in a test.

alternatively, when you mention that as much data as possible should load in the route: DO you mean that the isFulfilled condition should not be happening in the template, but in the route, which would then return the data directly to the template?


#4

Yes. When you return a Promise from a route’s model() hook, the router takes care of resolving the promise for you before your templates run. In that case your templates and components only ever see the value, not the promise for the value.