How to Mock History.state for writing unit tests in angular
Asked Answered
B

3

9

I am writing unit tests for my component but having trouble in creating the instance of the component and showing following error,

TypeError: Cannot read property 'patientId' of null 

I have tried mocking all the providers including router and active router My component.ts is

export class PatientInsurancePlanSearchComponent implements OnInit {

  private patientId: number = -1;
  public selectedOrganizationInsurance: OrganizationInsurance;
  public organizationInsurancePlans$: Observable<OrganizationInsurancePlan[]>;

  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,
    private biilingHttpService: BillingHttpService
  ) {
    this.selectedOrganizationInsurance = new OrganizationInsurance();
  }

  ngOnInit() {
    this.patientId = history.state.patientId as number;
    this.selectedOrganizationInsurance = history.state.selectedOrganizationInsurance as OrganizationInsurance;
    this.organizationInsurancePlans$ = this.biilingHttpService.getOrganizationInsurancePlans(this.selectedOrganizationInsurance.id);
  }

spec.ts

class FakeInsurancePlanSearchComponent {
  @Input() public organizationInsurancePlans: OrganizationInsurancePlan[] = [];
  @Input() public selectedOrganizationInsurance: OrganizationInsurance;
  }
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ PatientInsurancePlanSearchComponent
      , FakeInsurancePlanSearchComponent ],
      imports: [
        StoreModule.forRoot({}),
        HttpClientModule,
        RouterTestingModule,
      ],
      providers: [
        Store,
        {
          provide: ActivatedRoute, useValue: {
            state: of({ selectedorganizationInsurancePlan: 'AETNA'})
        }
      },
      BillingHttpService
      ]
    })
    .compileComponents();
  }));

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

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

Kindly guide me whats i am missing..

Bernadettebernadina answered 5/11, 2019 at 13:10 Comment(0)
G
19

If you want to add patientId to the browsers session history stack, you can simply use:

history.pushState(state, title, url);

In your case it should be something like this:

describe(MyComponent.name, () => {
   ...

   beforeEach(() => {
       window.history.pushState({ patientId: 'somevalue'}, '', '');

       ...
   })


   it('...', () => {

   })
}
Gurtner answered 24/1, 2020 at 15:55 Comment(2)
please accept this as a valid answer: is works as a perfect mockMerely
This is working for me, thank you. However, when I use history.pushState(state, title, URL); in another component to mock history.state, My whole Karma tests stop, and I get a NOT FOUND message. Has anyone encountered this? If so, would you know how to go about this error? Cheers.Deckard
F
2

If you are using Jasmine testing framework, you can simply mock the history using below code

spyOnProperty(window.history, 'state').and.returnValue({ patientId: someValue });
Forjudge answered 17/3 at 17:37 Comment(0)
L
0

Simple answer:

You can provide the state in :

provideMockStore({ initialState: your_state })

or

mockStore.setState(your_state );

BUT I suggest you do do the following if you have a complex store:

  • create a class where you will have your mock store state: MockStoreState.

type RecursivePartial<T> = {
  [P in keyof T]?:
  T[P] extends (infer U)[] ? RecursivePartial<U>[] :
    T[P] extends object ? RecursivePartial<T[P]> :
      T[P];
};

export class MockStoreState {
  private store_a: RecursivePartial<Store_A>;
  private store_b: RecursivePartial<Store_b>;

  build(): any {
    const defaultStore_a = {
      ...
    };
    const defaultStore_b = {
      ...
    };

    return {
      store_a: { ...defaultStore_a , ...this.store_a},
      store_b: { ...defaultStore_b , ...this.store_b },
    };
  }

  setStore_a(value: RecursivePartial<Store_A>): Store_A_State {
    this.store_a= value;
    return this;
  }

  setStore_b(value: RecursivePartial<DatasourceState>): Store_B_State {
    this.store_b= value;
    return this;
  }
}
  • Set the state in your store in the test:
describe(MyComponent.name, () => {
   ...
   let mockStore: MockStore<any>;

   beforeEach(() => {
       ...
       mockStore = TestBed.get(Store);
   })


   it('...', () => {
     const state = new MockStoreState().setStore_a({...})
    .build();

    mockStore.setState(state);

   // HERE you have set the data in your store.
   })
}
Lessen answered 5/11, 2019 at 13:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.