NBash
NBash

Reputation: 515

Test doesn't recognize the services called in ngOnInit

I want to add a test to some functionality I have in my component. In ngOnInit of my component, I'm calling a function that interacts with ChWidget service and it works fine. But the test fails because the ChWidget is undefined for it.

I was trying to mock this step but it didn't work well for me.

Could you advise if there is a proper way of handling this? Thank you!

Component:

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

import { ActionsService } from '@ch-common/ch-common.module';
import { Product } from '@ch-products/product';
declare var window;

@Component({
  selector: 'ch-container-header',
  templateUrl: './container-header.component.html',
  styleUrls: ['./container-header.component.scss']
})
export class ContainerHeaderComponent implements OnInit {
  @Input() container: any;

  product_group: any;

  constructor(private actions: ActionsService) { }

  ngOnInit() {
    if (this.isProductList()) {
      this.product_group = this.getGroupDetails(this.container);
    }
  }

  getGroupDetails(container) {
    var product = new Product(container.nodes[0].params.product)
    var group_id = window.ChWidget.utils.getQueryStringParam("product-group-id", document.location.href)

    return product.productBadgeIcons.find(obj => obj["group_id"] == group_id);
  }

  gotActions() {
    return (this.container.params.actions || []).length > 0;
  }
}

My test:

function setComponentParams(params) {
    component.container = params;
  }

  function renderComponentWithParams(params) {
    fixture = TestBed.createComponent(ContainerHeaderComponent);
    component = fixture.componentInstance;

    setComponentParams(params);
    fixture.detectChanges();
    compiled = fixture.debugElement.nativeElement;
  }


  fit('renders the show all if there is an action on the container and opens a product group page when clicking it', () => {
    var container = {
      nodes: [
        {params: {
            product: {
              group_id: '5bc56a4ee9b43a9df8491',
              group_name: 'Test Group'
            }
          }
        }
      ],
      params: {
        container_role: 'product_list',
        show_container_title: false,
        title: 'my fancy title',
        actions: [{type: 'openProduct', params: {id: '123'}}]
      }
    };

    renderComponentWithParams(container);
    fixture.detectChanges();

    const elem = element.querySelector('.container-action-tile');
    expect(elem).not.toBeNull();

    const actionsService = TestBed.inject(ActionsService);
    spyOn(actionsService, 'performActions');


    elem.click();
    fixture.detectChanges();
    expect(actionsService.performActions).toHaveBeenCalledWith(
      [{type: 'openProducts', params: {query_params: {filtered_group_id: '5bc56a4ee9b4351aa9df8491'}, title: 'Test Group'}}]
    );
  });
});

The error I am getting while running the test:

Cannot read property utils of undefined

enter image description here

Upvotes: 0

Views: 86

Answers (1)

AliF50
AliF50

Reputation: 18859

You have to mock the window object to have what you want.

function renderComponentWithParams(params) {
    fixture = TestBed.createComponent(ContainerHeaderComponent);
    component = fixture.componentInstance;
    
    window.ChWidget = {};
    window.ChWidget.utils = {};
    window.chWidget.utils.getQueryStringParam = () => 'the id you want';

    setComponentParams(params);
    fixture.detectChanges();
    compiled = fixture.debugElement.nativeElement;
  }

it('renders the show all if there is an action on the container and opens a product group page when clicking it') {
  ...
}

afterEach(() => {
  // Delete the ChWidget on the window because it will leak between tests.
  // Every test, you should mock it again.
  delete window.ChWidget;
});

Upvotes: 1

Related Questions