Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting up Karma config for Hybrid Angular 2/1x app

For simplicity, I'll be referring to my Angular 1x version (1.6) as AngularJS and Angular 2/4x (4.0) as Angular.

I've been working on migrating a large AngularJS app to Angular, using the UpgradeModule approach as documented in the official documentation.

The app is running fine but I'm now trying to run all of the existing unit tests via Karma, and after quite a bit of Googling I'm struggling to understand exactly how my Karma config needs to be set up.

Even though my app is now a hybrid of Angular and AngularJS, all of my existing modules are still written in AngularJS. **I haven't yet added any Angular modules except for the root module that bootstraps AngularJS.

My app is compiled using a combination of gulp > browserify > tsify. Here is a snippet of my build steps:

return function() {
        var bundler = browserify([
            'src/app.d.ts',
            'src/app.ts',
            'src/main.module.ajs.ts'
        ], {
            debug: true
        })
        .plugin(tsify)
            .transform(babelify.configure({
                presets: ["es2015"]
            }));

        return bundler
            .bundle()
            .pipe(source('main.js'))
            .pipe(buffer())
            .pipe(sourcemaps.init({
                loadMaps: true,
                sourceRoot: '/src'
            }))

            .pipe(sourcemaps.write('./'))
            .pipe(gulp.dest(paths.scripts.dest));

This is the main entry file to my app:

app.ts

import 'core-js/es6/reflect';
import 'core-js/es7/reflect';

import 'zone.js/dist/zone';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';

import { AppModule } from './main.module';

platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
    const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
    upgrade.bootstrap(document.documentElement, ['main']);
});

This is the Angular module:

main.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';

@NgModule({
    imports: [
        BrowserModule,
        UpgradeModule
    ],
})

export class AppModule {
    ngDoBootstrap() {}
}

This is the AngularJS module:

main.module.ajs.ts

import './authentication/authentication.module';

import { MainController } from './main.controller';

import { CONFIGURATION } from '../config';

angular
    .module('main', [
        'authentication',
    ])
    .controller('MainController', MainController)
    .config(applicationRouting)
    .run(applicationInit)
    .constant('CONFIGURATION', CONFIGURATION);

function applicationInit($rootScope, CONFIGURATION) {
    $rootScope.CONFIGURATION = CONFIGURATION;
}

function applicationRouting($routeProvider, $analyticsProvider) {
    $analyticsProvider.firstPageview(false);
    $analyticsProvider.virtualPageviews(false);
    $routeProvider
        .when('/?', {
                reloadOnSearch: false
        })
        .otherwise({
                redirectTo: '/'
        });
}

..and finally, my karma config file:

karma.conf.js

module.exports = function(config) {
    config.set({
        basePath: '',
        frameworks: ['browserify', 'jasmine'],
        plugins: ['karma-jasmine', 'karma-chrome-launcher', 'karma-coverage', 'karma-ng-html2js-preprocessor', 'karma-browserify'],
        files: [
            'node_modules/jquery/dist/jquery.js',
            'node_modules/angular/angular.js',
            'node_modules/angular-route/angular-route.min.js',
            'node_modules/angular-mocks/angular-mocks.js',
            'node_modules/lodash/lodash.min.js',
            'node_modules/angular-messages/angular-messages.min.js',
            'node_modules/angular-sanitize/angular-sanitize.min.js',
            'node_modules/vis/dist/vis.min.js',
            'node_modules/moment/min/moment.min.js',
            'node_modules/pikaday/pikaday.js',
            'node_modules/filesaver.js/FileSaver.min.js',
            'node_modules/angulartics/src/angulartics.js',
            'node_modules/angulartics/dist/angulartics-piwik.min.js',
            'node_modules/jsencrypt/bin/jsencrypt.min.js',
            'node_modules/d3/d3.min.js',
            'node_modules/node-uuid/uuid.js',
            'node_modules/angular-vs-repeat/src/angular-vs-repeat.js',

            'src/**/*.module.js',
            'src/**/!(*.spec).js',
            'src/**/*.spec.js',
            'src/**/*.tpl.html'
        ],
        browserify: {
            debug: true,
            transform: [
                ['babelify', {
                    presets: ['es2015']
                }]
            ]
        },
        preprocessors: {
            'src/app.d.ts': ['browserify'],
            'src/app.ts': ['browserify'],
            'src/main.module.ajs.ts': ['browserify'],
            'src/**/!(*.spec).js': ['browserify'],

            'src/**/*.tpl.html': 'ng-html2js'
        },
        ngHtml2JsPreprocessor: {
            stripPrefix: 'src/',
            moduleName: 'dir-templates'
        },
        reporters: ['dots'],
        colors: true,
        port: 9018,
        runnerPort: 9101,
        autoWatch: true,
        browsers: [
            'Chrome'
        ],
        captureTimeout: 5000,
        logLevel: 'DEBUG'
    });
};

As you can see in the config file, I include all of my app's third party libraries. Before switching to the hybrid app, this set up worked fine, but I assume that now my app is essentially 'wrapped' with the new Angular framework, I'm gonna need to do some configuration changes.

I'm just not entirely clear what needs to happen. When I try to run my tests with this set up, I get the following error:

Error: [$injector:modulerr] Failed to instantiate module routing due to:
Error: [$injector:modulerr] Failed to instantiate module authentication due to:
Error: [$injector:modulerr] Failed to instantiate module utils due to:
Error: [$injector:modulerr] Failed to instantiate module timeline due to:
Error: [$injector:modulerr] Failed to instantiate module events due to:
Error: [$injector:modulerr] Failed to instantiate module rest due to:
Error: [$injector:modulerr] Failed to instantiate module main due to:
Error: [$injector:nomod] Module 'main' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.6.1/$injector/nomod?p0=main
    at node_modules/angular/angular.js:68:12
    at node_modules/angular/angular.js:2183:17
    at ensure (node_modules/angular/angular.js:2107:38)
    at module (node_modules/angular/angular.js:2181:14)
    at node_modules/angular/angular.js:4736:22
    at forEach (node_modules/angular/angular.js:357:20)
    at loadModules (node_modules/angular/angular.js:4720:5)
    at node_modules/angular/angular.js:4737:40
    at forEach (node_modules/angular/angular.js:357:20)
    at loadModules (node_modules/angular/angular.js:4720:5)

So it's clearly not able to find the 'main' AngularJS module in order to run the tests.

Any help will be greatly appreciated! Let me know if you need more information.

like image 701
remi90 Avatar asked May 11 '17 08:05

remi90


1 Answers

Well this is a really old question and I don't know if it's still relevant but here it is:

There is a golden method of UpgradeAdapter called registerForNg1Tests() that you should try out. Here is a complete guide.

like image 146
theJediCode Avatar answered Oct 15 '22 16:10

theJediCode