Giter Club home page Giter Club logo

ionic-unit-testing-example's Introduction

2018-03-28: We have a pull request for updating to Karma 2 awaiting review. If you can take the time to install this update and let us know if it works for you, that would be very helpful. Comments are welcome!

Ionic Unit Testing Example

This repository is an example project that gives guidance on setting up your Ionic application for unit testing and end-to-end (E2E) testing. We have been told the folks at Ionic will be adding testing features to new projects in the future. But until then, feel free to borrow from this project as needed.

Special thanks to all of the contributors. With the exception of the Ionic team's updates to the framework, this project is stable. If you have a suggestion, feel free to update code and make a pull request. Find a problem or bug, feel free to file a detailed issue.

How to Configure Your Ionic Application for Testing

Read this tutorial for instructions on how to apply the testing configuration in this project to your own project.

Mocking Classes for Ionic

When a developer unit tests a component, the objective is to isolate that component as much as possible. In the case of an Ionic page, you may have Ionic components like NavController, LoadingContoller, or Platform. Adding these components means adding pieces of the Ionic framework to your test, thus not isolating the component. As part of this example, the file test-config/mocks-ionic.ts is provided for creating simple mocks for many of the classes in Ionic that you may need. You may use the classes from this file in test files inside the TestBed.configureComponent() method argument's provider array as seen in our example unit test file.

There are other mocking options that should be mentioned: ionic-mocks ionic-test-doubles

Also worth mentioning is ionic-native-mocks which can be helpful when mocks for Ionic Native classes used in your project are needed.

Getting Started with this Project

To get started, clone this repo, and run npm install in the root directory.

git clone https://github.com/ionic-team/ionic-unit-testing-example.git
cd ionic-unit-testing-example
npm install

Then, you should run ionic serve to make sure the project loads.

Unit Tests

To run the tests, run npm run test.

See the example test in src/app/app.component.spec.ts for an example of a component test.

End-To-End Tests (Browser-Only)

To serve the app, run ionic serve.

To run the end-to-end tests, run (while the app is being served) npm run e2e.

See the example end-to-end test in e2e/app.e2e-spec.ts.

UPDATES:

2018-02-25: Updated to Ionic 3.9.2

Updated project to use the latest version Ionic and dependencies. Take a look at the package.json for more details.

2017-09-05: Added Code Coverage Functionality

Thanks to @lathonez, we now have functioning code coverage functionality. With this update, developers can run npm run test-coverage which will run the project's unit tests with Karma and produce documentation that gives guidance on how well the project's tests cover the code.

Example Image of Completed Code Coverage

The documentation is created inside the /coverage folder (ignored by git).

Looking for Version 2?

If you are using Ionic v2, please see our ionic-v2-branch.

Credits

This repository is based on the awesome unit testing example from @roblouie ๐Ÿ‘

Past Updates

2017-08-26: Update to ionic-angular version 3.6.0

We updated the project to ionic-angular version 3.6.0. Developers wishing to use this should also update Ionic CLI for a better experience. With today's update, this project is now at version 0.0.5.

Added: Fix for assets not being found by Karma

Thanks to @datencia for providing an update to our Karma configuration that properly sets the Karma base path so that image assets can be found during testing. This fix should also work any JSON data files you might want to use for testing. He also provided an image and updated our sample unit test spec file that tests that the image is found.

Added: Update code to match Ionic templates

Thanks (again) to @danielsogl for providing a code update to the project so that our code matches code created by using the ionic start command. Having this code properly match is important as it provides the best practice guidance for handling application start up.

2017-05-28: Update to Version 3.3.0

Thanks to @danielsogl for getting us up-to-date with Ionic 3.3.0, Angular 4.1.2 and Ionic Native 3.10.2.

Thanks to @johnstonbl01 for adding a couple of mocks that prevent us from seeing some unnecessary warning messages.

2017-05-12: Update to Version 3

We've updated this repo to use Ionic v3.2.1 and Ionic CLI v3.0.0.

If you already have this repository downloaded on your system, after you sync with our Master branch make certain you delete your node_modules folder and then run npm install.

Also, since we've updated to Ionic CLI v3.0.0, you will need to update your version as well:

npm remove -g ionic
npm install -g ionic

