Ionic,  Code,  Testing

Testing Ionic presentables

Testing Ionic presentables

I frequently come across the question of how we can test a presentable in Ionic. A presentable is component that is presented in a separate navigation stack like a Modal, an Alert, an ActionSheet, a Toast, a LoadingModal etc.

Our code will normally look like:

private openEditorModal() {
  const modal = this._modal.create(MyModalComponent);
  modal.onDidDismiss((data: { note: string }) => {
    this.note = data.note;
  });
  modal.present();
}

So how can we test that this.note will take the value returned from the modal? We need a way to trigger onDidDismiss. After gathering a few similar cases that I wanted to test I came up with a mock that can be used to test such functionality, mimicking the behaviour of normal presentables.

export class PresentableControllerMock {
  public presentableRef = {
    present: () => Promise.resolve(),
    dismiss: (data?: any) => {
      if (this.dismissCallbackFn) {
        this.dismissCallbackFn(data);
      }
      return Promise.resolve({});
    },
    onDidDismiss: (fn) => {
      this.dismissCallbackFn = fn;
    }
  };

  public dismissCallbackFn = null;

  public create(options?) {
    return Object.assign(this.presentableRef, options);
  }
}

Now this opens up a few possibilities in our tests. Let’s have a look at a simple case first.

it('updates the note if it is edited', function () {
  const modalCtrl = fixture.debugElement.injector.get(ModalController);
  spyOn(modalCtrl, 'create').and.callThrough();
  const modal = (<PresentableControllerMock>(<any>modalCtrl)).presentableRef;
  spyOn(modal, 'present').and.callThrough();

  sut.openEditorModal();

  expect(modal.present).toHaveBeenCalled();
  modal.dismiss({ note: 'new note' });

  expect(sut.notes).toEqual('new note');
});

Thanks for reading! To stay updated on my latest posts and thoughts, follow me on Twitter @masimplo

Subscribe to masimplo.com

Get the latest posts delivered right to your inbox