Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 2 ViewController unit testing

mIve got the following unit tests that tests a Component I have written in Ionic 2. The unit tests gives an error from one of the Ionic libraries, I assume that I am not mocking it out properly or as such

import { ComponentFixture, async } from '@angular/core/testing';
import { TestUtils }               from '../../test';
import {} from 'jasmine';

import { LocationSearchModal } from './LocationSearchModal';
import { LocationService } from '../../services/LocationService';
import { PouchDbService } from '../../services/common/PouchDbService';

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TestBed } from '@angular/core/testing';
import { App, MenuController, NavController, Platform, Config, Keyboard, Form, IonicModule, ViewController, GestureController, NavParams }  from 'ionic-angular';
import { ConfigMock } from '../../mocks';
import { TranslateModule } from 'ng2-translate';
import { LoadingController } from 'ionic-angular';

let fixture: ComponentFixture<LocationSearchModal> = null;
let instance: any = null;

describe('LocationSearchModal', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        LocationSearchModal
      ],
      providers: [
        App, Platform, Form, Keyboard, MenuController, NavController, GestureController, LocationService, LoadingController,
        { provide: ViewController, useClass: class { ViewController = jasmine.createSpy("viewController"); } },
        { provide: NavParams, useClass: class { NavParams = jasmine.createSpy("navParams"); } },
        { provide: PouchDbService, useClass: class { PouchDbService = jasmine.createSpy("pouchDbService"); } },
        {provide: Config, useClass: ConfigMock}
      ],
      imports: [
        FormsModule,
        IonicModule,
        ReactiveFormsModule,
        TranslateModule.forRoot(),
      ],
    })
    .compileComponents()
    .then(() => {
      fixture = TestBed.createComponent(LocationSearchModal);
      instance = fixture.debugElement.componentInstance;
      fixture.autoDetectChanges(true);
    });
  }));

  afterEach(() => {
    fixture.destroy();
  });

  it('loads', () => {
    expect(fixture).not.toBeNull();
    expect(instance).not.toBeNull();
  })
})

This is the relevant excerpt which uses the ViewController from the component that is being tested.

this.locationService.getLocationById(this.selectedLocation)
      .subscribe((location: any) => {
        this.viewController.dismiss(location.doc)
      });

The test fails and I get the following stack trace

  Chrome 53.0.2785 (Linux 0.0.0)
TypeError: viewCtrl._setHeader is not a function
    at new Header (webpack:///home/milinda/workspaces/eclipse/inspection/addedinspection/Inspection-Upgrade/~/ionic-angular/components/toolbar/toolbar.js:14:0 <- src/test.ts:11833:30)
    at new Wrapper_Header (/IonicModule/Header/wrapper.ngfactory.js:7:18)

This is related to the ViewController line which I have created a jasmine spy for

{ provide: ViewController, useClass: class { ViewController = jasmine.createSpy("viewController"); } },

After having a look at the code base I found the _setHeader method in here

https://github.com/driftyco/ionic/blob/6b3e2ed447340cdd35c328c96aa7cfa5f34eb214/src/navigation/view-controller.ts#L364

I also tried writing a custom provider but got the same error as well. Any idea on what is the correct method of testing the ViewController.

Additionally sometimes after resolving the ViewController issue an issue may occur from NavParams perhaps

like image 764
MilindaD Avatar asked Nov 29 '22 22:11

MilindaD


2 Answers

Building on Marky Sparky's answer. As of ionic 3+:

export class ViewControllerMock{
  readReady = {
    subscribe(){

    }
  };
  writeReady = {
    subscribe(){

    }
  };

  dismiss(){
    console.log('View Controller Dismiss Called');
  }
  _setHeader(){

  }
  _setNavbar(){

  }
  _setIONContent(){

  }
  _setIONContentRef(){

  }
}

Working on version:

Cordova CLI: 6.5.0 
Ionic Framework Version: 3.0.1
Ionic CLI Version: 3.0.0-beta7
ios-deploy version: 1.9.1 
ios-sim version: Not installed
OS: macOS Sierra
Node Version: v7.8.0
Xcode version: Xcode 8.3.2 Build version 8E2002
like image 155
James Macmillan Avatar answered Dec 06 '22 11:12

James Macmillan


I had the same issue when referring to ViewController in unit tests. I just solved it. Create a mock like this

class ViewControllerMock {
  public _setHeader(): any {
    return {}
  };
  public _setIONContent(): any {
    return {}
  };
  public _setIONContentRef(): any {
    return {}
  };
}

Then add it to your providers in the call to TestBed.configureTestingModule like this:

TestBed.configureTestingModule({
  declarations: [
    ...components,
    OrdinalPipe,
    IgnoreNulls
  ],
  providers: [
    NavController,
    ChartsService, FundsService, Utils, BlogService
    , Payment, PlanHelper, Storage, PalIdle, SimpleExpiry, ContentService, PlansService,
    App, Platform, Form, Keyboard, MenuController,
    { provide: ModalController, useClass: ModalControllerMock },
    { provide: ViewController, useClass: ViewControllerMock },
    { provide: Config, useClass: ConfigMock }
  ],
  imports: [
    FormsModule,
    IonicModule,
    ReactiveFormsModule,
  ],
})

This worked for me when I had the viewCtrl._setHeader is not a function error earlier today. Hope it helps.

like image 29
Marky Sparky Avatar answered Dec 06 '22 13:12

Marky Sparky