Search code examples
javascriptangularunit-testingjasmine

Angular Jasmine unit test cases for mat-Autocomplete filter


I'm trying to write Angular unit test cases for filtering the mat-autocomplete options by inserting input data, but I couldn't able to do code coverage for value changes input.

app.component.html:

  <div class="container">
     <form [formGroup]="form">
        <mat-form-field>
           <input
           matInput
           type="text"
           formControlName="name"
           [matAutocomplete]="auto1"
           />
           <mat-autocomplete #auto1="matAutocomplete">
              <mat-option *ngFor="let data of data | async" [value]="data.name">
              {{ data.name }}
              </mat-option>
           </mat-autocomplete>
        </mat-form-field>
     </form>
   </div>

app.component.ts:

 import { Component, OnInit } from '@angular/core';
 import { FormBuilder, FormGroup } from '@angular/forms';
 import { map, Observable, startWith } from 'rxjs';

 @Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: [ './app.component.css' ]
 });
 export class AppComponent implements OnInit {

 data = [{
   "id": 1,
   "name": "One"
 },{
   "id": 2,
   "name": "Two"
 },{
   "id": 3,
    "name": "Three"
 }];

 form: FormGroup = this.formBuilder.group({
   name: [''],
 });

 constructor(private formBuilder: FormBuilder) {}

 ngOnInit() {
     this.filteredNames = this.form.controls['name'].valueChanges.pipe(
      startWith(''),
      map((value) => this.getFilterData(value))
    );
 }

   getFilterData(value) {
      const filterValue = value.toLowerCase();
      return this.data.filter((val) => val.name.toLowerCase().includes(filterValue));
   }
}

app.component.spec.ts:

        import { HttpClientTestingModule } from '@angular/common/http/testing';
        import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
        import { ComponentFixture, TestBed } from '@angular/core/testing';
        import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
        import { MatAutocompleteModule } from '@angular/material/autocomplete';
        import { MatFormFieldModule } from '@angular/material/form-field';
        import { MatInputModule } from '@angular/material/input';

        import { AppComponent } from './app.component';

        const mockData = [{
            "id": 1,
            "name": "One"
          },{
            "id": 2,
            "name": "Two"
          },{
            "id": 1,
            "name": "Three"
          }];

        describe('AppComponent', () => {
          let component: AppComponent;
          let fixture: ComponentFixture<AppComponent>;
          const formBuilder: FormBuilder = new FormBuilder();

          beforeEach(async () => {
            await TestBed.configureTestingModule({
              imports: [
                HttpClientTestingModule,
                FormsModule,
                ReactiveFormsModule,
                MatAutocompleteModule,
                MatFormFieldModule,
                MatInputModule,
              ],
              declarations: [AppComponent],
              schemas: [CUSTOM_ELEMENTS_SCHEMA],
              providers: [
                { provide: FormBuilder, useValue: formBuilder },
              ],
            }).compileComponents();
          });

          beforeEach(() => {
            fixture = TestBed.createComponent(AppComponent);
            component = fixture.componentInstance;
            fixture.detectChanges();
          });

          it('should create', () => {
            expect(component).toBeTruthy();
          });

          it('getSysValuechanges.', () => {
             const spyFilter = spyOn<any>(component, 'getFilterData');
             component.form.controls.name.setValue('Rambo');
             expect(spyFilter).toHaveBeenCalled();
          });
        });

Can anyone please help me to write test cases for valuechanges on mat-autocomplete input element.


Solution

  • I found it, forgot to create mock service & inject in to spec.

          let serviceSpy: jasmine.SpyObj<AppService>;
          serviceSpy.getData.and.returnValue(of(mockData as any));
    

    and inject the mock service.

           beforeEach(async () => {
            await TestBed.configureTestingModule({
              imports: [,,,,]
              declarations: [AppComponent],
              providers: [
                { provide: AppService, useValue: serviceSpy},
              ],
            }).compileComponents();
          });