If you run ionic -v it should return 3.0.0 (or better, depending on what has been released.

ionic-unit-testing-example's People

Contributors

butters16 avatar danielsogl avatar datencia avatar johnstonbl01 avatar kensodemann avatar lancetw avatar lathonez avatar leifwells avatar mlynch avatar roblouie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ionic-unit-testing-example's Issues

Issues with image in html

I've set up my test exactly like this example repo, everything worked properly until I added an image element into html, e.g.

<ion-row>
      <img style="height:16px; width:16px" src="assets/icon/star-16.png" *ngFor="let star of item.stars" />
 </ion-row>

When npm run test, always got

ERROR in ./src/pages/home/home.html
Module not found: Error: Can't resolve './assets/icon/star-16.png' in '/Users/xxx/Dev/ionic-apps/my-app/src/pages/home'
 @ ./src/pages/home/home.html 1:2111-2147
 @ ./src/pages/home/home.ts
 ...
 @ ./src/app/app.component.ts
 @ ./src/app/app.component.spec.ts
 @ ./src \.spec\.ts
 @ ./test-config/karma-test-shim.js
webpack: Failed to compile.

I'm new to Karma and Webpack, any idea?

Uncaught Error: Module build failed: TypeError: Cannot read property 'afterCompile' of undefined

I followed the instructions for setting up testing on my Ionic project, but I got the error Uncaught Error: Module build failed: TypeError: Cannot read property 'afterCompile' of undefined

After some investigation I realized that Ionic uses webpack 3, but the default version of ts-loader installed with npm install is for webpack 4. Please update the blog entry to install a 3.x.x version of ts-loader.

For anyone facing this error you can simply install the correct version of ts-loader manually like this...

npm uninstall -D ts-loader
npm install -D [email protected]

Valdiating Ionic-options

I want to write a test that validates that a ionic-select get's loaded with the right ionic-options.

I'm struggling to figure out how to do this using karma/jasmine, is this something that's not possible with unit testing? Or is it only possible with e2e testing?

Errors with Ionic Serve

When I run Ionic Serve on this project I get a bunch of errors (npm test worked fine). The errors are shown below. Do we need to be running a particular version of Jasmine? I have version 2.5.3 installed.

ionic-app-scripts 1.1.4
[19:47:52] watch started ...
[19:47:52] build dev started ...
[19:47:52] clean started ...
[19:47:52] clean finished in 1 ms
[19:47:52] copy started ...
[19:47:52] transpile started ...
[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 40
'=' expected.

  L39:  declare namespace jasmine {
  L40:      type Expected<T> = T | ObjectContaining<T> | Any | Spy;

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 42
'=' expected.

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 40
L42: var clock: () => Clock;

        A parameter initializer is only allowed in a function or constructor implementation.

  L39:  declare namespace jasmine {

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 40
L40: type Expected = T | ObjectContaining | Any | Spy;

        Cannot find name 'keyof'.

  L39:  declare namespace jasmine {
  L40:      type Expected<T> = T | ObjectContaining<T> | Any | Spy;

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 42

        A parameter initializer is only allowed in a function or constructor implementation.

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 42
ar clock: () => Clock;

        Cannot find name 'keyof'.

  L42:      var clock: () => Clock;

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 58
Cannot find name 'Partial'.

  L57:      function getEnv(): Env;
  L59:      function addCustomEqualityTester(equalityTester: CustomEqualityTester): void;

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 99
Cannot find name 'Partial'.

  L98:          new (env: Env, func: SpecFunction, spec: Spec): any;
 L100:          execute(onComplete: () => void): void;

[19:47:55] typescript: node_modules/@types/jasmine/index.d.ts, line: 99
Cannot find name 'Partial'.

  L98:          new (env: Env, func: SpecFunction, spec: Spec): any;
 L100:          execute(onComplete: () => void): void;

ion-slides fails to test

This is apparently a continuation of an issue over at Clicker: Problem with ion-slides #227

I can't seem to get ion-slides to test. I have a branch available for testing purposes. Essentially, I have a page with a slides implementation created from the example from the documentation.

Repo

Currently, the test is failing with this error:

Chrome 56.0.2924 (Mac OS X 10.11.6) Slides Page should have expected <ion-slide> elements FAILED
	TypeError: platform.getQueryParam is not a function
	    at Config.get (webpack:///~/ionic-angular/config/config.js:165:33 <- karma-test-shim.js:718:66)
	    at Config.getBoolean (webpack:///~/ionic-angular/config/config.js:243:25 <- karma-test-shim.js:796:41)
	    at new App (webpack:///~/ionic-angular/components/app/app.js:60:0 <- karma-test-shim.js:6480:45)
	    at DynamicTestModuleInjector.createInternal (/DynamicTestModule/module.ngfactory.js:299:18)
	    at DynamicTestModuleInjector.NgModuleInjector.create (webpack:///~/@angular/core/src/linker/ng_module_factory.js:123:53 <- karma-test-shim.js:79064:76)
	    at NgModuleFactory.create (webpack:///~/@angular/core/src/linker/ng_module_factory.js:91:0 <- karma-test-shim.js:79032:18)
	    at TestBed._initIfNeeded (webpack:///~/@angular/core/bundles/core-testing.umd.js:784:0 <- karma-test-shim.js:24745:82)
	    at TestBed.createComponent (webpack:///~/@angular/core/bundles/core-testing.umd.js:853:0 <- karma-test-shim.js:24814:18)
	    at Function.TestBed.createComponent (webpack:///~/@angular/core/bundles/core-testing.umd.js:682:0 <- karma-test-shim.js:24643:33)
	    at Object.<anonymous> (webpack:///src/pages/slides-page/slides-page.spec.ts:130:22 <- karma-test-shim.js:134190:82)
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:229:0 <- karma-test-shim.js:105237:26)
	    at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 <- karma-test-shim.js:104904:39)
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:228:0 <- karma-test-shim.js:105236:32)
	    at Zone.run (webpack:///~/zone.js/dist/zone.js:113:0 <- karma-test-shim.js:105121:43)
	    at Object.<anonymous> (webpack:///~/zone.js/dist/jasmine-patch.js:102:0 <- karma-test-shim.js:104619:34)
	    at webpack:///~/@angular/core/bundles/core-testing.umd.js:96:0 <- karma-test-shim.js:24057:21
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:229:0 <- karma-test-shim.js:105237:26)
	    at AsyncTestZoneSpec.onInvoke (webpack:///~/zone.js/dist/async-test.js:49:0 <- karma-test-shim.js:104209:39)
	    at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:76:0 <- karma-test-shim.js:104901:39)
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:228:0 <- karma-test-shim.js:105236:32)
	    at Zone.run (webpack:///~/zone.js/dist/zone.js:113:0 <- karma-test-shim.js:105121:43)
	    at AsyncTestZoneSpec._finishCallback (webpack:///~/@angular/core/bundles/core-testing.umd.js:91:0 <- karma-test-shim.js:24052:29)
	    at webpack:///~/zone.js/dist/async-test.js:38:0 <- karma-test-shim.js:104198:31
	    at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:262:0 <- karma-test-shim.js:105270:35)
	    at Zone.runTask (webpack:///~/zone.js/dist/zone.js:151:0 <- karma-test-shim.js:105159:47)
	    at ZoneTask.invoke (webpack:///~/zone.js/dist/zone.js:332:0 <- karma-test-shim.js:105340:33)
	    at data.args.(anonymous function) (webpack:///~/zone.js/dist/zone.js:1149:0 <- karma-test-shim.js:106157:25)
	TypeError: Cannot read property 'detectChanges' of undefined
	    at Object.<anonymous> (webpack:///src/pages/slides-page/slides-page.spec.ts:138:12 <- karma-test-shim.js:134196:16)
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:229:0 <- karma-test-shim.js:105237:26)
	    at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 <- karma-test-shim.js:104904:39)
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:228:0 <- karma-test-shim.js:105236:32)
	    at Zone.run (webpack:///~/zone.js/dist/zone.js:113:0 <- karma-test-shim.js:105121:43)
	    at Object.<anonymous> (webpack:///~/zone.js/dist/jasmine-patch.js:102:0 <- karma-test-shim.js:104619:34)
	    at webpack:///~/@angular/core/bundles/core-testing.umd.js:96:0 <- karma-test-shim.js:24057:21
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:229:0 <- karma-test-shim.js:105237:26)
	    at AsyncTestZoneSpec.onInvoke (webpack:///~/zone.js/dist/async-test.js:49:0 <- karma-test-shim.js:104209:39)
	    at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:76:0 <- karma-test-shim.js:104901:39)
	    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:228:0 <- karma-test-shim.js:105236:32)
	    at Zone.run (webpack:///~/zone.js/dist/zone.js:113:0 <- karma-test-shim.js:105121:43)
	    at AsyncTestZoneSpec._finishCallback (webpack:///~/@angular/core/bundles/core-testing.umd.js:91:0 <- karma-test-shim.js:24052:29)
	    at webpack:///~/zone.js/dist/async-test.js:38:0 <- karma-test-shim.js:104198:31
	    at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:262:0 <- karma-test-shim.js:105270:35)
	    at Zone.runTask (webpack:///~/zone.js/dist/zone.js:151:0 <- karma-test-shim.js:105159:47)
	    at ZoneTask.invoke (webpack:///~/zone.js/dist/zone.js:332:0 <- karma-test-shim.js:105340:33)
	    at data.args.(anonymous function) (webpack:///~/zone.js/dist/zone.js:1149:0 <- karma-test-shim.js:106157:25)
Chrome 56.0.2924 (Mac OS X 10.11.6): Executed 2 of 6 (2 FAILED) (skipped 4) ERROR (2.644 secs / 2.018 secs)

To be clear, I am asking for support here. In slides-page.spec.ts I have a PlatformMock with some methods commented because I feel like I'm heading down a black hole by continuing to update that class.

After working on this for a long time, I'm beginning to believe that the Slides component is too tightly bound to Platform and other components.

Any feedback will be greatly appreciated.

How to test delayed NavController.setRoot()?

Hi,

i can't figure out how to test the setRoot() method of the root navigation controller in the app component if the root page is not set directly but delayed in a promise chain.
For this i cloned the repo and just changed in app.component.ts rootPage: any = Page1; to rootPage: any; and then set the root page within the platform.ready() promise via this.nav.setRoot(Page1);.
The whole app.component.ts now looks like:

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

import { Page1 } from '../pages/page1/page1';
import { Page2 } from '../pages/page2/page2';


@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  @ViewChild(Nav) nav: Nav;

  rootPage: any;

  pages: Array<{ title: string, component: any }>;

  constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
    this.initializeApp();

    // used for an example of ngFor and navigation
    this.pages = [
      { title: 'Page One', component: Page1 },
      { title: 'Page Two', component: Page2 }
    ];

  }

  initializeApp() {
    this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      this.statusBar.styleDefault();
      this.splashScreen.hide();

      return this.nav.setRoot(Page1);
    });
  }

  openPage(page) {
    // Reset the content nav to have just this page
    // we wouldn't want the back button to show in this scenario
    this.nav.setRoot(page.component);
  }
}

How has a test to be written to test the current root page after the promise chain in initializeApp() has finished?
I don't care if it's done via checking the rootPage property or NavControllers getActive() methor or even spy on NavControllers setRoot() method... (Whatever i tried so far, i always got either failing tests or strange zone errors)
Any hints on this?

Running test fails

When I run test I get the errors below.

C:\ionic-test>npm test

[email protected] test C:\ionic-test
karma start ./test-config/karma.conf.js

02 01 2018 20:51:10.747:ERROR [config]: Invalid config file!
Error: Cannot find module 'webpack'
at Function.Module._resolveFilename (module.js:536:15)
at Function.Module._load (module.js:466:25)
at Module.require (module.js:579:17)
at require (internal/module.js:11:18)
at Object. (C:\ionic-test\test-config\webpack.test.js:1:15)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
at tryModuleLoad (module.js:497:12)
at Function.Module._load (module.js:489:3)
at Module.require (module.js:579:17)
at require (internal/module.js:11:18)
at Object. (C:\ionic-test\test-config\karma.conf.js:1:21)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
npm ERR! Test failed. See above for more details.

Cannot read property Ionic of undefined

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);
  }

}

Adding code coverage

Would be great if code coverage was added to this. I'm working on getting it working with karma-coverage, but the instructions all don't really support @angular/cli and don't support webpack.

Discussion about Jest for unit tests

I just added a PR #32 to have an example of working unit tests with Jest.

Maybe we could use this issue for discussion if other people are interested in making jest usable with ionic. Also maybe there are good reasons not to use Jest with ionic. I would appreciate if someone could enlighten me in this case :)

Some advantages of Jest over Karma:

  • Only run tests on modified files
  • Only run tests for modified files since last commit

Article about testing with Jest in angular:
https://www.xfive.co/blog/testing-angular-faster-jest/

ts-loader's default config makes Webpack extremely slow in larger projects

The nature of ts-loader makes it slower as the project's size increases.
https://github.com/TypeStrong/ts-loader#faster-builds

There are 2 options to make it fast:

  • Use a separate process for typechecking, following ts-loader's docs in the link above:
var ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
[ ... ]
  module: {
    rules: [{
        test: /\.ts$/,
        loaders: [{
          loader: 'ts-loader',
          options: {
              transpileOnly: true
          }
        }, 'angular2-template-loader']
      },
[ ... ].
  plugins: [
    new ForkTsCheckerWebpackPlugin(),
[ ... ]
  • Use awesome-typescript-loader:
[ ... ]
  module: {
    rules: [{
        test: /\.ts$/,
        loaders: ['awesome-typescript-loader', 'angular2-template-loader']
      },
[ ... ]

Any inputs on if these changes breaks anything?

Use ionic native mocks in tests

Note: This is a duplicate from chrisgriffith/ionic-native-mocks#7. I apologize in advance if this is not the place for this kind of questions

I am using unit and end to end tests on my app (with Karma, Jasmine and Protactor by following this repo and the tutorial you mention)

Let's say I have a class that calls the actual Ionic Native wrapper for a plugin, but I want to test this component. For tests, I'd like to use the mock for that Ionic Native wrapper, instead of the wrapper itself. I think I could use ionic-native-mocks, which you mention in your readme. Please see the example below:

// My class using an Ionic Native wrapper
import { BLE } from '@ionic-native/ble';

export class ClassToBeTested {
  uuid: string
  ble: BLE

  constructor (uuid) {
    this.uuid = uuid
    this.ble = new BLE()
  }

  connect () {
    this.ble.connect(this.uuid)
    // ...
  }
}
// Test:
import { ClassToBeTested } from "../../lib/class_to_be_tested"

describe('ClassToBeTested', () => {
  it('can be instantiated', () => {
    let instance:ClassToBeTested = new ClassToBeTested("a")
    expect(instance instanceof ClassToBeTested).toBe(true)
    expect(instance.uuid).toBe("a")
  })

  it('can connect', () => {
    let instance:ClassToBeTested = new ClassToBeTested("a")
    expect(instance.connect).not.toThrow()
    // This fails: Expected function not to throw, but it threw TypeError: Cannot read property 'ble' of undefined.
  })
})

I think that what I need is to use BLEMock instead of BLE when testing. How can this be done?

Unit test within async using fixture.detectChanges() fails

Hello,

This is the issue description:
Using the method from ComponentFixture .detectChanges() is failing when you use it within an async() unit test.

How to reproduce:

  1. Clone this repo: git clone https://github.com/ionic-team/ionic-unit-testing-example.git
  2. Install packages: cd ionic-unit-testing-example && sudo npm install
  3. Add the following unit test to the src/app/app.component.spec.ts:
  it( 'example test async with fixture.detectChanges()', async(() => {
    fixture.detectChanges();
  }));
  1. Run tests: npm run test-ci

After running the tests, it fails with the following error:

..ERROR: 'Unhandled Promise rejection:', 'invalid link: Page1', '; Zone:', 'angular', '; Task:', 'Promise.then', '; Value:', 'invalid link: Page1', undefined

ERROR: 'Unhandled Promise rejection:', 'invalid link: Page1', '; Zone:', 'angular', '; Task:', 'Promise.then', '; Value:', 'invalid link: Page1', undefined
Chrome 65.0.3325 (Linux 0.0.0) MyApp Component example test async with fixture.detectChanges() FAILED
        Failed: Uncaught (in promise): invalid link: Page1
        Error: Uncaught (in promise): invalid link: Page1
            at resolvePromise (webpack:///node_modules/zone.js/dist/zone.js:824:0 <- test-config/karma-test-shim.js:117151:31)
            at Object.reject (webpack:///node_modules/zone.js/dist/zone.js:746:0 <- test-config/karma-test-shim.js:117073:17)
            at NavControllerBase._fireError (webpack:///node_modules/ionic-angular/navigation/nav-controller-base.js:223:0 <- test-config/karma-test-shim.js:51342:16)
            at NavControllerBase._failed (webpack:///node_modules/ionic-angular/navigation/nav-controller-base.js:216:0 <- test-config/karma-test-shim.js:51335:14)
            at webpack:///node_modules/ionic-angular/navigation/nav-controller-base.js:263:44 <- test-config/karma-test-shim.js:51382:59
            at ZoneDelegate.invoke (webpack:///node_modules/zone.js/dist/zone.js:392:0 <- test-config/karma-test-shim.js:116719:26)
............

Expected result should be at least not to throw this error when using fixture.detectChanges().

The full src/app/app.component.spec.ts file would be as the following:

import { async, TestBed, fakeAsync, ComponentFixture, tick } from '@angular/core/testing';
import { IonicModule, Platform, MenuController, Menu } from 'ionic-angular';

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

import { MyApp } from './app.component';
import {
  PlatformMock,
  StatusBarMock,
  SplashScreenMock
} from '../../test-config/mocks-ionic';
import { Page } from 'ionic-angular/navigation/nav-util';
import { By } from '@angular/platform-browser';

describe('MyApp Component', () => {
  let fixture;
  let component;

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

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

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

  it('should have two pages', () => {
    expect(component.pages.length).toBe(2);
  });

  it( 'example test async with fixture.detectChanges()', async(() => {
    fixture.detectChanges();
  }));

});

Doest anyone at least know why this could be happenning? I don't know if this could even be an Angular bug with lazy loading or whatever.

The only reference to Page1 is inside src/app/app.component.ts in order to set up the page as the rootPage of the app:

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


@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  @ViewChild(Nav) nav: Nav;

  rootPage: any = 'Page1';

  pages: Array<{ title: string, component: any }>;


  constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
    // used for an example of ngFor and navigation
    this.pages = [
      { title: 'Page One', component: 'Page1' },
      { title: 'Page Two', component: 'Page2' }
    ];

  }

  ionViewDidLoad() {
    this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });
  }

  openPage(page) {
    // Reset the content nav to have just this page
    // we wouldn't want the back button to show in this scenario
    this.nav.setRoot(page.component);
  }

}

Thank you in advance.

Regards,

David.

No test was found

I ran 'npm test'.The chrome was displayed and connected. However there is no test, only displayed like below:

Karma v1.7.0 - connected
Chrome 60.0.3112 (Windows 10 0.0.0) is idle

My Status:
My branch is up to origin/master and at commit '5aa5b69a2f04a503fdeae47bd633293b7350ec21 '.
There is no local changes.
I have ran 'npm install'.
My global 'ionic' is 3.6.

My console log:
`
C:\Users\zelijin\code\web\ionic-unit-testing-example>npm test
[email protected] test C:\Users\zelijin\code\web\ionic-unit-testing-example
karma start ./test-config/karma.conf.js

webpack: Compiled successfully.
webpack: Compiling...
ts-loader: Using [email protected] and C:\Users\zelijin\code\web\ionic-unit-testing-example\tsconfig.json
22 08 2017 18:50:33.424:WARN [karma]: No captured browser, open http://localhost:9876/

webpack: Compiled successfully.
22 08 2017 18:50:33.451:INFO [karma]: Karma v1.7.0 server started at http://0.0.0.0:9876/
22 08 2017 18:50:33.453:INFO [launcher]: Launching browser Chrome with unlimited concurrency
22 08 2017 18:50:33.951:INFO [launcher]: Starting browser Chrome
22 08 2017 18:50:39.151:INFO [Chrome 60.0.3112 (Windows 10 0.0.0)]: Connected on socket f0EHW9GoLj6OYj9rAAAA with id 96719920
Chrome 60.0.3112 (Windows 10 0.0.0) ERROR
Uncaught ReferenceError: jasmine is not defined
at C:/Users/zelijin/code/web/ionic-unit-testing-example/node_modules/._karma-jasmine-html-reporter@0.2.2@karma-jasmine-html-reporter/src/lib/adapter.js:6
Chrome 60.0.3112 (Windows 10 0.0.0) ERROR
Uncaught ReferenceError: jasmine is not defined
at C:/Users/zelijin/code/web/ionic-unit-testing-example/node_modules/._karma-jasmine-html-reporter@0.2.2@karma-jasmine-html-reporter/src/lib/adapter.js:6
Chrome 60.0.3112 (Windows 10 0.0.0): Executed 0 of 0 ERROR (0.383 secs / 0 secs)`

e2e tests shows error

I get an error executing e2e the following error:

Can you tell me what I am doing wrong?

Thanks!

Ionic lifecycle methods not called

The Ionic lifecycle methods (eg. ionViewDidLoad) do not get called when executing these tests. I modified page1 to set some text in ionViewDidLoad and then display that text on the page - a common pattern I use in my app and would like to test. However, the test fails because ionViewDidLoad does not get called. I was expecting either createComponent or detectChanges to invoke the Ionic lifecycle. Am I missing something?

page1.ts

import { Component } from '@angular/core';
import { IonicPage, NavController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-page1',
  templateUrl: 'page1.html'
})
export class Page1 {
  title: string = 'Ionic did not load';

  constructor(public navCtrl: NavController) {
  }

  ionViewDidLoad(): void {
    this.title = 'Ionic loaded...';
  }

}

page1.html

<ion-header>
  <ion-navbar>
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Page One</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <h3>{{ title }}</h3>

  <img src="assets/icon/favicon.ico" alt="" />

  <p>
    If you get lost, the <a href="http://ionicframework.com/docs/v2">docs</a> will show you the way.
  </p>

  <button ion-button secondary menuToggle>Toggle Menu</button>
</ion-content>

page1.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { Page1 } from './page1';
import { IonicModule, Platform, NavController} from 'ionic-angular/index';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

describe('Page1', () => {
  let de: DebugElement;
  let comp: Page1;
  let fixture: ComponentFixture<Page1>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [Page1],
      imports: [
        IonicModule.forRoot(Page1)
      ],
      providers: [
        NavController
      ]
    });
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(Page1);
    comp = fixture.componentInstance;
    de = fixture.debugElement.query(By.css('h3'));
  });

  it('should create component', () => expect(comp).toBeDefined());

  it('should have expected <h3> text', () => {
    fixture.detectChanges();
    const h3 = de.nativeElement;
    expect(h3.innerText).toMatch('Ionic loaded...',
      '<h3> should say something about "Ionic"');
  });

  it('should show the favicon as <img>', () => {
    fixture.detectChanges();
    const img: HTMLImageElement = fixture.debugElement.query(By.css('img')).nativeElement;
    expect(img.src).toContain('assets/icon/favicon.ico');
  });
});

output:

Error: Expected 'Ionic did not load' to match 'Ionic loaded...', '

should say something about "Ionic"'.

Karma throws StaticInjectorError

I tried to add testing to my app using this repo, but I get this error when running

npm test

SocialSharing is added to my porvider's list in app.module.ts, and the project builds and runs correctly. Removing it causes Karma to throw the same error from another plugin in my list.

I only get this error while testing:

Chrome 64.0.3282 (Mac OS X 10.13.3) MyApp Component should be created FAILED
Error: StaticInjectorError[SocialSharing]: 
  StaticInjectorError[SocialSharing]: 
    NullInjectorError: No provider for SocialSharing!
    at _NullInjector.get (webpack:///~/@angular/core/esm5/core.js:923:0 <- test-config/karma-test-shim.js:1195:19)
    at resolveToken (webpack:///~/@angular/core/esm5/core.js:1211:0 <- test-config/karma-test-shim.js:1483:24)
    at tryResolveToken (webpack:///~/@angular/core/esm5/core.js:1153:0 <- test-config/karma-test-shim.js:1425:16)
    at StaticInjector.get (webpack:///~/@angular/core/esm5/core.js:1024:0 <- test-config/karma-test-shim.js:1296:20)
    at resolveToken (webpack:///~/@angular/core/esm5/core.js:1211:0 <- test-config/karma-test-shim.js:1483:24)
    at tryResolveToken (webpack:///~/@angular/core/esm5/core.js:1153:0 <- test-config/karma-test-shim.js:1425:16)
    at StaticInjector.get (webpack:///~/@angular/core/esm5/core.js:1024:0 <- test-config/karma-test-shim.js:1296:20)
    at resolveNgModuleDep (webpack:///~/@angular/core/esm5/core.js:10585:0 <- test-config/karma-test-shim.js:10857:25)
    at NgModuleRef_.get (webpack:///~/@angular/core/esm5/core.js:11806:0 <- test-config/karma-test-shim.js:12078:16)
    at resolveDep (webpack:///~/@angular/core/esm5/core.js:12302:0 <- test-config/karma-test-shim.js:12574:45)
    at createClass (webpack:///~/@angular/core/esm5/core.js:12172:0 <- test-config/karma-test-shim.js:12444:32)
    at createDirectiveInstance (webpack:///~/@angular/core/esm5/core.js:12011:21 <- test-config/karma-test-shim.js:12283:37)
    at createViewNodes (webpack:///~/@angular/core/esm5/core.js:13449:37 <- test-config/karma-test-shim.js:13721:53)
    at createRootView (webpack:///~/@angular/core/esm5/core.js:13339:0 <- test-config/karma-test-shim.js:13611:5)
    at callWithDebugContext (webpack:///~/@angular/core/esm5/core.js:14740:25 <- test-config/karma-test-shim.js:15012:42)
    at Object.debugCreateRootView [as createRootView] (webpack:///~/@angular/core/esm5/core.js:14041:0 <- test-config/karma-test-shim.js:14313:12)
    at ComponentFactory_.create (webpack:///~/@angular/core/esm5/core.js:10960:25 <- test-config/karma-test-shim.js:11232:46)
    at initComponent (webpack:///~/@angular/core/esm5/testing.js:1086:0 <- test-config/karma-test-shim.js:79576:49)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:392:0 <- test-config/karma-test-shim.js:179321:26)
    at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 <- test-config/karma-test-shim.js:178825:39)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:391:0 <- test-config/karma-test-shim.js:179320:32)
    at Object.onInvoke (webpack:///~/@angular/core/esm5/core.js:4629:0 <- test-config/karma-test-shim.js:4901:33)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:391:0 <- test-config/karma-test-shim.js:179320:32)
    at Zone.run (webpack:///~/zone.js/dist/zone.js:142:0 <- test-config/karma-test-shim.js:179071:43)
    at NgZone.run (webpack:///~/@angular/core/esm5/core.js:4446:47 <- test-config/karma-test-shim.js:4718:69)
    at TestBed.createComponent (webpack:///~/@angular/core/esm5/testing.js:1089:0 <- test-config/karma-test-shim.js:79579:58)
    at Function.TestBed.createComponent (webpack:///~/@angular/core/esm5/testing.js:808:0 <- test-config/karma-test-shim.js:79298:29)
    at UserContext.<anonymous> (webpack:///src/app/app.component.spec.ts:35:22 <- test-config/karma-test-shim.js:282489:82)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:392:0 <- test-config/karma-test-shim.js:179321:26)
    at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 <- test-config/karma-test-shim.js:178825:39)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:391:0 <- test-config/karma-test-shim.js:179320:32)
    at Zone.run (webpack:///~/zone.js/dist/zone.js:142:0 <- test-config/karma-test-shim.js:179071:43)
    at UserContext.<anonymous> (webpack:///~/zone.js/dist/jasmine-patch.js:104:0 <- test-config/karma-test-shim.js:178524:34)
    at webpack:///~/@angular/core/esm5/testing.js:93:0 <- test-config/karma-test-shim.js:78583:17
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:392:0 <- test-config/karma-test-shim.js:179321:26)
    at AsyncTestZoneSpec.onInvoke (webpack:///~/zone.js/dist/async-test.js:49:0 <- test-config/karma-test-shim.js:178008:39)
    at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:76:0 <- test-config/karma-test-shim.js:178822:39)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:391:0 <- test-config/karma-test-shim.js:179320:32)
    at Zone.run (webpack:///~/zone.js/dist/zone.js:142:0 <- test-config/karma-test-shim.js:179071:43)
    at AsyncTestZoneSpec._finishCallback (webpack:///~/@angular/core/esm5/testing.js:88:0 <- test-config/karma-test-shim.js:78578:25)
    at webpack:///~/zone.js/dist/async-test.js:38:0 <- test-config/karma-test-shim.js:177997:31
    at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:425:0 <- test-config/karma-test-shim.js:179354:31)
    at Zone.runTask (webpack:///~/zone.js/dist/zone.js:192:0 <- test-config/karma-test-shim.js:179121:47)
    at ZoneTask.invokeTask (webpack:///~/zone.js/dist/zone.js:499:0 <- test-config/karma-test-shim.js:179428:34)
    at ZoneTask.invoke (webpack:///~/zone.js/dist/zone.js:488:0 <- test-config/karma-test-shim.js:179417:48)
    at timer (webpack:///~/zone.js/dist/zone.js:2040:0 <- test-config/karma-test-shim.js:180969:29)

Generators are only available for Ionic 2 projects (CLI v2.2.1)

When doing:

ionic generate component settings-menu

You get this error:

Generators are only available for Ionic 2 projects (CLI v2.2.1)

Your system information:

Cordova CLI: 6.5.0
Ionic Framework Version: 2.2.0
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.1.4
ios-deploy version: 1.9.1
ios-sim version: 5.0.13
OS: OS X El Capitan
Node Version: v6.9.1
Xcode version: Xcode 8.2.1 Build version 8C1002

Any generate commands seem to yield the same thing.

error was thrown in afterAll with angular 5

I've followed the instructions, but when I execute npm run test, I'm receiving the following error:

> [email protected] test-ci /home/jmgomez/securitas/test/starter-with-testing
> karma start ./test-config/karma.conf.js --single-run


webpack: Compiled successfully.
webpack: Compiling...

webpack: Compiled with warnings.
16 02 2018 15:24:04.909:INFO [karma]: Karma v2.0.0 server started at http://0.0.0.0:9876/
16 02 2018 15:24:04.910:INFO [launcher]: Launching browser Chrome with unlimited concurrency
16 02 2018 15:24:04.931:INFO [launcher]: Starting browser Chrome
16 02 2018 15:24:05.989:INFO [Chrome 64.0.3282 (Linux 0.0.0)]: Connected on socket 6K6qqAOzO0RIRsN8AAAA with id 89855277
Chrome 64.0.3282 (Linux 0.0.0) ERROR
  {
    "message": "An error was thrown in afterAll\nUncaught TypeError: env.catchExceptions is not a function",
    "str": "An error was thrown in afterAll\nUncaught TypeError: env.catchExceptions is not a function"
  }
Chrome 64.0.3282 (Linux 0.0.0) ERROR
  {
    "message": "An error was thrown in afterAll\nUncaught TypeError: env.catchExceptions is not a function",
    "str": "An error was thrown in afterAll\nUncaught TypeError: env.catchExceptions is not a function"
  }
Chrome 64.0.3282 (Linux 0.0.0): Executed 0 of 0 ERROR (0.004 secs / 0 secs)
Chrome 64.0.3282 (Linux 0.0.0): Executed 0 of 0 ERROR (0.016 secs / 0 secs)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test-ci: `karma start ./test-config/karma.conf.js --single-run`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] test-ci script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/jmgomez/.npm/_logs/2018-02-16T14_24_06_588Z-debug.log

Result for ionic info is the following one:

cli packages: (/home/jmgomez/.nvm/versions/node/v8.9.1/lib/node_modules)

    @ionic/cli-utils  : 1.19.1
    ionic (Ionic CLI) : 3.19.1

local packages:

    @ionic/app-scripts : 3.1.8
    Ionic Framework    : ionic-angular 3.9.2

System:

    Node : v8.9.1
    npm  : 5.6.0 
    OS   : Linux 4.4

Misc:

    backend : pro

My android version is 5 instead of 4 as you can check in the package.json uploaded in the repository https://github.com/biaggi/karma-test-failing. Any hint on what's happening there?

Can we do Integration Testing with the present example?

Hi, Can we do Integration testing with Karma/Jasmine?
I know this is not the right platform to ask these questions, but no one answers about unit testing or integration testing on SO, and I have already used my friend google, but I did'not find any pointers or any examples.

For example:
If I test a component to navigate page1 to page2 when a click is handled, then in the page1.spec.ts file where the page1 component is tested, can I test Page2? And similarly to page 3?

404 Warning for assets

I've got 404 warnings for images, which could not load while testing. I don't want to test the images, just suppress the warnings.

After some research something like this

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

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

in the karma.conf.js should help, but I've got still

WARN [web-server]: 404: /base/src/assets/img/ionic_logo.png

I have fiddled around with the path expressions, but did't get it.

If someone please could help, Here my example https://github.com/11lein/ionic-unit-testing-example

Duplicated output in terminal

All the log / warning / error output in the terminal appears twice: once without colors and once with colors.
I've been unable so far to fix that or even understand why it's happening. I'm using the exact same configuration as the one in this repo.
Screenshot

Toggle Menu button does nothing

It's not related to unit testing, but the 'Toggle Menu' button does nothing when clicked, both with ionic serve and the Android emulator.

I don't have this problem with the original app, created with ionic start myApp sidemenu --v2
I just did npm install after cloning this repo. Which steps am I missing?

Handle E2E tests on real devices

Hi there, it might be great if this (already useful) example could be completed with an example of E2E tests on real devices. I am trying to do that with Appium but it fails for the moment, I submitted an issue, here, in the Appium repository concerning the troubles that I am facing, trying to extend this Ionic Unit Testing Example.

Maybe someone already tried this and/or faced this issue?

Vivaldi supported?

I modified test-config/karma.conf.js file.

And replaced browsers: ['Chrome'], to browsers: ['Vivaldi'],.

I run npm run test.
But, Cannot load browser "Vivaldi": it is not registered! Perhaps you are missing some plugin? message.

Adding any tests to app.component.spec.ts (even empty ones) causes other tests to fail

After migrating from @angular/cli to this testing setup, two of my tests started failing. Both of these tests are long standing and have not been modified in ages.

I tried re-writing one of the tests using the latest recommendations on Stack Overflow, to no avail.

To cut a very long story short, I figured out that commenting out the tests in app.component.spec.ts let the tests run fine.

I also tried empty tests (nothing in the test block at all), as well as adding an afterEach() => destroy, which didn't help.

To Replicate:

  • git clone [email protected]:lathonez/clicker.git
  • cd clicker
  • npm install
  • uncomment the tests in app.component.spec.ts
  • npm test

Note

I do not expect a solution to this problem, but I consider leaving the repo in it's current state (as long as we are unable to explain the behaviour) pretty dangerous in terms of other user's time. There is nothing at all to make you think that these tests would be affected by app.component.spec.ts, indeed everything we know about the unit testing setup tells us otherwise. You can easily sink several hours into this problem before coming to this point, or just getting frustrated and binning your perfectly valid tests.

Problem running test: Cannot read property 'afterCompile'

Hi,
I'm a newbie working with unit test on Ionic and I'm having a rough time with this issue. I'm able to run the test without problem if I'm not using any spec files (I used #79 to get there), but I get the next error trying to test a page.

> karma start ./test-config/karma.conf.js

webpack: Compiled successfully.
webpack: Compiling...
01 03 2018 11:40:21.848:WARN [karma]: No captured browser, open http://localhost:9876/

webpack: Compiled with warnings.
01 03 2018 11:40:21.858:INFO [karma]: Karma v2.0.0 server started at http://0.0.0.0:9876/
01 03 2018 11:40:21.858:INFO [launcher]: Launching browser Chrome with unlimited concurrency
01 03 2018 11:40:21.915:INFO [launcher]: Starting browser Chrome
01 03 2018 11:40:30.401:INFO [Chrome 62.0.3202 (Linux 0.0.0)]: Connected on socket Vo5QLQDs_T0I_Q9pAAAA with id 48205151

START:
01 03 2018 11:40:31.055:WARN [reporter]: SourceMap position not found for trace: undefined
01 03 2018 11:40:31.056:WARN [reporter]: SourceMap position not found for trace: undefined
01 03 2018 11:40:31.057:WARN [reporter]: SourceMap position not found for trace: undefined
01 03 2018 11:40:31.057:WARN [reporter]: SourceMap position not found for trace: undefined
01 03 2018 11:40:31.057:WARN [reporter]: SourceMap position not found for trace: undefined
01 03 2018 11:40:31.058:WARN [reporter]: SourceMap position not found for trace: undefined
Chrome 62.0.3202 (Linux 0.0.0) ERROR
  {
    "message": 
"Uncaught Error: Module build failed: TypeError: Cannot read property 'afterCompile' 
of undefined\n    at successfulTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:147:27)\n    
at Object.getTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:48:12)\n    
at Object.loader (/path/node_modules/ts-loader/dist/index.js:16:41)\nat karma-test-shim.js:80874:1\n\n
Error: Module build failed: TypeError: Cannot read property 'afterCompile' of undefined\n    
at successfulTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:147:27)\n    
at Object.getTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:48:12)\n    
at Object.loader (/path/node_modules/ts-loader/dist/index.js:16:41)\n    
at Object.<anonymous> (karma-test-shim.js:80874:7)\n    at __webpack_require__ (webpack:///webpack/bootstrap%2034e18eb4bd6904d0fe6e:19:0 <- karma-test-shim.js:20:30)\n    
at webpackContext (webpack:///src%20/.spec/.ts:5:0 <- karma-test-shim.js:80855:9)\n    at Array.forEach (<anonymous>)\n    at Object.<anonymous> (webpack:///test-config/karma-test-shim.js:16:0 <- karma-test-shim.js:73175:19)\n    
at __webpack_require__ (webpack:///webpack/bootstrap%2034e18eb4bd6904d0fe6e:19:0 <- karma-test-shim.js:20:30)\n    at webpack:///webpack/bootstrap%2034e18eb4bd6904d0fe6e:62:0 <- karma-test-shim.js:63:18\n    at karma-test-shim.js:66:10",
    "str": "Uncaught Error: Module build failed: TypeError: Cannot read property 'afterCompile' 
of undefined\n    at successfulTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:147:27)\n    
at Object.getTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:48:12)\n    
at Object.loader (/path/node_modules/ts-loader/dist/index.js:16:41)\nat karma-test-shim.js:80874:1\n\n
Error: Module build failed: TypeError: Cannot read property 'afterCompile' of undefined\n    
at successfulTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:147:27)\n    
at Object.getTypeScriptInstance (/path/node_modules/ts-loader/dist/instances.js:48:12)\n    
at Object.loader (/path/node_modules/ts-loader/dist/index.js:16:41)\n    
at Object.<anonymous> (karma-test-shim.js:80874:7)\n    at __webpack_require__ (webpack:///webpack/bootstrap%2034e18eb4bd6904d0fe6e:19:0 <- karma-test-shim.js:20:30)\n    
at webpackContext (webpack:///src%20/.spec/.ts:5:0 <- karma-test-shim.js:80855:9)\n    at Array.forEach (<anonymous>)\n    at Object.<anonymous> (webpack:///test-config/karma-test-shim.js:16:0 <- karma-test-shim.js:73175:19)\n    
at __webpack_require__ (webpack:///webpack/bootstrap%2034e18eb4bd6904d0fe6e:19:0 <- karma-test-shim.js:20:30)\n    at webpack:///webpack/bootstrap%2034e18eb4bd6904d0fe6e:62:0 <- karma-test-shim.js:63:18\n    at karma-test-shim.js:66:10"
  }

Finished in 0.662 secs / 0 secs @ 11:40:31 GMT+0100 (CET)

SUMMARY:
โœ” 0 tests completed

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: /\.html$/,
        loader: 'html-loader?attrs=false'
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'null-loader'
      }
    ]
  },

  plugins: [
    new webpack.ContextReplacementPlugin(
      /angular(\\|\/)core(\\|\/)@angular/,
      root('./src'),
      {}
    ),
    new webpack.ContextReplacementPlugin(
      /ionic-angular/,
      root('./src'),
      {}
    ),
  ]
};

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: './karma-test-shim.js', watched: true }
    ],

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

    webpack: webpackConfig,

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

    webpackServer: {
      noInfo: true
    },

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

    reporters: ['mocha', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  };

  config.set(_config);
};'

karma-test-shim.js

Error.stackTraceLimit = Infinity;

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()
);

spec file

describe("Dashboard", () => {

    it("Sum", () => expect(2+2).toBe(5));

})

package.json

"devDependencies": {
    "@angular/tsc-wrapped": "^4.4.6",
    "@ionic/app-scripts": "3.0.1",
    "@types/jasmine": "^2.8.6",
    "@types/jasminewd2": "^2.0.3",
    "angular2-template-loader": "^0.6.2",
    "html-loader": "^0.5.5",
    "jasmine": "^2.99.0",
    "karma": "^2.0.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-jasmine": "^1.1.1",
    "karma-jasmine-html-reporter": "^0.2.2",
    "karma-mocha-reporter": "^2.2.5",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^2.0.13",
    "null-loader": "^0.1.1",
    "ts-loader": "^4.0.0",
    "ts-node": "^5.0.0",
    "typescript": "^2.4.2"
  },

Any hint on what's happening?
Thanks for the help!

Searching for HTML elements works only on first rootPage in E2E testing

Hey guys!

I am facing one issue when I try to run E2E tests. I am using Protractor (5.1.2) for E2E tests.
So everything works fine when I try to search for elements on the rootPage. My tests look like this:

game.navigateToRoot();
game.startGame();
game.playTheGame();

Navigation to root works fine, I can normally find the START BUTTON and click on it, which leads me to the GameComponent (I actually change the root like this.nav.setRoot(GameComponent)).
When the game panel is shown, I can not do any HTML selector query, not even (browser.title), because neither one Promise callback is executed. I tried to wait the browser with:

const until = rotractor.ExpectedConditions;
browser.wait(until.presenceOf(game.getFinalResultWrapper()), 5000, 'Element taking too long to appear in the DOM');

Here is my game page object where I make HTML queries:

navigateToRoot() {
    return browser.get('');
}

startGame() {
    const startGameButton = this.getStartGameButton();
    this.getStartGameButton().click();
    // the NavController's root changes
}

getStartGameButton() {
    return $('#start-game');
}

getFinalResultWrapper() {
    return $('.level-complete-wrapper');
}

playTheGame() {
    // nothing works from now on
    const goalWrapper = $('#goal-wrapper');
    const until = protractor.ExpectedConditions;
    browser.wait(until.presenceOf(goalWrapper), 5000, 'Element taking too long to appear in the DOM');
    browser.getTitle().then((title) => {
        console.log('title = ', title);
    });
    $('#goal-wrapper').getSize().then((size) => {
        console.log(size);
    });
}

Can not load "webpack"

Environment: use the same package.json, and 3 test-config files with this repo.

after trying http://www.roblouie.com/article/376/ionic-2-set-up-unit-testing-the-best-way/, console shows Can not load "webpack" Error when npm test:

07 04 2017 10:13:17.281:ERROR [preprocess]: Can not load "webpack"!
WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.

  • configuration.module.rules[2] should be an object.
    at webpack (/Users/stevezheng/webstorm/hiitTool/node_modules/webpack/lib/webpack.js:19:9)
    at new Plugin (/Users/stevezheng/webstorm/hiitTool/node_modules/karma-webpack/lib/karma-webpack.js:67:16)
    at invoke (/Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:75:15)
    at Array.instantiate (/Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:59:20)
    at get (/Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:48:43)
    at /Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:71:14
    at Array.map (native)
    at Array.invoke (/Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:70:31)
    at Injector.get (/Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:48:43)
    at instantiatePreprocessor (/Users/stevezheng/webstorm/hiitTool/node_modules/karma/lib/preprocessor.js:55:20)
    at Array.forEach (native)
    at createPreprocessor (/Users/stevezheng/webstorm/hiitTool/node_modules/karma/lib/preprocessor.js:74:20)
    at Array.invoke (/Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:75:15)
    at get (/Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:48:43)
    at /Users/stevezheng/webstorm/hiitTool/node_modules/di/lib/injector.js:71:14
    at Array.map (native)

Using the whole ionic theme in karma specs

Does anyone know a way to get the unit tests working with the whole ionic theme? I.e. rendering Angular/Ionic components in the karma view (in the browser, e.g. http://localhost:9876/debug.html) with real ionic styling?

Especially I mean integrating the following paths:

  • node_modules/ionic-angular/themes
  • node_modules/ionicons/dist/scss
  • node_modules/ionic-angular/fonts
  • and the variables.scss from an ionic app

By using the method configureIonicTestingModule() from the "clicker app" (see https://github.com/lathonez/clicker/blob/3a8b6103c86d827130a41a3406a7fbba8c776bab/src/test-utils.ts), we got it working that ionic tags are compiled in the karma output, but they have no styles.

Maybe someone already solved this, we are trying, but could not make it work yet.

Cheers & Thanks,
Michael

Ionic 3 support

I had an existing Ionic 2.4.8, and followed the tutorial by @roblouie to add unit tests.
Which worked great.

I'm in the process of upgrading to Ionic 3, using the ChangeLog Steps.

I've followed it, step by step but unit tests are now broken.

I see you have a pull request by @MTechDE.

Is this master branch going to work with ionic 3.x? I can't find the branch for ionic 3 package.json version and file changes.

e2e cannot select elements

It's great that e2e support is provided! However I have problems to use it. The example you provide for selecting the title of the page works great. It only seems that it is not possible to select elements from the template/page which is loaded.

element(by.css('.title')) .getText() .then(text => { console.log("text from .title: ", text); });

The error is the following:
Failed: No element found using locator: By(css selector, .title)

So my conclusion is, that the element selection is started before the page has been loaded fully. Is there a way to wait until the page has fully loaded?

I have tried already things like, without success:
waitForAngular: http://www.protractortest.org/#/api?view=ProtractorBrowser.prototype.waitForAngular

Async tests fail in presence of IonicModule

Hello everyone,

I'm experiencing issues with async tests of the UI in the presence of IonicModule.forRoot.

The spec looks like this:

import { async, TestBed, ComponentFixture } from '@angular/core/testing';
import { IonicModule } from 'ionic-angular';

import { TestComponent } from './test';

describe('TestComponent', function() {

    let comp;
    let fix;

    beforeEach(function() {
        TestBed.configureTestingModule({
            declarations: [TestComponent],
            imports: [IonicModule.forRoot(TestComponent)]
        });
    });

    beforeEach(function() {
        fix = TestBed.createComponent(TestComponent);
        comp = fix.componentInstance;
    });

    it('is created', function() {
        expect(comp instanceof TestComponent).toBeTruthy();
    });

    it('should call openPage', async(function() {
        spyOn(comp, 'test');
        let btn = fix.debugElement.nativeElement.querySelector('button#test');
        btn.click();
        fix.whenStable().then(() => {
            expect(comp.test).toHaveBeenCalled();
        });
    }));
});

The spy is never called. If you comment the call to IonicModule.forRoot the test passes though.

This can be reproduced like so:

git clone https://github.com/ionic-team/ionic-unit-testing-example
cd ionic-unit-testing-example
npm i
ionic g component test
touch src/components/test/test.spec.ts

Copy the spec, insert a button into the component template and add a dummy function to the TestComponent. Then

npm run test

Tests fail due to: "TypeError: Cannot read property 'run' of null"

I have added the sample test files to an existing ionic 3 project and replaced instances of "MyApp" with the class name of my actual app. When I run npm test both default tests fail with the below error repeated four times.

TypeError: Cannot read property 'run' of null
    at <Jasmine>
    at UserContext.<anonymous> (http://localhost:9876/base/test-config/karma-test-shim.js:130803:34)
    at <Jasmine>
    at ZoneDelegate.invokeTask (http://localhost:9876/base/test-config/karma-test-shim.js:127920:31)
    at Zone.runTask (http://localhost:9876/base/test-config/karma-test-shim.js:127687:47)
    at drainMicroTaskQueue (http://localhost:9876/base/test-config/karma-test-shim.js:128097:35)

And if this helps, system info:

$ ionic info

cli packages: (/Users/swhitman/FIClock/node_modules)

    @ionic/cli-utils  : 1.19.2
    ionic (Ionic CLI) : 3.20.0

global packages:

    cordova (Cordova CLI) : 6.5.0 

local packages:

    @ionic/app-scripts : 3.0.0
    Cordova Platforms  : android 6.1.2 ios 4.3.1
    Ionic Framework    : ionic-angular 3.7.0

System:

    ios-sim : 5.0.13 
    Node    : v8.1.3
    npm     : 4.6.1 
    OS      : macOS Sierra
    Xcode   : Xcode 9.2 Build version 9C40b 

Environment Variables:

    ANDROID_HOME : not set

Misc:

    backend : legacy

Click not working on ion-button (e2e)

I 'm developing an Ionic 3 PWA (using lazy load). The tests was based on this example. I'm trying to do e2e tests.

My initial test is try to fill a form and click in the submit button of a login screen. I can select the button, altought the click event doesn't works. It should show an error message if the input are empty.

My test:


import { browser, by, WebElementPromise } from 'protractor';

describe('App', () => {

  beforeEach(() => {
    
  });

  describe('default screen', () => {
    beforeEach(() => {
      browser.navigateTo('http://10.0.1.63:8100/#/login');
    });

    

    it('It must work', () => {
              browser.findElement(by.css('#login-button')).then(function (element) {                    
                element.click().then(function (clickResult) {
                      console.log(clickResult) // it logs null
                  }).catch(function (error) {
                      console.error('ERROr ON CLICK', error)
                  });
              }).catch(function (error: Error) {
                  console.error('ERROR ON FIND ELEMENT', error)
              });
    });
        
  })
});


Package.json:
{
  "name": "ionic-unit-testing-example",
  "author": "Ionic Framework",
  "homepage": "https://ionicframework.com/",
  "private": true,
  "scripts": {
    "clean": "ionic-app-scripts clean",
    "build": "ionic-app-scripts build",
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve",
    "test": "karma start ./test-config/karma.conf.js",
    "test-ci": "karma start ./test-config/karma.conf.js --single-run",
    "e2e": "webdriver-manager update --standalone false --gecko false; protractor ./test-config/protractor.conf.js"
  },
  "dependencies": {
    "@angular/common": "4.1.2",
    "@angular/compiler": "4.1.2",
    "@angular/compiler-cli": "4.1.2",
    "@angular/core": "4.1.2",
    "@angular/forms": "4.1.2",
    "@angular/http": "4.1.2",
    "@angular/platform-browser": "4.1.2",
    "@angular/platform-browser-dynamic": "4.1.2",
    "@ionic-native/core": "3.12.1",
    "@ionic-native/splash-screen": "3.12.1",
    "@ionic-native/status-bar": "3.12.1",
    "@ionic/storage": "2.0.1",
    "ionic-angular": "3.3.0",
    "ionicons": "3.0.0",
    "rxjs": "5.1.1",
    "sw-toolbox": "3.4.0",
    "zone.js": "0.8.11"
  },
  "devDependencies": {
    "@ionic/app-scripts": "1.3.7",
    "@ionic/cli-plugin-ionic-angular": "1.4.1",
    "@types/jasmine": "^2.5.41",
    "@types/node": "^7.0.8",
    "angular2-template-loader": "^0.6.2",
    "html-loader": "^0.4.5",
    "ionic": "3.7.0",
    "jasmine": "^2.5.3",
    "jasmine-spec-reporter": "^4.1.0",
    "karma": "^1.5.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-jasmine": "^1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^2.0.3",
    "null-loader": "^0.1.1",
    "protractor": "^5.1.1",
    "ts-loader": "^2.0.3",
    "ts-node": "^3.0.2",
    "typescript": "2.3.3"
  },
  "version": "0.0.1",
  "description": "An Ionic project"
}

Mark repo as unsupported?

Hey,

Lots of people from your community are putting their time into improving this example.

#6 (comment)

If the above comment is accurate, do you think it'd be worth stating on the readme that there's no point raising issues or PR (or perhaps disable that altogether if that's possible)?

If the above comment is not accurate - great stuff ๐Ÿ˜ธ

Let us know

HTTP Error 404 Not Found for node-sass 4.5.0 for Windows 64 bit

D:\dev\git\ionic-unit-testing-example>npm i

[email protected] install D:\dev\git\ionic-unit-testing-example\node_modules\node-sass
node scripts/install.js

Downloading binary from https://github.com/sass/node-sass/releases/download/v4.5.0/win32-x64-59_binding.node
Cannot download "https://github.com/sass/node-sass/releases/download/v4.5.0/win32-x64-59_binding.node":

HTTP error 404 Not Found

Hint: If github.com is not accessible in your location
try setting a proxy via HTTP_PROXY, e.g.

  export HTTP_PROXY=http://example.com:1234

or configure npm proxy via

  npm config set proxy http://example.com:8080

[email protected] postinstall D:\dev\git\ionic-unit-testing-example\node_modules\node-sass
node scripts/build.js

Building: C:\Program Files\nodejs\node.exe D:\dev\git\ionic-unit-testing-example\node_modules\node-gyp\bin\node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=
gyp info it worked if it ends with ok
gyp verb cli [ 'C:\Program Files\nodejs\node.exe',
gyp verb cli 'D:\dev\git\ionic-unit-testing-example\node_modules\node-gyp\bin\node-gyp.js',
gyp verb cli 'rebuild',
gyp verb cli '--verbose',
gyp verb cli '--libsass_ext=',
gyp verb cli '--libsass_cflags=',
gyp verb cli '--libsass_ldflags=',
gyp verb cli '--libsass_library=' ]
gyp info using [email protected]
gyp info using [email protected] | win32 | x64
gyp verb command rebuild []
gyp verb command clean []
gyp verb clean removing "build" directory
gyp verb command configure []
gyp verb check python checking for Python executable "python2" in the PATH
gyp verb which failed Error: not found: python2
gyp verb which failed at getNotFoundError (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:13:12)
gyp verb which failed at F (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:68:19)
gyp verb which failed at E (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:80:29)
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:89:16
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\index.js:42:5
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\windows.js:36:5
gyp verb which failed at FSReqWrap.oncomplete (fs.js:166:21)
gyp verb which failed python2 { Error: not found: python2
gyp verb which failed at getNotFoundError (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:13:12)
gyp verb which failed at F (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:68:19)
gyp verb which failed at E (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:80:29)
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:89:16
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\index.js:42:5
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\windows.js:36:5
gyp verb which failed at FSReqWrap.oncomplete (fs.js:166:21)
gyp verb which failed stack: 'Error: not found: python2\n at getNotFoundError (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:13:12)\n at F (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:68:19)\n at E (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:80:29)\n at D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:89:16\n at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\index.js:42:5\n at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\windows.js:36:5\n at FSReqWrap.oncomplete (fs.js:166:21)',
gyp verb which failed code: 'ENOENT' }
gyp verb check python checking for Python executable "python" in the PATH
gyp verb which failed Error: not found: python
gyp verb which failed at getNotFoundError (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:13:12)
gyp verb which failed at F (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:68:19)
gyp verb which failed at E (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:80:29)
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:89:16
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\index.js:42:5
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\windows.js:36:5
gyp verb which failed at FSReqWrap.oncomplete (fs.js:166:21)
gyp verb which failed python { Error: not found: python
gyp verb which failed at getNotFoundError (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:13:12)
gyp verb which failed at F (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:68:19)
gyp verb which failed at E (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:80:29)
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:89:16
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\index.js:42:5
gyp verb which failed at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\windows.js:36:5
gyp verb which failed at FSReqWrap.oncomplete (fs.js:166:21)
gyp verb which failed stack: 'Error: not found: python\n at getNotFoundError (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:13:12)\n at F (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:68:19)\n at E (D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:80:29)\n at D:\dev\git\ionic-unit-testing-example\node_modules\which\which.js:89:16\n at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\index.js:42:5\n at D:\dev\git\ionic-unit-testing-example\node_modules\isexe\windows.js:36:5\n at FSReqWrap.oncomplete (fs.js:166:21)',
gyp verb which failed code: 'ENOENT' }
gyp verb could not find "python". checking python launcher
gyp verb could not find "python". guessing location
gyp verb ensuring that file exists: C:\Python27\python.exe
gyp ERR! configure error
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
gyp ERR! stack at PythonFinder.failNoPython (D:\dev\git\ionic-unit-testing-example\node_modules\node-gyp\lib\configure.js:483:19)
gyp ERR! stack at PythonFinder. (D:\dev\git\ionic-unit-testing-example\node_modules\node-gyp\lib\configure.js:508:16)
gyp ERR! stack at D:\dev\git\ionic-unit-testing-example\node_modules\graceful-fs\polyfills.js:284:29
gyp ERR! stack at FSReqWrap.oncomplete (fs.js:166:21)
gyp ERR! System Windows_NT 6.1.7601
gyp ERR! command "C:\Program Files\nodejs\node.exe" "D:\dev\git\ionic-unit-testing-example\node_modules\node-gyp\bin\node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd D:\dev\git\ionic-unit-testing-example\node_modules\node-sass
gyp ERR! node -v v9.4.0
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok
Build failed with error code: 1
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] postinstall: node scripts/build.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\carloslima\AppData\Roaming\npm-cache_logs\2018-01-18T17_33_33_853Z-debug.log

D:\dev\git\ionic-unit-testing-example>echo %HTTP_PROXY%
http://10.34.240.107:80

Webpack errors out on images

I cloned this repo and tried adding an image into src/assets/img and referencing in the Page1.html like so:

<img src="assets/img/lego.jpg">

However, webpack chokes on this with a "Module not found" error and prevents any of the tests from running:

ERROR in ./src/pages/page1/page1.html
Module not found: Error: Can't resolve './assets/img/lego.jpg' in 'C:\dev\ionic-unit-testing-example-master\src\pages\page1'
 @ ./src/pages/page1/page1.html 1:405-437
 @ ./src/pages/page1/page1.ts
 @ ./src/pages/page1/page1.spec.ts
 @ ./src \.spec\.ts
 @ ./test-config/karma-test-shim.js

I assume this requires a modification to the webpack.config.js to get it to look in the correct location but I am not that familiar with webpack so I'm not sure the fix. I did note that images are loaded using "null_loader" which I understand just loads a null module, in which case I am not sure why webpack cares about where the image is.

Anyone know what needs to be changed to prevent this problem?

How to mock a service which has http requests?

Hey,
I know this is not the right platform to ask this, but on right platform, there is no reply from anyone.
How to mock a service which contains http requests?
For eg:

I want to test my provider class, so I am unable to write spec for providers.
My provider is as follows:
service.ts

//imports are done correctly.  
@Injectable() 
export class Service {     
constructor(private http: Http) { }      
getGoogle():Observable<any> {        
 console.log("Inside service");       
  return this.http.get('https://jsonplaceholder.typicode.com/posts/1');   
  } }

My page.ts is as follows:

page.ts

**//imports are done correctly.

  export class Page1 {  
  constructor(private service: Service, private navCtrl: NavController) { }   
async get() {     console.log("inside get method");     
const data =  await this.service.getGoogle().toPromise();       
console.log('The response is' , data);       
 } } 

service.spec.ts

//imports are done correctly  

describe('Service', () => 
{     let comp: Service;    
 let fixture: ComponentFixture<Service>;    
 let de: DebugElement;      
 beforeEach(async(() => {         
TestBed.configureTestingModule({             
declarations: [],             
imports: [               
 IonicModule.forRoot(Service)           
   ],            
 providers: [Http]       

  }).compileComponents();   

   }));     

beforeEach(() => {        

 fixture = TestBed.createComponent(Service);      
  comp = fixture.componentInstance;         
 de = fixture.debugElement;   
  });    

 afterEach(() => {       

  fixture.destroy();    

 }); 

it('test the http request to te server', ()=>{           

   //code to test http request of the Service class  }); 

 });** 

All the imports are done correctly, only the logic to test the getGoogle() with http.get() needs to be tested.Please help or share some links or tell me some steps in order to do testing of this ionic2 content.

Thanks
Adi

How to choose Chrome User Profile before a test (e2e)?

I would like to choose Chrome user profile to test my app so that I can do login mannually before run the tests.

In the way it works today it opens a new user profile which only exists during the test execution.

How to choose Chrome User Profile before a test (e2e)?

Question/Discussion: E2E headless browser

Seems I've misunderstood the E2E browser only clause about his repo.

Has anyone got this to work in a CI/CD pipeline?

I have experimented with this repo and running e2e in Bitbucket Pipelines.

Seems it Protractor clear method does not work while running a headless chrome browser.

Any feedback or workarounds are welcome here.

How can we mock the service that makes http requests, in order to test the component?

Hey,
How can we test http requests in ionic?
For example:

Service.ts

//assume all the imports are done.

@Injectable()
export class Service {

    public http: string;

    constructor(private http: Http) { }

    getGoogle():Observable<any> {
        console.log("Inside service");
        return this.http.get('https://jsonplaceholder.typicode.com/posts/1');
    }
}

page1.ts


//all imports are done.

@Component({
  selector: 'page-page1',
  templateUrl: 'page1.html',
})
export class Page1 {
 
  constructor(private service: Service) {

   get() {
    console.log("inside get method");
    this.service.getGoogle().subscribe(
      (response:Response)=>{
        console.log('The resonse is', response);
      }
    ); 
  }
   

spec.ts

//all the imports are done.

describe('Page1 to be tested', () => {

    let fixture: ComponentFixture<Page1>;
    let comp: Page1;
    let de: DebugElement;
    let el: HTMLElement;
    // let service: null;


    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [Page1],
            imports: [
                IonicModule.forRoot(Page1),
            ],
            providers: [NavController,
                // service = fixture.debugElement.injector.get(Service)
                { provide: Service, useClass: ServiceMock }
            ],
        }).compileComponents();
    }
    ));
    beforeEach(() => {
        fixture = TestBed.createComponent(Page1);
        comp = fixture.componentInstance;
        de = fixture.debugElement;
        let service = TestBed.get(Service);
        //  let service1 = fixture.debugElement.injector.get(Service);

    });

    it('is created', () => {
        expect(comp).toBeTruthy();
        expect(fixture).toBeDefined();
    });
  });


1.) How will I test my HTTP request that is made to the server?
2.)When to use a mock-backend?

Thanks
Adi

References

Hey All,

Thanks a lot for getting around to this. I can finally deprecate https://github.com/lathonez/clicker, which I plan on doing immediately. It's certainly been a long time coming but I'm glad it's here :)

Based on Josh Morony's excellent Unit Testing guides and sample app.

Josh's guides are amazing - much better than anything I could put together. As Josh's write-ups and sample app are based on clicker (he kindly references me here: https://www.joshmorony.com/introduction-to-testing-ionic-2-applications-with-testbed/), I expected to be mentioned here in a similar fashion.

One of my first users, @BugsBunnyBR raised a PR ionic-team/ionic-framework#5579 in February 2016 to merge Clicker into ionic-app-base. This PR is still open against ionic-app-scripts (and I still contribute to it) on ionic-team/ionic-app-scripts#687.

lathonez/clicker@7b1a80c in October 2016 is the first example of an Ionic App leveraging angular/cli for testing (very happy to be corrected on this) - which this repo is ultimately based on.

I've also kept a pretty comprehensive changelog if you're interested: https://github.com/lathonez/clicker/blob/master/CHANGELOG.md

If you need further convincing, compare your src/mocks.ts with mine ๐Ÿ˜‰

References aside, thanks for the fantastic work you've done with Ionic 2. For me the introduction of this repository makes the framework complete.

Thanks,

Stephen

unable to execute test cases

Hi team,
I am getting below error when i tried in my project

PhantomJS 2.1.1 (Windows 8 0.0.0) Reverse unit test s toBeUndefined Should Controller exist FAILED
D:/InsightApp3rdMarch/www/lib/angular/angular.js:4641:53
forEach@D:/InsightApp3rdMarch/www/lib/angular/angular.js:321:24
loadModules@D:/InsightApp3rdMarch/www/lib/angular/angular.js:4601:12
createInjector@D:/InsightApp3rdMarch/www/lib/angular/angular.js:4523:30
workFn@D:/InsightApp3rdMarch/www/lib/angular-mocks/angular-mocks.js:3074:60
loaded@http://localhost:9876/context.js:162:17
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0 secs / 0.018 secs)

Collection of Ionic Mocks for Use in Every Project

EDIT: I just realized that the main place I've grabbed Ionic mock from was the Clicker project. mocks.ts. Thanks to @lathonez for making this file available.

I created this issue to begin a discussion around mock objects in Ionic (and I'm not sure where else to have this discussion).

I've been doing a lot of unit testing lately for an Ionic 2 application. One of the things I've found to be very helpful is that there appear to be many mock objects available out there for use in Ionic unit testing. I've put together a few objects that I've needed in a current project into one file so that I can reference them. Take a look.

FYI:

  1. While I have made adjustments to this code, it is not mine. I've found these objects sprinkled over Stack Overflow and else where.
  2. These mocks are working for me, but Your Mileage May Vary.

Here's my issue. For this project, having reliable Ionic mocks is important. We should be unit testing our applications, not the Ionic Framework. There is no reason for each of us to be building their own set of Ionic mocks. As a community, we should be able to assemble these mocks.

Shouldn't we be able to provide mocks for as many of the Ionic pieces that may be needed?

Shouldn't we be able to provide best practices as to where to place these mocks and how to use them?

Re: Best practices: Currently, I have three files in my project:

  • src/testing/mock-ionic.ts: Ionic mocks
  • src/testing/mock-app.ts: mocks of object created in my project
  • src/testing/mock-data.ts: mock data that I can use with my mock services

This is how I've organized my current project. Again, YMMV.

Let the discussion begin.

e2e tests not running

I just tried this repo and e2e tests do not run.

I cloned it, npm installed, served, then e2e tests and this is all I get:

D:\dvlp\ionic\aa-test>npm run e2e

[email protected] e2e D:\dvlp\ionic\aa-test
webdriver-manager update --standalone false --gecko false; protractor ./test-config/protractor.conf.js

[14:41:05] I/update - chromedriver: file exists D:\dvlp\ionic\aa-test\node_modules\protractor\node_modules\webdriver-manager\selenium\chromedriver
_2.30.zip
[14:41:05] I/update - chromedriver: unzipping chromedriver_2.30.zip
[14:41:06] I/update - chromedriver: chromedriver_2.30.exe up to date
[14:41:06] I/update - geckodriver: file exists D:\dvlp\ionic\aa-test\node_modules\protractor\node_modules\webdriver-manager\selenium\geckodriver-v
0.17.0.zip
[14:41:06] I/update - geckodriver: unzipping geckodriver-v0.17.0.zip
[14:41:06] I/update - geckodriver: geckodriver-v0.17.0.exe up to date

D:\dvlp\ionic\aa-test>

I assume I'm supposed to get some type of test results?

Can't resolve all parameters for navParams?

After cloning the Repo of ionic-unit-testing-example I wrote test cases to initialise Page2, So it failed by showing an error thatCan't resolve all parameters for navParams?

import { async, TestBed, ComponentFixture } from "@angular/core/testing";
import { Page2 } from "./page2";
import { IonicModule, NavController } from "ionic-angular/index";
import { DebugElement } from "@angular/core";
import { By } from "@angular/platform-browser";
import { NavParams } from "ionic-angular/navigation/nav-params";

describe('Page2 should be tested', () => {
    let comp: Page2;
    let fixture: ComponentFixture<Page2>;
    let de : DebugElement;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [Page2],
            imports: [IonicModule.forRoot(Page2)],
            providers: [
                NavController,
                NavParams
            ]
        })
    }));
        beforeEach( ()=>{
            fixture = TestBed.createComponent(Page2);
                comp  = fixture.componentInstance;
                de   = fixture.debugElement.query(By.css('h4'));
        });

        it('against component initialisation', ()=>{
            expect(fixture).toBeTruthy();
            expect(comp).toBeDefined();
        })

})

Please suggest?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.