0
votes

I'm new to angular 2, can someone please explain to me, how to properly test a component with an observable inside (using the async pipe)

The error is : Cannot read property 'next' of undefined

I think it's because the Observable don't have enough time to instanciate the observer, so in the subscribe method _mockObserver is undefined

Can you help me ?

Code :

@Component({
   moduleId: module.id,
   selector: 'app-list',
   templateUrl: 'list.component.html',
   styleUrls: ['list.component.css']
 })
export class ListComponent implements OnInit {

@Input() objects$: Observable<Object[]>;

constructor() {
}

ngOnInit() {

}

}


<tr *ngFor="let object of objects$ | async">
  <td >{{ object.id }}</td>
  <td id="field1">{{ object.field1}}</td>
  <td id="field2">{{ object.field2}}</td>
  <td id="field3">{{ object.field3}}</td>
  <td>
  <i class="fa fa-pencil-square font-list" aria-hidden="true"></i>
  <i class="fa fa-trash font-list" aria-hidden="true"></i>
</td>
</tr>

My test who don't work :

it('should display the object', inject([], () => {
 builder.createAsync(ListComponentTestController)
  .then((fixture: ComponentFixture<any>) => {
    let listCmp = fixture.componentInstance;
    let _mockObserver: Observer<Object[]>;

    listCmp.recipe$ = new Observable<Object[]>(observer => {
      this._mockObserver = observer;
    });

    Observable.of(MOCK)
      .map(MOCKOBJECT => MOCKOBJECT ).subscribe(data => {
        // Push the new list of users into the Observable stream
        this._mockObserver.next(data);
        fixture.detectChanges();
        let objectElement = fixture.nativeElement;
        expect(objectElement.querySelector('#id')).toHaveText("looooooooool");

      }, error => console.log('Could not load mock.'));

  });

}));

I tried that :

 it('Should display two list items', () => {
        // Arrange
        const MOCK_DATA = [{
            id: 10,
            field1: 'Field 10',
            field2: 'Field 20',
            field3: 'Field 30',
        }, {
            id: 11,
            field1: 'Field 11',
            field2: 'Field 21',
            field3: 'Field 31',
        }];
        fixture.componentInstance.objects$ = Observable.of(MOCK_DATA);

        // Act
        fixture.detectChanges();

        // Assert
        const element = fixture.nativeElement;
        expect(element.getElementsByTagName('tr').length).toBe(2);
    });
});

But didn't work either

Thanks by advance

1

1 Answers

1
votes

You don't subscribe on listCmp.recipe$ so the corresponding initialization function isn't called and _mockObserver isn't initialized.

I would add the following:

listCmp.recipe$ = new Observable<Object[]>(observer => {
  this._mockObserver = observer;
});
listCmp.recipe$.subscribe((data) => {
});