Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5 component testing select and triggered event

I have a component which has a dropdown. When changed it triggers an event which filters through an array to get the selectedProduct from an array based on the event value.

My code is as follows:

  public onProductChanged(event): void {
    this.selectedProduct = this.products.find((product: Products) => product.id == event.target.value);
  }

My select dropdown:

<select id="product" (change)="onProductChanged($event)">
    <option>--- Please Select ---</option>
    <option *ngFor="let product of products" [value]="product.id"> {{ product.displayName }} </option>
</select>

The product object is an object:

{ "id": 1, "name": "name_here", "displayName": "Name Here" }

This all works however I want to test in my component test that changing the select value triggers the event and the correct value is retrieved.

My test code is as follows:

  describe('Product selection', () => {
    it('should select product', () => {

      expect(component.selectedProduct).toBeUndefined();
      productSelectElement.nativeElement.value = 'Product Name';
      productSelectElement.nativeElement.dispatchEvent(new Event('change'));

      fixture.detectChanges();

      expect(component.onProductChanged).toHaveBeenCalled();
      expect(component.selectedProduct).toEqual({ "id": 1, "name": "product_name", "displayName": "Product Name" });
    });
  });

The productChanged event has been called and that test passes. My selectedProduct is however always null. How do I get the event to fire using the changed value in the dropdown?

like image 715
Steve Fitzsimons Avatar asked Nov 30 '17 14:11

Steve Fitzsimons


People also ask

What is the correct way to trigger click event on a button when testing an Angular component?

For click event we can use triggerEventHandler method of Angular DebugElement class. We can also call native JavaScript click method of button. On click of button, we call a component method and it is possible that our component method has other dependencies to execute.

What is fixture detectChanges ()?

fixture is a wrapper for our component's environment so we can control things like change detection. To trigger change detection we call the function fixture.detectChanges() , now we can update our test spec to: Copy it('login button hidden when the user is authenticated', () => { expect(el. nativeElement.

What is Componentfixture in Angular testing?

You can create a component fixture with TestBed. createComponent . Fixtures have access to a debugElement , which will give you access to the internals of the component fixture. Change detection isn't done automatically, so you'll call detectChanges on a fixture to tell Angular to run change detection.

How do you trigger event in Jasmine?

According to the Angular Testing documentation, to trigger the events from the tests, we use the triggerEventHandler() method on the debug element. This method takes the event name and the object .


1 Answers

Turns out that in the before each I had set a spyOn for the function without a call through. Working code is as follows:

  beforeEach(() => {
    fixture = TestBed.createComponent(SelectProductsComponent);
    component = fixture.componentInstance;
    component.products = products;
    fixture.detectChanges();

    productSelectElement = fixture.debugElement.query(By.css('#products'));

    spyOn(component, 'onProductChanged').and.callThrough();

    expect(component.products).toEqual(products);
    expect(component.selectedProduct).toBeUndefined();
  });

  describe('Product selection', () => {
    it('should select product', () => {

      productSelectElement.nativeElement.value = 1;
      productSelectElement.nativeElement.dispatchEvent(new Event('change'));

      fixture.detectChanges();

      expect(component.onProductChanged).toHaveBeenCalled();
      expect(component.selectedProduct).toEqual({ "id": 1, "name": "product_name", "displayName": "Product Name" });

    });
  });
like image 63
Steve Fitzsimons Avatar answered Nov 11 '22 23:11

Steve Fitzsimons