<p dir="auto">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.</p>
<p dir="auto">Here are the requirements:</p>
<ul dir="auto">
<li>instantiate a component in a test along with its template and child components</li>
<li>replace child components with mocks</li>
<li>pass bound values to the component</li>
<li>trigger change detection</li>
<li>fake the event loop, a la <a href="https://github.com/google/quiver-dart/blob/cf72b438560a502ebb319e764700e96c1f4dbe01/lib/testing/src/async/fake_async.dart">FakeAsync</a></li>
<li>verify that component implement change detection correctly (e.g. via observables, immutables)</li>
<li>access underlying DOM to trigger user events, such as click on buttons (this is usually done with the assistance of the Page Objects framework)</li>
</ul>
<p dir="auto">Strawman:</p>
<div class="highlight highlight-source-dart notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
// This annotation tells Angular about test-specific dependency overrides
@ComponentTest(
  component: MyComponent,
  dependencyOverrides: const {
    ChildComponent: MockChildComponent,
    RealGoogleMap: MockGoogleMap,
  }
)
main() {
  describe(&quot;my-component&quot;, () {
    TestBed&lt;MyComponent&gt; testBed;

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

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

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

      // 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);
    });
  });
}"><pre class="notranslate"><span class="pl-c">// This annotation tells Angular about test-specific dependency overrides</span>
<span class="pl-k">@ComponentTest</span>(
  component<span class="pl-k">:</span> <span class="pl-c1">MyComponent</span>,
  dependencyOverrides<span class="pl-k">:</span> <span class="pl-k">const</span> {
    <span class="pl-c1">ChildComponent</span><span class="pl-k">:</span> <span class="pl-c1">MockChildComponent</span>,
    <span class="pl-c1">RealGoogleMap</span><span class="pl-k">:</span> <span class="pl-c1">MockGoogleMap</span>,
  }
)
<span class="pl-en">main</span>() {
  <span class="pl-en">describe</span>(<span class="pl-s">"my-component"</span>, () {
    <span class="pl-c1">TestBed</span>&lt;<span class="pl-c1">MyComponent</span>&gt; testBed;

    <span class="pl-en">beforeEach</span>(() {
      testBed <span class="pl-k">=</span> <span class="pl-en">createTestBedFor</span>(<span class="pl-c1">MyComponent</span>);
    });

    <span class="pl-en">it</span>(<span class="pl-s">"should work as intended"</span>, <span class="pl-en">fakeAsync</span>(<span class="pl-k">async</span>) {
      <span class="pl-c">// instantiates a new component</span>
      <span class="pl-c1">MyComponent</span> cmp <span class="pl-k">=</span> testBed.<span class="pl-en">component</span>();

      <span class="pl-c">// pass bindings using normal setters</span>
      cmp.field1 <span class="pl-k">=</span> <span class="pl-s">"hello"</span>;
      cmp.field2 <span class="pl-k">=</span> <span class="pl-s">"world"</span>;

      <span class="pl-c">// detectChanges runs change detection and returns how many</span>
      <span class="pl-c">// components ended up reevaluated, allowing testing correctness</span>
      <span class="pl-c">// of change detection</span>
      <span class="pl-en">expect</span>(testBed.<span class="pl-en">detectChanges</span>().length, <span class="pl-c1">5</span>);

      <span class="pl-c">// emulate passage of time</span>
      <span class="pl-k">async</span>.<span class="pl-en">flushMicrotasks</span>();
      <span class="pl-k">async</span>.<span class="pl-en">elapse</span>(seconds<span class="pl-k">:</span> <span class="pl-c1">1</span>);

      <span class="pl-c">// get access to the DOM</span>
      <span class="pl-c1">Element</span> rootElem <span class="pl-k">=</span> testBed.<span class="pl-en">element</span>();
      rootElem.<span class="pl-en">querySelector</span>(<span class="pl-s">'some-button'</span>).<span class="pl-en">click</span>();

      <span class="pl-en">expect</span>(cmp.buttonClicked, <span class="pl-c1">true</span>);
    });
  });
}</pre></div>
<ul class="contains-task-list">
<li><strong>I'm submitting a ...</strong></li>
<li>[x ] bug report</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> feature request</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> support request =&gt; Please do not submit support request here, see note at the top of this template.</li>
</ul>
<p dir="auto"><strong>Current behavior</strong><br>
I'm using angular2 with the universal component, i had my project working few weeks ago but now i wanted to install the app on another machine and i have a dependency issue<br>
my package.json refers to<br>
"angular2": "2.0.0-beta.15",<br>
"angular2-universal": "0.98.3"<br>
...<br>
on my local machine, the initial install made few weeks ago succesfully installed the following<br>
+-- angular2@2.0.0-beta.15<br>
+-- angular2-universal@0.98.3<br>
| +-- angular2-express-engine@0.11.1<br>
| +-- angular2-hapi-engine@0.11.1<br>
| +-- angular2-universal-polyfills@0.4.1<br>
| | +-- es6-promise@3.0.2<br>
| | `-- ie-shim@0.1.0<br>
...</p>
<p dir="auto">same thing today on another machine gives<br>
+-- angular2@2.0.0-beta.15<br>
+-- angular2-universal@0.98.3<br>
| +-- angular2-express-engine@0.13.1<br>
| +-- angular2-hapi-engine@0.13.1<br>
| +-- UNMET PEER DEPENDENCY angular2-universal@^0.101.4<br>
| +-- angular2-universal-polyfills@0.4.1<br>
| | +-- es6-promise@3.0.2<br>
| | `-- ie-shim@0.1.0<br>
...<br>
and i assume that this is why my project aint working there</p>
<p dir="auto"><strong>Expected/desired behavior</strong><br>
have a package that works with those dependencies</p>
<ul dir="auto">
<li><strong>What is the motivation / use case for changing the behavior?</strong><br>
it just fails</li>
<li><strong>Please tell us about your environment:</strong><br>
node 5.11.1<br>
windows 7</li>
<li><strong>Angular version:</strong> 2.0.0-beta.15</li>
<li><strong>Browser:</strong> [all ]</li>
<li><strong>Language:</strong> [ TypeScript]</li>
</ul>