Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Testing: FormControl valueChanges Observable

I have a text input and I'm listening for the changes.

component

name = new FormControl('',Validators.required);

ngOnInit() {
  this.data = 'oldvalue';
  this.checkName();
}

checkName() {
  this.name.valueChanges.subscribe(val=>{
     console.log(val);
     this.data= "newvalue"; // updating Value
  });
}

HTML

<input name="name" formControlName="name">

My Attempt so far:

component.spec.ts

it('should test data field ', () => {
    const fixture = TestBed.createComponent(UserComponent);
    const app=fixture.debugElement.componentInstance;
    const el = fixture.nativeElement.querySelector('input');
    el.value ='something';
    dispatchEvent(new Event(el));
    fixture.detectChanges();
    fixture.whenStable().then(()=>{expect(app.data).toBe('newvalue');
});

Problem: Even though input field is populated the code inside subscribe callback is never executed.

It always shows:

Expected 'oldvalue' to be 'newvalue'.

I tried setValue() method too but it did not work. it never goes inside subscribe callback

app.name.setValue('vikas');
fixture.detectChanges();
fixture.whenStable().then(()=>{expect(app.data).toBe('newvalue');

I referred Updating input html field from within an Angular 2 test and Angular2 Component: Testing form input value change but no luck :(

What am I missing?

like image 959
Vikas Avatar asked Aug 18 '18 16:08

Vikas


People also ask

What is type of ValueChanges in on a FormControl?

The ValueChanges is an event raised by the Angular forms whenever the value of the FormControl, FormGroup or FormArray changes. It returns an observable so that you can subscribe to it. The observable gets the latest value of the control. It allows us to track changes made to the value in real-time and respond to it.

How do you test Angular components?

To run your tests using the Angular CLI, you use the ng test command in your terminal. As a result, Karma will open up the default browser and run all the tests written with the aid of Jasmine and will display the outcome of those tests.

What are some of the different tests types you can write Angular?

You'll run across two types of tests when developing Angular applications: unit tests and E2E tests. You use unit tests to test the actual code, whereas you write E2E tests in a way that enables them to simulate user interactions. TypeScript is a language created by Microsoft that's a superset of JavaScript.


1 Answers

At first glance I think you missed the fact that your FormControl is not connected to input because you're using FormControlName directive that takes control name as @Input.

If you want to test FormControl then you can consider FormControlDirective that takes FormControl as @Input:

<input name="name" [formControl]="name">
                                  ^^^^^
                      `name` is FormControl instance here not string

Now we can be sure that whenever we change text in input your FormControl will fire changes. But as soon as you write such template angular will ask you for ReactiveFormsModule dependency in your test:

import { ReactiveFormsModule } from '@angular/forms';
....

TestBed.configureTestingModule({
   imports: [
     ReactiveFormsModule  <=== add this
   ],
   declarations: [TestComponent],
});

Now regarding your test.

1) You must tell the TestBed to perform data binding by calling fixture.detectChanges():

const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); <== add this

2) You should fire change on input correctly:

el.dispatchEvent(new Event('input'));

Here's the whole code:

it('should display original title', () => {
  const fixture = TestBed.createComponent(TestComponent);
  fixture.detectChanges();
  const app = fixture.debugElement.componentInstance;
  const el = fixture.nativeElement.querySelector('input');
  el.value = 'something';
  el.dispatchEvent(new Event('input'));
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(app.data).toBe('newvalue');
  });
});

Plunker Example

like image 74
yurzui Avatar answered Sep 16 '22 12:09

yurzui