2

I am writing unit test for angular app, precisely angular6. I have mat-autocomplete in the code, all I want to test is the user filtered based on the input I type in the input box. I was inspired by the post enter link description here.

Here is the code snippet of spec file

  it('should filter customer',async () => {
    fixture.detectChanges();
    let toggleButton = fixture.debugElement.query(By.css('input'));
    console.log(toggleButton.nativeElement);

    toggleButton.nativeElement.dispatchEvent(new Event('focusin'));
    toggleButton.nativeElement.value = "xyz";
    toggleButton.nativeElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    await fixture.whenStable();
    fixture.detectChanges();

    const matOptions = document.querySelectorAll('mat-option');
    expect(matOptions.length).toBe(1); //test fails

  })


  <mat-form-field >
     <input id="inputCustomer" matInput [matAutocomplete]="auto"  [formControl]="customerFilterControl">
     <mat-autocomplete panelWidth ="450px" #auto="matAutocomplete" [displayWith] = "displayFn" style="width:750px;">
         <mat-option  *ngFor="let customer of filteredOptions | async" [value] ="customer.AccountID + '('+ customer.AccountName + ')'" (onSelectionChange)="onCustomerChange(customer)">
         {{customer.AccountID}} ({{customer.AccountName}})
        </mat-option>
     </mat-autocomplete>
  </mat-form-field>

**typescript.ts**
    this.filteredOptions = this.customerFilterControl.valueChanges.pipe(
      startWith(''),
      map(value => this._filter(value))
    );  


  _filter(value:any):any[] {
    const filterValue = value.toLowerCase();
    return this.customers.filter(function (option) {
      if(option.AccountID.includes(filterValue) || option.AccountName.includes(filterValue)) {
        return option;
       }
    });
  }

enter image description here

karansys
  • 2,449
  • 7
  • 40
  • 78

1 Answers1

0

You seem to be missing initializing your options

  it('should filter customer',async () => {
    // Prepare the data
    const option1 = {AccountID: 1, AccountName: 'AccountName1'};
    const option2 = {AccountID: 2, AccountName: 'xyz'}
    // Prepare the data source
    fixture.component.filteredOptions = of([option1,option2])
    fixture.detectChanges();
    let toggleButton = let toggleButton = fixture.debugElement.query(By.css('#inputCustomer'));
    console.log(toggleButton.nativeElement);

    toggleButton.nativeElement.dispatchEvent(new Event('focusin'));
    toggleButton.nativeElement.value = "xyz";
    toggleButton.nativeElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    await fixture.whenStable();
    fixture.component._filter("xyz");
    fixture.detectChanges();

    const matOptions = document.querySelectorAll('mat-option');
    expect(matOptions.length).toBe(1); //test fails

  })

This way your component will have some values to select from when you add the autocomplete values.

Bear in mind that you should use the of operator (let me know if it works as I have not tested it) for the async pipe to work.

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61