Search code examples
ionic-frameworkjasminekarma-jasminecapacitor

Ionic 5 + Jasmine test whether SplashScreen.hide() was called fails (update to Capacitor 3)


I have a problem to pass a unit test that worked before. I'm trying to update my Ionic project from Capacitor 2 to Capacitor 3 and have a problem to integrate the new SplashScreen plugin. Here is my app.component.ts class:

import { Component } from '@angular/core';
import { SplashScreen } from '@capacitor/splash-screen';
import { Platform } from '@ionic/angular';
import { TranslateService } from '@ngx-translate/core';
import { AuthenticationService } from './api/authentication.service';
import { SettingsService } from './services/settings.service';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  constructor(private platform: Platform, private translate: TranslateService,
      private settingsService: SettingsService, private authService: AuthenticationService ) {
    this.initializeApp();
    this.authService.logIn();
  }
  
  private splashScreen = SplashScreen;

  initializeApp() {
    if (this.platform.is('hybrid')) {
      this.platform.ready().then(() => {
        console.log("It's a hybrid context!")
        this.splashScreen.hide().then(()=>console.log("SplashScreen hidden"));
        console.log("Platform ready, SplashScreen hidden")
      });
    }

    /** Set default language */
    this.translate.setDefaultLang('en');
    this.translate.use(this.settingsService.getUserLanguage());
  }

}

And here is my app.component.spec.ts file:

import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TestBed, waitForAsync } from '@angular/core/testing';
import { SplashScreen } from '@capacitor/splash-screen';
import { Platform } from '@ionic/angular';
import { TranslateModule } from '@ngx-translate/core';
import { AppComponent } from './app.component';

describe('AppComponent', () => {

  let splashScreenSpy, platformReadySpy, platformSpy;

  beforeEach(waitForAsync(() => {

    splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']);
    platformReadySpy = Promise.resolve();
    platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy, is: (type: string) => { 
      if (type === 'hybrid') {
        return true; 
      } else { 
        return false; 
      } 
    }});

    console.log("Configuring Testing Module")

    TestBed.configureTestingModule({
      declarations: [AppComponent],
      imports: [TranslateModule.forRoot()],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      providers: [
        { provide: Platform, useValue: platformSpy },
        { provide: SplashScreen, useValue: splashScreenSpy }
      ]
    }).compileComponents();
    
    console.log("Testing Module configured")
  }));
  
  it('hides the splash screen', waitForAsync (()  => {
    (platformSpy.is as any).withArgs('hybrid').and.returnValue(true);
    TestBed.createComponent(AppComponent).whenStable().then(() => {
      expect(platformSpy.ready).toHaveBeenCalled();
      console.log("Check whether splash screen will be hidden is going to start now")
      expect(splashScreenSpy.hide).toHaveBeenCalled();
      console.log("Check whether splash screen will be hidden is finished")
    });
  }));

The last expect fails with following error:

LOG: 'Configuring Testing Module'
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 0 of 48 SUCCESS (0 secs / 0 secs)
LOG: 'Testing Module configured'
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 0 of 48 SUCCESS (0 secs / 0 secs)
LOG: 'It's a hybrid context!'
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 0 of 48 SUCCESS (0 secs / 0 secs)
LOG: 'Platform ready, SplashScreen hidden'
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 0 of 48 SUCCESS (0 secs / 0 secs)
LOG: 'SplashScreen hidden'
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 0 of 48 SUCCESS (0 secs / 0 secs) 
LOG: 'Check whether splash screen will be hidden is going to start now'
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 0 of 48 SUCCESS (0 secs / 0 secs)
LOG: 'Check whether splash screen will be hidden is finished'
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 0 of 48 SUCCESS (0 secs / 0 secs)
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1) AppComponent hides the splash screen FAILED
    Error: Expected spy SplashScreen.hide to have been called.
        at <Jasmine>
        at src/app/app.component.spec.ts:51:36
        at ZoneDelegate.invoke (node_modules/zone.js/dist/zone-evergreen.js:372:1)
        at AsyncTestZoneSpec.push.QpwO.AsyncTestZoneSpec.onInvoke (node_modules/zone.js/dist/zone-testing.js:1248:1)
Chrome Headless 90.0.4427.0 (Mac OS 11.5.1): Executed 1 of 48 (1 FAILED) (0 secs / 2.194 secs)

I've already spent 8 hours and tried many different approaches, but it still doesn't pass. Do you have an idea what's wrong here?

Best regards Valdes


Solution

  • This is the official guide describing how to mock a Capacitor plugin with Jasmine: https://capacitorjs.com/docs/guides/mocking-plugins

    You have to create stub files in __mocks__/@capactor and add a path to your tsconfig.spec.ts.