ionic-team / ionic-unit-testing-example

Example of adding unit testing in your Ionic 2.x or greater apps with Karma and Jasmine
Other
374 stars 145 forks source link

Cannot read property Ionic of undefined #93

Closed davidwillianx closed 6 years ago

davidwillianx commented 6 years ago

I'm trying to unit test my app and I got message :

    Failed: Cannot read property 'Ionic' of undefined
        at <Jasmine>
        at E (webpack:///node_modules/ionic-angular/config/config.js:363 <- test-config/karma-test-shim.js:956:92100)
        at webpack:///node_modules/@angular/core/esm5/core.js:10960 <- test-config/karma-test-shim.js:298:1193
        at fi (webpack:///node_modules/@angular/core/esm5/core.js:10910 <- test-config/karma-test-shim.js:298:1349)
        at webpack:///node_modules/@angular/core/esm5/core.js:10860 <- test-config/karma-test-shim.js:313:8938
        at new t (webpack:///node_modules/@angular/core/esm5/core.js:12115 <- test-config/karma-test-shim.js:313:8948)
        at Ri (webpack:///node_modules/@angular/core/esm5/core.js:12104 <- test-config/karma-test-shim.js:313:8601)
        at Object.Xo [as createNgModuleRef] (webpack:///node_modules/@angular/core/esm5/core.js:14438 <- test-config/karma-test-shim.js:363:2428)
        at e.create (webpack:///node_modules/@angular/core/esm5/core.js:15576 <- test-config/karma-test-shim.js:371:436)
        at t._initIfNeeded (webpack:///node_modules/@angular/core/esm5/testing.js:1006 <- test-config/karma-test-shim.js:725:5278)
        at t.createComponent (webpack:///node_modules/@angular/core/esm5/testing.js:1138 <- test-config/karma-test-shim.js:725:8455)
        at Function.t.createComponent (webpack:///node_modules/@angular/core/esm5/testing.js:837 <- test-config/karma-test-shim.js:725:2576)
        at UserContext.<anonymous> (webpack:///src/app/app.component.spec.ts:38:22 <- test-config/karma-test-shim.js:1066:146072)
        at t.invoke (webpack:///node_modules/zone.js/dist/zone.js:388 <- test-config/karma-test-shim.js:768:7001)
        at t.onInvoke (webpack:///node_modules/zone.js/dist/async-test.js:106 <- test-config/karma-test-shim.js:925:1819)
        at t.onInvoke (webpack:///node_modules/zone.js/dist/proxy.js:125 <- test-config/karma-test-shim.js:872:2235)
        at t.invoke (webpack:///node_modules/zone.js/dist/zone.js:387 <- test-config/karma-test-shim.js:768:6941)
        at e.runGuarded (webpack:///node_modules/zone.js/dist/zone.js:151 <- test-config/karma-test-shim.js:768:2374)
        at a (webpack:///node_modules/@angular/core/esm5/testing.js:107 <- test-config/karma-test-shim.js:697:17982)
        at UserContext.<anonymous> (webpack:///node_modules/@angular/core/esm5/testing.js:46 <- test-config/karma-test-shim.js:697:17044)
        at t.invoke (webpack:///node_modules/zone.js/dist/zone.js:388 <- test-config/karma-test-shim.js:768:7001)
        at t.onInvoke (webpack:///node_modules/zone.js/dist/proxy.js:128 <- test-config/karma-test-shim.js:872:2261)
        at t.invoke (webpack:///node_modules/zone.js/dist/zone.js:387 <- test-config/karma-test-shim.js:768:6941)
        at e.run (webpack:///node_modules/zone.js/dist/zone.js:138 <- test-config/karma-test-shim.js:768:2171)
        at l (webpack:///node_modules/zone.js/dist/jasmine-patch.js:142 <- test-config/karma-test-shim.js:910:1303)
        at UserContext.<anonymous> (webpack:///node_modules/zone.js/dist/jasmine-patch.js:158 <- test-config/karma-test-shim.js:910:1380)
        at <Jasmine>
        at t.invokeTask (webpack:///node_modules/zone.js/dist/zone.js:421 <- test-config/karma-test-shim.js:768:7685)
        at e.runTask (webpack:///node_modules/zone.js/dist/zone.js:188 <- test-config/karma-test-shim.js:768:2865)
        at m (webpack:///node_modules/zone.js/dist/zone.js:595 <- test-config/karma-test-shim.js:768:9934)
    Expected false to be true.

webpack.test.js

var webpack = require('webpack');
var path = require('path');

module.exports = {
  devtool: 'inline-source-map',

  resolve: {
    extensions: ['.ts', '.js']
  },

  module: {
    rules: [{
        test: /\.ts$/,
        loaders: [{
          loader: 'ts-loader'
        }, 'angular2-template-loader']
      },
      {
        test: /.+\.ts$/,
        exclude: /(index.ts|mocks.ts|\.spec\.ts$)/,
        loader: 'istanbul-instrumenter-loader',
        enforce: 'post',
        query: {
          esModules: true
        }
      },
      {
        test: /\.html$/,
        loader: 'html-loader?attrs=false'
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'null-loader'
      }
    ]
  },

  plugins: [
    new webpack.ContextReplacementPlugin(
      // The (\\|\/) piece accounts for path separators in *nix and Windows
      /(ionic-angular)|(angular(\\|\/)core(\\|\/)@angular)/,
      root('./src'), // location of your src
      {} // a map of your routes
    )
  ]
};

function root(localPath) {
  return path.resolve(__dirname, localPath);
}

karma.conf.js

var webpackConfig = require('./webpack.test.js');

module.exports = function(config) {
  var _config = {
    basePath: '../',

    frameworks: ['jasmine'],

    files: [
      {
        pattern: './test-config/karma-test-shim.js',
        watched: true
      },
      {
        pattern: './src/assets/**/*',
        watched: false,
        included: false,
        served: true,
        nocache: false
      }
    ],

    proxies: {
      '/assets/': '/base/src/assets/'
    },

    preprocessors: {
      './test-config/karma-test-shim.js': ['webpack', 'sourcemap']
    },

    webpack: webpackConfig,

    webpackMiddleware: {
      stats: 'errors-only'
    },

    webpackServer: {
      noInfo: true
    },

    browserConsoleLogOptions: {
      level: 'log',
      format: '%b %T: %m',
      terminal: true
    },

    coverageIstanbulReporter: {
      reports: [ 'html', 'lcovonly' ],
      fixWebpackSourcePaths: true
    },

    reporters: config.coverage ? ['kjhtml', 'dots', 'coverage-istanbul'] : ['kjhtml', 'dots'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  };

  config.set(_config);
};

karma-test-shim.js


require('core-js/es6');
require('core-js/es7/reflect');

require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');

var appContext = require.context('../src', true, /\.spec\.ts/);

appContext.keys().forEach(appContext);

var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');

testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());

app.component.spec.ts

import { IonicModule, Platform } from 'ionic-angular';
import { Storage, IonicStorageModule } from '@ionic/storage';

import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import  { AuthProvider } from '../providers/auth/auth';

import { MyApp } from './app.component';

describe('MyApp Component', () => {

  let fixture;
  let component;

  beforeEach( async(() => {
    TestBed.configureTestingModule({
      declarations: [MyApp],
      imports: [
        IonicModule.forRoot(MyApp)
      ],
      providers: [
        Platform,
        StatusBar,
        SplashScreen,
        AuthProvider
      ]
    });

    fixture = TestBed.createComponent(MyApp);
    component = fixture.componentInstance;

  }));

  it('should be created', () => {
    expect(component instanceof MyApp).toBe(true);
  });

});

app.component.js

import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { AuthProvider } from '../providers/auth/auth';

import { HomePage } from '../pages/home/home';
import { LoginPage } from '../pages/login/login';
import { SobrePage } from '../pages/sobre/sobre';

@Component({
  selector: 'myapp',
  templateUrl: 'app.html'
})
export class MyApp {

  @ViewChild(Nav) nav: Nav;

  rootPage: any = null;
  isUserAuthenticated: boolean = false;

  paginas: Array<{title: string, component: any, icone:string}> = [
        { title: 'Frequêcia e Conteúdo', component: HomePage, icone: 'school' },
        { title: 'Sobre', component: SobrePage, icone: 'help'},
        { title: 'Sair', component: LoginPage, icone: 'log-out' }
  ];

  constructor(
    public platform: Platform,
    public statusBar: StatusBar,
    public splashScreen: SplashScreen,
    private authProvider: AuthProvider
  ) {
      this.bootstrap();
  }

  bootstrap(): void{

    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });

    this.authProvider
    .authUser.subscribe(auth => {

        if(auth){

           if(auth.token)
              this.rootPage = HomePage;
              this.isUserAuthenticated = !this.isUserAuthenticated;
        }

        if(!auth) this.rootPage = LoginPage;

      });

    this.authProvider.checkAuthentication();

  }

  public openPage(pageSelected): void {

       if(pageSelected.title === "Sair"){
          this.authProvider.logout();
          this.nav.setRoot(pageSelected.component);
       }
       else
          this.nav.push(pageSelected.component);
  }

}
davidwillianx commented 6 years ago

I figure out when I remove PlatForm from MockInjection works as I expect, but I don't really know the reason.

RonnyAnc commented 5 years ago

What if you really need to mock Platform?