Skip to content

Strawman for component-level testbed #1146

Closed

Description

@yjbanov

It is very common for application developers to test their components with their templates. Internally we call these tests "component tests" (as opposed to unit- or integration-tests). These tests are not unit tests as they exercise more than just the component class. Nor are they integration tests as far as the application is concerned; that term is reserved for testing cross-component interactions, full application tests, and tests that involve the back-end.

Here are the requirements:

  • instantiate a component in a test along with its template and child components
  • replace child components with mocks
  • pass bound values to the component
  • trigger change detection
  • fake the event loop, a la FakeAsync
  • verify that component implement change detection correctly (e.g. via observables, immutables)
  • access underlying DOM to trigger user events, such as click on buttons (this is usually done with the assistance of the Page Objects framework)

Strawman:

// This annotation tells Angular about test-specific dependency overrides
@ComponentTest(
  component: MyComponent,
  dependencyOverrides: const {
    ChildComponent: MockChildComponent,
    RealGoogleMap: MockGoogleMap,
  }
)
main() {
  describe("my-component", () {
    TestBed<MyComponent> testBed;

    beforeEach(() {
      testBed = createTestBedFor(MyComponent);
    });

    it("should work as intended", fakeAsync(async) {
      // instantiates a new component
      MyComponent cmp = testBed.component();

      // pass bindings using normal setters
      cmp.field1 = "hello";
      cmp.field2 = "world";

      // detectChanges runs change detection and returns how many
      // components ended up reevaluated, allowing testing correctness
      // of change detection
      expect(testBed.detectChanges().length, 5);

      // emulate passage of time
      async.flushMicrotasks();
      async.elapse(seconds: 1);

      // get access to the DOM
      Element rootElem = testBed.element();
      rootElem.querySelector('some-button').click();

      expect(cmp.buttonClicked, true);
    });
  });
}

Activity

  1. added this to the milestone on Mar 27, 2015
  2. yjbanov commented on Mar 27, 2015

    @yjbanov
    ContributorAuthor
  3. matanlurey commented on Mar 27, 2015

    @matanlurey
    Contributor

    Apparently this may be partially covered by #615. But I'd like to keep this open if possible because the strawman above is what would ease migration.

  4. changed the title [-]Provide component-level testbed[/-] [+]Strawman for component-level testbed[/+] on Mar 27, 2015
  5. yjbanov commented on Mar 27, 2015

    @yjbanov
    ContributorAuthor
  6. naomiblack commented on Mar 30, 2015

    @naomiblack
    Contributor

    @vicb can you resolve this along with #615?

  7. mhevery commented on Apr 3, 2015

    @mhevery
    Contributor

    @yjbanov I think we need to discuss this. I think this should be done through TestBed API rather than annotation. I am going to move it to later milestone for now.

  8. modified the milestones: , on Apr 3, 2015
  9. yjbanov commented on Apr 3, 2015

    @yjbanov
    ContributorAuthor

    @mhevery What would be the benefits of using imperative API over annotations?

  10. mhevery commented on Apr 4, 2015

    @mhevery
    Contributor

    Annotations are static. Imperative APIs can be easily extended, conditionally applied etc in the tests and even in the middle of the test.

  11. yjbanov commented on Apr 7, 2015

    @yjbanov
    ContributorAuthor

    OTOH, imperative API shuts the door to any potential code generated approaches to DI as no static analysis can be done on it. Could you give any concrete examples that annotations would not support?

  12. mhevery commented on Apr 7, 2015

    @mhevery
    Contributor

    Not sure code generation is high priority for tests.

  13. 5 remaining items

  14. yjbanov commented on May 1, 2015

    @yjbanov
    ContributorAuthor

    @mhevery the existing test bed API is based on internal classes and lacks integration with the event loop (specifically microtasks) and change detection.

    @vicb what do you think of the above proposal? We need to start working on this asap. If you are blocked on something urgent, please we can reassign.

    I'm ok with dropping the static API for the short term solution.

  15. vicb commented on May 4, 2015

    @vicb
    Contributor

    @yjbanov I think most of the requested features are available (fakeAsync excepted) via the TestBed.

    The priority right now should be to make the TestBed public (#1609) - might be a good idea to re-assign this item to someone with more bandwidth & who knows the render architecture better than I do.

    I have been working a lot on zones lately (#1609). Once we come with a working solution for microtasks in JS/Dart (hopefully sometime this week), I'll resume the work on fakeAsync() (as of today JS does not know what a microtask is which make it impossible to microleap() / flushMicrotasks())

    I also think we should first focus on the imperative API before starting to think about the static API.

    We also need to instrument the CD to fully cover your proposal, I had created a separate issue: #1172

  16. matanlurey commented on May 6, 2015

    @matanlurey
    Contributor

    I am looking into how Yegor's proposal could work, focusing on Dart. Will report back with any blockers.

  17. vicb commented on May 7, 2015

    @vicb
    Contributor

    @matanlurey I'm working on fakeAsync ATM (making sure we don't duplicate the effort)

  18. matanlurey commented on May 7, 2015

    @matanlurey
    Contributor

    I am just using the Dart (quiver/testing/async) library, which can be replaced by yours when it's ready.

  19. vicb commented on May 7, 2015

    @vicb
    Contributor

    My plan is to use fake_async (Dart) and lolex (JS) and come with Dart & JS wrappers.

    I think it will be easier now that JS zone also has a scheduleMicrotask

  20. mhevery commented on May 8, 2015

    @mhevery
    Contributor

    I will work on this.

  21. yjbanov commented on May 12, 2015

    @yjbanov
    ContributorAuthor

    This has been superseded by #1812. Closing.

  22. angular-automatic-lock-bot commented on Sep 6, 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.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions