Error encountered during Jasmine unit testing for the ng-redux @select directive

Here is a snippet from my component.ts file:

import { Component, OnInit } from '@angular/core';
import { select } from 'ng2-redux';
import { Observable } from 'rxjs/Observable';
import { PersonalDetailsComponent } from '../personal-details/personal-details.component'

@Component({
  selector: 'app-profile-details',
  templateUrl: './profile-details.component.html'
})
export class ProfileDetailsComponent implements OnInit {

  @select(['customerData', 'personalDetails'])personalDetails:Observable<object>; //<------if i comment out @select statement, then the tests work 
  @select(['loading']) loading: Observable<boolean>;//<------if i comment out @select statement, then the tests work 

  constructor() { }

  ngOnInit() { }

}

Below is how my jasmine test for the ProfileDetailsComponent looks like:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NgRedux, select } from 'ng2-redux';
import { ProfileDetailsComponent } from './profile-details.component';
import { customerData } from '../data/customerProfileDataMock';
import { PersonalDetailsComponent } from '../personal-details/personal-details.component'
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';

class RouterStub { navigate(params) { } }
class MockSelect { }
class MockObservable<T> {}
class NgReduxStub {
  constructor() { }
  dispatch = () => undefined;
  getState = () => { return customerData; };
  subscribe = () => undefined;
}

describe('ProfileDetailsComponent', () => {
  let component: ProfileDetailsComponent;
  let fixture: ComponentFixture<ProfileDetailsComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ProfileDetailsComponent, PersonalDetailsComponent],
      providers: [
        { provide: Router, useClass: RouterStub },
        { provide: select, useClass: MockSelect },
        { provide: NgRedux, useClass: NgReduxStub },
        { provide: Observable, useClass: MockObservable }
      ],
    })
      .compileComponents();
  }));

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

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

});

Despite setting up mocks in the test, I'm encountering an issue where the @select statement is not being mocked correctly. This leads to an error when running the tests using the command 'ng test':

TypeError: ng_redux_1.NgRedux.instance is undefined in src/test.ts

Answer №1

It appears that there may have been some changes in the package you are using. I observed that ng2-redux on npm (https://www.npmjs.com/package/ng2-redux) now directs to the github repository https://github.com/angular-redux/store. This could indicate a merging of branches.

If this is the case, I recommend updating your package. A new feature called MockNgRedux has been recently introduced, which you can incorporate into your tests as follows:

import { NgReduxTestingModule, MockNgRedux } from '@angular-redux/store/testing';

To integrate this into TestBed, use the following:

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [
      NgReduxTestingModule,
    ],

You can utilize MockNgRedux to test components that utilize @select() by setting up values on specific selectors like this:

const stub = MockNgRedux.getSelectorStub(selector);
stub.next(values);
stub.complete();

It's worth noting that the methods are static and do not require an instance of MockNgRedux.

Remember to reset the mock store between tests:

beforeEach(() => {
  MockNgRedux.reset();
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating multiple ngApps in Angular 4, 5, or 6

In our organization, we are considering a transition from Struts/Servlets to Angular 6 with a complete rewrite. However, since we have limited experience with Angular technology, I have some concerns. I am contemplating creating a shared Angular micro-s ...

A guide on incorporating and utilizing third-party Cordova plugins in Ionic 5

Attempting to implement this plugin in my Ionic 5 application: https://www.npmjs.com/package/cordova-plugin-k-nfc-acr122u I have added the plugin using cordova plugin add cordova-plugin-k-nfc-acr122u but I am unsure of how to use it. The plugin declares: ...

Exploring Immediately Invoked Function Expressions in TypeScript

I came across an interesting article on self-invoking functions in JavaScript by Minko Gechev. This article teaches us how to create a JavaScript function that calls itself immediately after being initialized. I am curious about how we can achieve this in ...

What is the syntax for accessing elements from an iterable?

Is it possible to create a getter that acts like a function generator? My attempts class Foo { * Test1(): IterableIterator<string> { // Works, but not a getter... yield "Hello!"; } * get Test2(): IterableIterator<string> ...

How can I retrieve the value of a promise in Promise.map?

I am currently working on a project that involves saving data to a database using Mongoose. One specific field in the database is the 'thumbnail' field, which needs to be filled with a base64 converted file after the file is uploaded to the serve ...

I'm curious, which ref tag should I utilize for draft.js?

I'm currently working on a form using Draft.js with Next.js and TS, but I've encountered some errors in my code. Here is what I have so far: import {Editor, EditorState} from 'draft-js'; const [editorState, setEditorState] = useState( ...

What should I do to resolve the error when "HttpClient" name is not found?

Whenever I attempt to start my project using npm start, I encounter an error: [at-loader] Checking completed with 1 error [at-loader] ./node_modules/@ngx-translate/http-loader/src/http-loader.d.ts:10:23 TS2304: Cannot find name 'HttpClient' ...

Guide to sending jQuery data back to main class in TypeScript

Hi everyone, I'm diving into the world of typescript and JQuery. I have a simple question. In my typescript class called DatePicker, I am calling a function. Here's a snippet of the code: Class DatePicker { private pickerData; public update( ...

Attempting to implement a typeguard in Typescript that relies on the presence of specific content within an element

Currently, I am attempting to develop a Typescript conditional that verifies if a particular word is already present in the name. The function in question is as follows: isOrganic() { for (let i = 0; i < this.items.length; i++) { if(this.ite ...

Issue with props not being updated when Redux store state changes in Reactjs

When I make a call to the 'getGame' method after retrieving data from an API and updating the store, the props of my component do not update. However, everything works fine when using the 'getGames' method. I have confirmed that the ac ...

The overlay pop-up does not reposition on scroll movements

Within the image, there is a MatDialog Box positioned on top of another dialog box. Inside the MatDialog Box, there is a Component called MyNewDetailComponent. This component is accessed via Overlay with the scrollOptions set to reposition(). The issue ar ...

Issues with implementing Bootstrap icons in Angular are hindering functionality

As a beginner in Angular, I am currently working on creating a simple website using Angular and a Bootstrap template. However, I have encountered many issues along the way. Right now, I am struggling to utilize Bootstrap icons in my project. It appears tha ...

Enhancing native JavaScript types in TypeScript 1.8 with the power of global augmentation

Currently, I am working on expanding the capabilities of native JavaScript types using the new global augmentation feature in TypeScript 1.8, as detailed in this resource. However, I'm encountering difficulties when the extension functions return the ...

How can we add a key:value pair at a specific position in an array in Angular 2 using Typescript?

Is there a way to insert a key value pair at a specific index in an array? I am currently struggling with this task. Here is the code I have been working on: this.quiz.push( { "question-no":this.no, "Ans":this.ans } I require this functionality to ...

RxJS failing to properly merge the outcome of a subsequent HTTP request

Currently, I have a searchbox that utilizes three separate search APIs. Users can input either a string or a number. The API returns results differently based on the input type: for strings, it may return up to ten results; for numbers, a second GET reques ...

Customizing the Position of Material UI Select in a Theme Override

I'm trying to customize the position of the dropdown menu for select fields in my theme without having to implement it individually on each select element. Here's what I've attempted: createMuiTheme({ overrides: { MuiSelect: { ...

There is no mistake when using a value that falls outside of a TypeScript

Expecting to encounter a compile time error with this code, but it seems my understanding of enums is off... enum SortDirection { ascending = 1, descending = -1 } type IndexSpec = {[index: string]: SortDirection}; var i: IndexSpec = {thing: 3}; ...

Rendering a component in React based on multiple conditions

Checking sessionStorage and another state variable before rendering a component is essential for my application. I want to avoid showing the same message multiple times within the same session. This is how I have implemented it: const addSession = (noteId: ...

Establishing fixed values in an angular2 component

Is it possible in angular 2 to initialize values within the HTML view of a component that has already been rendered in PHP? //html page: <dropdown [(options)]="['Available', 'Busy', 'Away', 'Offline']"></dr ...

Ever tried asynchronous iteration with promises?

I have a specific code snippet that I am working on, which involves registering multiple socketio namespaces. Certain aspects of the functionality rely on database calls using sequelize, hence requiring the use of promises. In this scenario, I intend for t ...