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?

3
  • 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. Commented Jan 14, 2021 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: stackoverflow.com/questions/58018506/… Commented Jan 14, 2021 at 20:30
  • 1
    @MilanTenk that's right, thank you! I will use approach in testing which covers asynchronous implementations. Commented Jan 15, 2021 at 15:42

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.