Kevin Hunter
Kevin Hunter

Reputation: 61

Writing Ember.js async test helpers and tests involving async operations

I'm trying to figure out how to properly write an Ember test helper that performs its own async operations and tests that themselves involve async operations not necessarily wrapped in async helpers. The examples on the Ember site here and here both show async test helpers that are merely constructed by calling pre-existing async helpers, not code that creates its own async condition.

Background: I'm working on a service that's going to have a REST back end fronted by Ember+Ember Data. I want to write some test code that talks to the actual server in order to allow us to work out details on how Ember-Data interacts with the server. (Before you jump up and down about how integration tests should use fake data so that they can be run in CI mode, what we've done is set up a separate Ember app whose sole purpose in life is to exercise the data model through Ember Data for the purposes of debugging the server. Thus, these are really server tests, designed to ensure the compatibility between the server and Ember Data, not integration tests on the Ember application itself.)

Thus, what some of the tests want to do is:

  1. Execute an AJAX query to the server to trigger it to set up a certain data set. (Essentially, invoking some special test code inside the server to create appropriate preconditions.)
  2. Employ the Ember Data API in order to retrieve data from the server (or write data to it) in the same manner that the "real" Ember application would.
  3. Ensure that we get back what we expect, or that the data in the server looks correct afterwards.

Both of the first two operates are clearly asynchronous. The first would very clearly be a nice async helper. The second doesn't necessarily have to be a helper because each invocation is going to be different, but clearly the test itself needs to wait on the promise that methods from DS.store return.

Finally, other stuff I know:

  1. I understand the fundamental theory behind how Ember's test helper work. (Chained promises, etc.)
  2. The built-in async helpers (e.g. click, visit) all finish with return app.testHelpers.wait();
  3. wait returns an instance of RSVP.Promise which does a lot of processing to make sure things have more-or-less cleaned up before it resolves, including dealing with outstanding AJAX queries, test waiters, etc.
  4. wait can interact with test waiters, if required.

Thus, it would seem that if my async helper did the same thing as Ember's (i.e. return app.testHelpers.wait();) this would be sufficient for my AJAX helper, since wait would take care of waiting for the AJAX transaction to complete. This doesn't necessary answer the broader question, however.

OK, now the real questions:

  1. If I want to write my own arbitrary async helper, is it sufficient for me to return an instance of RSVP.Promise that will be resolved at the appropriate time? Or is it necessary to actually use the wait() mechanism (and possibly test waiters) because of some additional Ember dependencies on the behavior of the wait mechanism?

  2. Does Ember have any special requirements for tests involving async operations mid-stream? Or are the QUnit mechanisms for async tests sufficient?

  3. Does Ember have any kind of "wrapper" for the QUnit async stuff? (The way that it "hides" the QUnit-ness behind its set of test calls.)

  4. Do Ember Data interactions with the server have a dependency on the Ember run loop?

OK, I think that's clearly enough for a single question. :) I greatly appreciate anybody who's willing to educate me.

Upvotes: 3

Views: 251

Answers (1)

Nazim
Nazim

Reputation: 367

Trying to answer your questions with my experience with these issues which might be incomplete:

  1. You can simply register an async test helper that return an instance of RSVP.Promise. The andThen blocks will then wait for your promise to resolve before running as they do with built-in async helpers like visit.
  2. There are no specific requirements from Ember regarding async operations, afaik you should use the Qunit mechanisms. Some subtilities when you are writing async tests, the 'auto' run loop is disabled in test mode so you have to wrap your statements manipulating objects or setting properties on them inside an Ember.run statement
  3. AFAIK there aren't any Ember wrappers except for the modules (moduleForComponent etc..)
  4. Ember data interactions need to be nested inside an Ember.run statement because they are manipulating objects and the store and these need to be scheduled to run in the Ember run loop. When you run your app, Ember automatically schedules a bunch of calls for you but this is disabled in test mode

Hope this helps

Upvotes: 0

Related Questions