0

I use template driven input and can not get its value in unit test unlike of reactive input.

Here are two same components one implemented with template driven approach and anoter one with using of reactive form.

@Component({
  template: '<input [(ngModel)]="model.value">'
})
export class QuestionTemplateInputComponent {
  public model: any;

  ngOnInit(): void {
    this.model = { 
      value: 'value' 
    };
  }
}

@Component({
  template: '<form [formGroup]="formGroup"><input formControlName="value"></form>'
})
export class QuestionReactiveInputComponent implements OnInit {
  public formGroup: FormGroup;
  
  constructor (
    private readonly formBuilder: FormBuilder
  ) { }
  
  ngOnInit(): void {
    this.formGroup = this.formBuilder.group({
      value: ['value']
    });
  }
}

And here are also two tests in order to verify each component.

  let fixture1: ComponentFixture<QuestionTemplateInputComponent>;
  let fixture2: ComponentFixture<QuestionReactiveInputComponent>;

  ...

  it('verifies template input', () => {
    fixture1.detectChanges();
    const input: HTMLInputElement = fixture1.nativeElement.querySelector('input');
  
    expect(input.value).toBe('value'); // FAIL: Expected '' to be 'value'.
  });

  it('verifies reactive input ', () => {
    fixture2.detectChanges();
    const input: HTMLInputElement = fixture2.nativeElement.querySelector('input');
  
    expect(input.value).toBe('value'); // PASSED
  });

Why only one of them passes?

MrDiemath
  • 57
  • 4
  • Does the template driven test pass if the `public model: any;` variable is initialized following way: `public model = { value: 'value' } `? In this case the `ngOnInit()` is removed. – Milan Tenk Jan 14 '21 at 20:27
  • 1
    I guess it has something to do with the fact, that template-driven forms are asynchronous. I found a conversation about this here, it might be helpful: https://stackoverflow.com/questions/58018506/initializing-template-driven-form-in-angular-7 – Milan Tenk Jan 14 '21 at 20:30
  • 1
    @MilanTenk that's right, thank you! I will use approach in testing which covers asynchronous implementations. – MrDiemath Jan 15 '21 at 15:42

1 Answers1

1

I think there are some async tasks that need to complete for the template approach, check this out.

Try this:

it('verifies template input', () => {
    fixture1.detectChanges();
    fixture.whenStable().then(() => {
       const input: HTMLInputElement = fixture1.nativeElement.querySelector('input');
       expect(input.value).toBe('value');
    });
  })

fixture.whenStable ensures that the current promises (async tasks) have completed before carrying forward.

AliF50
  • 16,947
  • 1
  • 21
  • 37