title: Angular 2 - Unit test binding to nested custom form control
body: <p>I've got a custom from control with selector <code>app-date-picker</code>. It implements <code>ControlValueAccessor</code>. I have a component called <code>MyPage</code> that contains this custom form control via:</p>
  
  <pre><code>&lt;app-date-picker class="address__from-date" [(ngModel)]="fromDate"&gt;&lt;/app-date-picker&gt;
  </code></pre>
  
  <p>I'm trying to write a unit test for <code>MyPage</code> that tests both directions of binding. I have done this for other form fields just fine, for example:</p>
  
  <pre><code>it('should bind zip code', fakeAsync(() =&gt; {
    const formControl = element.query(By.css('.address__zip-code input')).nativeElement;
  
    // model -&gt; view
    component.zipCode = 76777;
    fixture.detectChanges();
    tick();
  
    expect(formControl.value).toEqual('76777');
  
    // view -&gt; model
    formControl.value = '89556';
    formControl.dispatchEvent(new Event('input'));
  
    expect(component.zipCode).toEqual(89556);
  }));
  </code></pre>
  
  <p>My problem arises when I try to do this for my custom form control. So far, I can only test one direction of binding, and even so it is requiring the use of <code>ng-reflect-model</code>, which is just awful:</p>
  
  <pre><code>it('should bind from-date', fakeAsync(() =&gt; {
    const formControl = element.query(By.css('.address__from-date app-date-picker')).nativeElement;
  
    // model -&gt; view
    component.fromDate = '01/2017';
    fixture.detectChanges();
    tick();
  
    expect(formControl.attributes['ng-reflect-model'].value).toEqual('01/2017');
  
    // view -&gt; model
    // Not sure what to do here either
  }));
  </code></pre>
  
  <p>Is there a better way to go about doing this? I'd like to:</p>
  
  <ol>
  <li>Be able to test both directions of binding from the <code>MyPage</code> unit tests, so that I know I wired it up to the form controls correctly</li>
  <li>Not have to use <code>ng-reflect-*</code></li>
  </ol>
  
  <p><strong>Other notes:</strong></p>
  
  <p>The <code>MyPage</code> component is a standard component with a <code>fromDate</code> (and a <code>zipCode</code>) field.</p>
  
  <p>The custom form field implements <code>ControlValueAccessor</code> correctly, has a <code>date</code> field, and uses an <code>&lt;input&gt;</code> internally, which itself is bound via <code>ngModel</code>:</p>
  
  <pre><code>&lt;input [(ngModel)]="date" type="date"&gt;
  </code></pre>
  
  <p><em>DatePickerComponent</em></p>
  
  <pre><code>@Component({
    selector: 'app-date-picker',
    templateUrl: './date-picker.component.html',
    styleUrls: ['./date-picker.component.scss'],
    providers: [{
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() =&gt; DatePickerComponent),
      multi: true
    }]
  })
  export class DatePickerComponent implements ControlValueAccessor {
  
    private propagateChange = (_: any) =&gt; {};
  
    private _date: string;
    get date(): string {
      return this._date;
    }
  
    @Input()
    set date(value: string) {
      this._date = value;
      this.propagateChange(value);
    }
  
    writeValue(newValue: any) {
      if (newValue !== undefined) {
        this.date = newValue;
      }
    }
  
    registerOnChange(fn: any) {
      this.propagateChange = fn;
    }
  
    registerOnTouched(fn: any) {
      // Not used
    }
  }
  </code></pre>
  
  <p><strong>UPDATE 8/10/2017</strong></p>
  
  <p>So far, I have gotten close to what I want with <code>@ViewChild</code>:</p>
  
  <pre><code>@Component(...)
  MyPageComponent {
   @ViewChild('fromDate') fromDatePicker: DatePickerComponent;
   ...
  }
  </code></pre>
  
  <p>The <code>MyPage</code> template becomes (note the template reference variable <code>#fromDate</code>):</p>
  
  <pre><code>&lt;app-date-picker #fromDate class="address__from-date" [(ngModel)]="fromDate"&gt;
  &lt;/app-date-picker&gt;
  </code></pre>
  
  <p>Then the test becomes:</p>
  
  <pre><code>it('should bind from-date', fakeAsync(() =&gt; {
    // model -&gt; view
    component.info.fromDate = '01/2017';
    fixture.detectChanges();
    tick();
  
    expect(component.fromDatePicker.date).toEqual('01/2017');
  
    // view -&gt; model
    component.fromDatePicker.date = '02/2017';
  
    expect(component.info.fromDate).toEqual('02/2017');
  }));
  </code></pre>
  
  <p>Anyone know of a better way? This gets me by for now, though it's not optimal.</p>