1

I am trying to test my component. The components receives an observable string and object as an input and iterates over this object and makes some calculations.

The component works fine in a browser, but throws an error when I execute the unit test:

Chrome 65.0.3325 (Mac OS X 10.13.1) ERROR
  Disconnected, because no message in 10000 ms.
Chrome 65.0.3325 (Mac OS X 10.13.1): Executed 1 of 116 DISCONNECTED (10.136 secs / 0.092 secs)
Chrome 65.0.3325 (Mac OS X 10.13.1) ERROR
Chrome 65.0.3325 (Mac OS X 10.13.1): Executed 1 of 116 DISCONNECTED (10.136 secs / 0.092 secs)

So i’ve started simplifying the component but still don't understand why the tests are failing.

My component's template:

<div *ngIf="hasDestinationFilter"></div>

<div *ngFor="let shipment of (filteredShipments$ | async)"></div>

TypeScript:

import { Component, Input, OnInit } from '@angular/core';

import { Observable } from 'rxjs/Observable';

import 'rxjs/add/observable/combineLatest';
import 'rxjs/add/operator/map';

import { ShipmentFilterService } from '../../services/shipment-filter/shipment-filter.service';

@Component({
  selector: 'search-results',
  templateUrl: './search-results.component.html',
})
export class SearchResultsComponent implements OnInit {
  @Input() searchResults$: Observable<any>;
  @Input() destination$: Observable<string>;

  filteredShipments$: Observable<any[]>;
  hasDestinationFilter = false;

  constructor(private shipmentFilterService: ShipmentFilterService) {}

  ngOnInit() {
    this.filteredShipments$ = Observable
      .combineLatest(this.searchResults$, this.destination$)
      .map(([ { shipments }, destination ]) => {
        this.hasDestinationFilter = this.shipmentFilterService.hasDestinationFilter(shipments);

        if (this.hasDestinationFilter) {
          return shipments;
        }
        return shipments;
      });
  }
}

My unit test:

import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

import { Observable } from 'rxjs/Observable';

import { ShipmentFilterService } from '../../services/shipment-filter/shipment-filter.service';
import { SearchResultsComponent } from './search-results.component';

describe('SearchResultsComponent', () => {
  let mockedHasDestinationFilter;

  const mockedShipment = {
    collectedDate: null,
    collectionCity: null,
    collectionDate: null,
    consignmentKey: null,
    consignmentNumber: null,
    customerReference: null,
    deliveryDueDate: null,
    deliveryTown: null,
    destinationCountry: null,
    fedexNumber: null,
    fromDate: null,
    originCountry: null,
    pieceQuantity: null,
    podFound: null,
    revisedDeliveryDate: null,
    shipmentId: null,
    signatory: null,
    signatoryFound: false,
    statusData: [],
    toDate: null,
    trackId: null,
  };

  const shipmentFilterServiceStub = {
    hasDestinationFilter: () => mockedHasDestinationFilter,
  };

  beforeEach(async(() => {
    TestBed
      .configureTestingModule({
        declarations: [
          SearchResultsComponent,
        ],
        providers: [
          { provide: ShipmentFilterService, useValue: shipmentFilterServiceStub },
        ],
        schemas: [
          NO_ERRORS_SCHEMA,
        ],
      })
      .compileComponents();
  }));

  function getComponent(destination = null) {
    let component: SearchResultsComponent;
    let fixture: ComponentFixture<SearchResultsComponent>;

    fixture = TestBed.createComponent(SearchResultsComponent);
    component = fixture.componentInstance;

    component.searchResults$ = Observable.of({
      query: {
        input: 'abc123',
      },
      shipments: [
        mockedShipment,
        mockedShipment,
        mockedShipment,
        mockedShipment,
        mockedShipment,
      ],
    });
    component.destination$ = Observable.of(destination);
    fixture.detectChanges();

    return fixture;
  }

  describe('optionally filters shipments by destination', () => {
    it('shows all shipments when there is no destination filter', () => {
      mockedHasDestinationFilter = false;
      const component = getComponent();

      expect(component.debugElement.queryAll(By.css('pb-shipment')).length).toBe(5);
    });

    fit('shows all shipments when there is destination filter, but no destination has been chosen', () => {
      mockedHasDestinationFilter = true;
      const component = getComponent('');
    });
  });
});

It's hard to understand where the problem since unit tests fails with timeout, but I noticed if I remove <div *ngIf="hasDestinationFilter"></div> or <div *ngFor="let shipment of (filteredShipments$ | async)"></div> from my templates the tests doesn't fail with timeout. Where can be my mistake?

1 Answer 1

1

Try to initialize the values of your inputs with default values

@Input() searchResults$: Observable<any> = Observable.from("");
@Input() destination$: Observable<string> = Observable.from("");

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.