Skip to content

Add an injectAsync helper to the test_lib #4572

Closed

Description

@juliemr

The problem:

Currently, using the test injector with an async test is wordy and unintuitive:

import {it, inject, AsyncTestCompleter} from 'angular2/test_lib';

it('does stuff', inject[ClassA, ClassB, AsyncTestCompleter], (a, b, async) => {
  async.done();
});

There's a split in the code path anyway for async / not-async, so let's just make this explicit:

import {it, injectAsync} from 'angular2/test_lib';

it('does stuff', injectAsync[ClassA, ClassB], (a, b, done) => {
  done();
});

We could deprecate the AsyncTestCompleter separately if we don't want two ways of doing the same thing.

Thoughts?

cc @wardbell and see his version at #4035 (comment)

cc @vicb for thoughts.

Activity

  1. vicb commented on Oct 7, 2015

    @vicb
    Contributor

    Why not.

  2. IgorMinar commented on Oct 7, 2015

    @IgorMinar
    Contributor

    do we even need injectAsync? we can't we just provide done as the last argument to the callback?

    I'm also thinking that we should make inject callback return a promise back to inject and then we automatically know when to call done, and more importantly, we can propagate and display errors automatically without users having to do anything:

    it('does stuff', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => 
      tcb.createAsync(HeroesComponent) // notice implicit return of the returned promise
          .then((rootTestComponent: RootTestComponent) => {
            // assert here
           });   
    ));
    

    it could be shortened even further by a TCB specific helper but since we need to be able to override metadata via tcb before creating an instance of a component, things get tricky.

  3. vicb commented on Oct 7, 2015

    @vicb
    Contributor

    we can't we just provide done as the last argument to the callback?

    It depends if we have plan to drop mirrors (reflection) from the tests (Dart)

  4. juliemr commented on Oct 7, 2015

    @juliemr
    ContributorAuthor

    Here's a stab at this:

    master...juliemr:testapi

    I haven't looked at how it would work with Dart at all yet.

    What it does is provide the done function if it's asked for. There is only inject, no injectAsync. So this works asynchronously:

    import {it, inject} from 'angular2/test_lib';
    
    it('does stuff', inject[ClassA, ClassB], (a, b, done) => {
      done();
    });

    This also works, synchronously:

    import {it, inject} from 'angular2/test_lib';
    
    it('does stuff', inject[ClassA, ClassB], (a, b) => {
      // this is sync, no done function
    });
  5. tbosch commented on Oct 8, 2015

    @tbosch
    Contributor

    Victor, the tests need the runtime compiler, which only works with Mirrors
    On Wed, Oct 7, 2015 at 4:51 PM Julie Ralph [email protected] wrote:

    Here's a stab at this:

    master...juliemr:testapi
    master...juliemr:testapi

    I haven't looked at how it would work with Dart at all yet.

    —
    Reply to this email directly or view it on GitHub
    #4572 (comment).

  6. IgorMinar commented on Oct 8, 2015

    @IgorMinar
    Contributor

    We should design the best api possible for js/ts and if necessary create
    separate api for Dart. Keep in mind that this api is meant for angular apps
    and doesn't need to be used by the angular core test suite which needs to
    be transpilable (if that's a real world) to dart.

    On Wed, Oct 7, 2015, 5:29 PM Tobias Bosch [email protected] wrote:

    Victor, the tests need the runtime compiler, which only works with Mirrors
    On Wed, Oct 7, 2015 at 4:51 PM Julie Ralph [email protected]
    wrote:

    Here's a stab at this:

    master...juliemr:testapi
    master...juliemr:testapi

    I haven't looked at how it would work with Dart at all yet.

    —
    Reply to this email directly or view it on GitHub
    #4572 (comment).

    —
    Reply to this email directly or view it on GitHub
    #4572 (comment).

  7. juliemr commented on Oct 8, 2015

    @juliemr
    ContributorAuthor

    Agreed - however, if possible, it's really helpful to be able to use the angular core test suite as examples and documentation of how to test, so if we can make it work smoothly with both, I would be very happy.

  8. wardbell commented on Oct 8, 2015

    @wardbell
    Contributor

    Hi folks. When I took my first stab at this, I made done the first parameter. It is the only parameter that is essential to the callback and a reliable home for the done function. I don't think this is a huge deal for the tester. I'm just saying that it seems easier in first position other things being equal.

    I'm thrilled that you found a way to have one inject that can be either sync or async ... in approximately the same manner as the Jasmine it callback. Not sure how you did it but I like. How do you know if the done fn is in the parameter list?

  9. juliemr commented on Oct 8, 2015

    @juliemr
    ContributorAuthor

    @wardbell my current implementation is pretty naive - I just check if the length of the parameters to the injected function is greater than the length of the types to inject :)

  10. wardbell commented on Oct 8, 2015

    @wardbell
    Contributor

    Igor mentioned a feature I had in my version, namely that the callback returns a promise and the wrapper appends the requisite catch(fail).then(done) trailer. This alleviates the need for the developer to remember that sequence (which I find absent in many tests).

    This works great as long as the test function has a ready promise to return ... which is most of the time. It's a bit clumsy when you're testing something that uses observables instead of promises. I don't have enough observable testing experience to recommend a "best practice" yet.

  11. wardbell commented on Oct 8, 2015

    @wardbell
    Contributor

    @juliemr That is sweetly naive ... and probably sufficient most of the time.

    We must tell the test developer about it. I have, in the past, injected a service for some side-effect without actually needing it. In some such cases I listed it in trailing inject list position in which case I could omit it from the end of the parameter list. Maybe that was being too clever and I'd have a hard time recommending that approach. It obviously won't work here.

    I'm cool with a less than perfect inject function. The folks who write tests are a bit more forgiving and sophisticated than the broader Angular audience.

    OTOH, if we want this API to approach the same standard as mainstream Angular APIs, we probably should not play these games and should go with separate explicit inject and injectAsync methods.

    I don't have strong feelings either way.

  12. juliemr commented on Oct 8, 2015

    @juliemr
    ContributorAuthor

    Note: I can get this working with dart, see master...juliemr:testapi-2

  13. 6 remaining items

  14. wardbell commented on Oct 9, 2015

    @wardbell
    Contributor

    I don't know what else to do but document that test goes bad if don't return a promise.

    That's not much different than failing to provide a done param in a standard jasmine test.

    The good news is that vs code displays a massive number of red squiggles if you forget to return a promise (or it did with my injectAsync prototype). Maybe that's another reason for separate inject and injectAsync methods?

  15. juliemr commented on Oct 13, 2015

    @juliemr
    ContributorAuthor

    Done with a1fa2e4

  16. angular-automatic-lock-bot commented on Sep 7, 2019

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  17. locked and limited conversation to collaborators on Sep 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions