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

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.

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.

Related

Angular migration - Hybrid application is not bootstrapping

I am working on migrating my Angularjs 1.6 application to Angular 7 via ngUpgrade route, after all done when I'm trying to bootstrap my hybrid application, it's failing to bootstrap, I noticed that my main.ts file isn't executing at all where as I've added it as entry point in my webpack config.
I'm using template.ejs file as template in my HtmlWebpackPlugin. For Webpack settings and package.json, Please check my application bundling and bootstrapping code on github here:
https://github.com/mmmathur/AngularMigration
I tried with renaming it as index.ts as well but still no luck.
main.ts
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { UpgradeModule } from '#angular/upgrade/static';
import { AppModule } from '../client/ngApp/ngApp.module';
const app = require('../client/app');
let appRoot = document.createElement('div');
const uiView = document.createElement('ui-view');
let body = document.querySelector('body');
appRoot.appendChild(uiView);
body.appendChild(appRoot);
console.log('executing main.ts');//even this statement is not executed
platformBrowserDynamic().bootstrapModule(AppModule).then((platformRef) => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.documentElement, [app]);
console.log('hybrid application is bootstrapped');
})
.catch(err => console.error(err))
ngAppModule.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import {HttpModule} from '#angular/http';
import { FormsModule} from '#angular/forms';
import {UpgradeModule} from '#angular/upgrade/static';
import { AppComponent } from './ngApp.component';
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
UpgradeModule
],
declarations: [
AppComponent
],
bootstrap: [
AppComponent
],
entryComponents: [
]
})
export class AppModule {}
ngApp.component.ts
import { Component } from "#angular/core";
#Component({
selector: 'ng-app',
template: `
<div>
<h2>Angular 7 application bootstraped</h2>
</div>
`
})
export class AppComponent {}
Expected: my Hybrid application gets bootstrapped.
Actual: a blank screen with no error thrown.
UPDATE Issue was these lines:
optimization:
{
splitChunks: {
chunks: 'all'
}
}
Optimization was causing this issue, once I removed above config option from webpack, application at least starting bootstrapping, though this time I'm getting error like:
Uncaught Error: Can't resolve all parameters for ApplicationModule: (?).
at syntaxError (compiler.js:2547)
at CompileMetadataResolver../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata (compiler.js:17874)
at CompileMetadataResolver../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getTypeMetadata (compiler.js:17767)
at CompileMetadataResolver../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (compiler.js:17635)
at CompileMetadataResolver../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleSummary (compiler.js:17445)
at compiler.js:17559
at Array.forEach (<anonymous>)
at CompileMetadataResolver../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (compiler.js:17547)
at CompileMetadataResolver../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleSummary (compiler.js:17445)
at compiler.js:17532
I tried to fix this by adding polyfills.ts file in my project
Polyfills.ts
import 'core-js/es7/reflect';
import 'core-js/client/shim';
import 'zone.js/dist/zone.js';
but still getting same error, I'm using core-js 3.2.1.
looking if someone have idea about what's going wrong with my code?
UPDATE I learned that I supposed to add polyfills.ts file in HtmlWebpackPlugin-->chunks array as well, after adding, it started picking polyfills file and now that error has gone and now my angularjs app also getting bootstrapped along side angular 7 app, however now I'm getting another error like:
Error: [$injector:modulerr] Failed to instantiate module $$UpgradeModule due to:
Error: [$injector:modulerr] Failed to instantiate module {"default":"ui.app"} due to:
Error: [ng:areq] Argument 'module' is not a function, got Object
https://errors.angularjs.org/1.6.10/$injector/modulerr?p0=%24%24UpgradeModule&p1=Error%3A%20%5B%24injector%3Amodulerr%5D%20Failed%20to%20instantiate%20module%20%7B%22default%22%3A%22ec.customer.servicing.ui.app%22%7D%20due%20to%3A%0AError%3A%20%5Bng%3Aareq%5D%20Argument%20'module'%20is%20not%20a%20function%2C%20got%20Object%0A%0Ahttps%3A%2F%2Ferrors.angularjs.org%2F1.6.10%2F%24injector%2Fmodulerr%3Fp0%3D%257B%2522default%2522%253A%2522ec.customer.servicing.ui.app%2522%257D%26p1%3DError%253A%2520%255Bng%253Aareq%255D%2520Argument%2520'module'%2520is%2520not%2520a%2520function%252C%2520got%2520Object%250Ahttps%253A%252F%252Ferrors.angularjs.org%252F1.6.10%252Fng%252Fareq%253Fp0%253Dmodule%2526p1%253Dnot%252520a%252520function%25252C%252520got%252520Object%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A32020%253A12%250A%2520%2520%2520%2520at%2520assertArg%2520(http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A33994%253A11)%250A%2520%2520%2520%2520at%2520assertArgFn%2520(http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A34004%253A3)%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A36915%253A11%250A%2520%2520%2520%2520at%2520forEach%2520(http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A32313%253A20)%250A%2520%2520%2520%2520at%2520loadModules%2520(http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A36889%253A5)%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A36907%253A40%250A%2520%2520%2520%2520at%2520forEach%2520(http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A32313%253A20)%250A%2520%2520%2520%2520at%2520loadModules%2520(http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A36889%253A5)%250A%2520%2520%2520%2520at%2520createInjector%2520(http%253A%252F%252Flocalhost%253A8080%252Fng1.bundle.js%253F29bb21d813a74a626d53%253A36806%253A19)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A32020%3A12%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A36929%3A15%0A%20%20%20%20at%20forEach%20(http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A32313%3A20)%0A%20%20%20%20at%20loadModules%20(http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A36889%3A5)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A36907%3A40%0A%20%20%20%20at%20forEach%20(http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A32313%3A20)%0A%20%20%20%20at%20loadModules%20(http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A36889%3A5)%0A%20%20%20%20at%20createInjector%20(http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A36806%3A19)%0A%20%20%20%20at%20doBootstrap%20(http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A33860%3A20)%0A%20%20%20%20at%20Object.bootstrap%20(http%3A%2F%2Flocalhost%3A8080%2Fng1.bundle.js%3F29bb21d813a74a626d53%3A33881%3A12)
at angular.js:125
at angular.js:5034
at forEach (angular.js:418)
at loadModules (angular.js:4994)
at createInjector (angular.js:4911)
at doBootstrap (angular.js:1965)
at Object.bootstrap (angular.js:1986)
at bootstrap (static.js:76)
at static.js:1595
at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
Any idea what's going wrong here?
If you're migrating from AngularJS probably the <script> tag for your bundle is inside the head segment. Move it to the end of body
<html>
<head>
</head>
<body>
... ...
<script src="dist/main.js" charset="utf-8"></script>
</body>
</html>

AngularJs Multiple Times loaded

I have a problem with upgrade my angularJs Application to Webpack4.
this is my setup:
vendor.ts
import "angular";
import "angular-i18n/de-de";
import "angular-route";
and
main.ts
import {MyAppModule} from "./my-app.app";
angular.element(document).ready(() => {
angular.bootstrap(document.body, [MyAppModule.name], { strictDi: true });
});
With webpack 3. I had a commonsChunkPlugin and everything worked.
With webpack 4, I'm using the splitChunks option to not import angularjs 5 times:
webpack.config.ts
...
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: "commons",
chunks: "initial",
minChunks: 2
}
}
}
}
...
That is working correctly. I have loaded the angularjs code only in my common.js file. But unfortunatelly the code is instantiated twice, so the app always logs the warning:
WARNING: Tried to load AngularJS more than once.
The chunks are loaded via HtmlWebpackPlugin in the html.
Any idea how to remove the warning?
Found the solution in the deeps of github issues:
The vendor file should not be an entry point but the entry point should be a list of files:
...
entry: {
main: ['./vendor.js', './main.js']
},
...

While bootstrapping a hybrid angular 1 + 2 application, how do you initialize the angular 1 injector?

To recreate the issue, I forked the Angular Quickstart plunker.
I have this simple angular 1.x module:
'use strict';
angular.module('testModule', [])
.factory('testService', function($q, $log, $interval, $rootScope){
//Create a service object that we'll build up with methods and eventually
//return.
var service = {};
service.test = 'test';
return service;
});
I have this angular 2 module which references the angular 1.x $injector to get the angular 1.x module as a provider:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { UpgradeModule } from '#angular/upgrade/static';
import { AppComponent } from './app.component';
#NgModule({
imports: [
BrowserModule,
UpgradeModule
],
declarations: [
AppComponent
],
bootstrap: [ AppComponent ],
providers: [{
provide: 'testModule',
useFactory: (i: any) => i.get('testModule'),
deps: ['$injector']
}]
})
export class AppModule {
ngDoBootstrap() {}
}
And I have my angular 2 component which requests the angular 1.x module via dependency injection:
import { Component, Inject } from '#angular/core';
#Component({
selector: 'my-app',
template: `<h1>Hello {{name}}, my name is {{myName}}</h1>`
})
export class AppComponent {
name = 'Angular';
constructor(#Inject('testModule') testModule: any) {
this.myName = testModule.test;
}
}
I then bootstrap the angular 2 module and the angular 1.x module
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, ['testModule'], {strictDi: true});
});
I then get this error TypeError: Cannot read property 'get' of undefined
at useFactory which is occurring from within the arrow function specified as the "useFactory" property of the provider definition I have in the angular 2 module
providers: [{
provide: 'testModule',
useFactory: (i: any) => i.get('testModule'),
deps: ['$injector']
}]
I think there is something I'm not understanding about how to initialize the angular 1.x injector in a hybrid angular 1 + 2 application. You can see I am pulling angular 1.x in via script tag, otherwise my angular 1.x module will throw an error about "angular" not being defined, and I suspect the problem may be related to that. If anyone could provide guidance, I'd appreciate it.
Here is the plunker: https://plnkr.co/edit/wdR7K4rDKoF8L0pfQypM?p=info
Here is the error with call stack:
TypeError: Cannot read property 'get' of undefined
at useFactory (https://run.plnkr.co/IgsjEBjD2d29O3YH/app/app.module.ts!transpiled:32:56)
at AppModuleInjector.get (/AppModule/module.ngfactory.js:140:65)
at AppModuleInjector.getInternal (/AppModule/module.ngfactory.js:192:46)
at AppModuleInjector.NgModuleInjector.get (https://unpkg.com/#angular/core/bundles/core.umd.js:8918:48)
at CompiledTemplate.proxyViewClass.AppView.injectorGet (https://unpkg.com/#angular/core/bundles/core.umd.js:12319:49)
at CompiledTemplate.proxyViewClass.DebugAppView.injectorGet (https://unpkg.com/#angular/core/bundles/core.umd.js:12699:53)
at CompiledTemplate.proxyViewClass.View_AppComponent_Host0.createInternal (/AppModule/AppComponent/host.ngfactory.js:15:63)
at CompiledTemplate.proxyViewClass.AppView.createHostView (https://unpkg.com/#angular/core/bundles/core.umd.js:12275:25)
at CompiledTemplate.proxyViewClass.DebugAppView.createHostView (https://unpkg.com/#angular/core/bundles/core.umd.js:12683:56)
at ComponentFactory.create (https://unpkg.com/#angular/core/bundles/core.umd.js:7710:29)
at ApplicationRef_.bootstrap (https://unpkg.com/#angular/core/bundles/core.umd.js:8677:61)
at eval (https://unpkg.com/#angular/core/bundles/core.umd.js:8506:93)
at Array.forEach (native)
at PlatformRef_._moduleDoBootstrap (https://unpkg.com/#angular/core/bundles/core.umd.js:8506:46)
at eval (https://unpkg.com/#angular/core/bundles/core.umd.js:8458:31)
I had same issue and found solution for my case on github.
Take a look at updated plunker. Note that there were also others not related issues in you code. Commented <script src="test-module.js"></script> and implicit injection parameters for testService.
Hope it will help you.

Module 'templates' is not available! in angular js?

I am trying to test directive in angular using Jasmine. I installed karma-ng-html2js-preprocessor using NPM. Then I istalled jQuery using Bower but I am getting this error
Connected on socket ndfTI8XJInIU5YJCAAAA with id 49983199
Chrome 47.0.2526 (Mac OS X 10.10.2) http controller test it should be one FAILED
Error: [$injector:modulerr] Failed to instantiate module templates due to:
Error: [$injector:nomod] Module 'templates' 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.4.8/$injector/nomod?p0=templates
at /Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:68:12
at /Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:2005:17
at ensure (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:1929:38)
at module (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:2003:14)
at /Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/a
I made directive like this
angular.module('app',[]).controller('first',function($scope,data){
$scope.name='test';
$scope.message='application';
data.getData().then(function(data){
console.log(data);
})
}).factory('data',function($http){
return{
getData:getData
}
function getData(){
return $http.get('data.json').success(successCall).error(errorcallback)
}
function successCall(data){
return data
}
function errorcallback(data){
return data
}
}).directive('helloWorld',function(){
return {
restrict:'E',
scope:{
data:'=',
message:'#'
} ,
templateUrl:'app/partial/home.html',
link:function(s,e,a){
}
}
})
home.html
<div class="dir">
<h1>{{data}}</h1>
<h1>{{message}}</h1>
</div>
test.js
describe('http controller test', function () {
var $rootScope,
$scope,
$compile,
$body=$('body'),
el,
$el,
controller,
html='<hello-world data="name" message="{{message}}"></hello-world>';
beforeEach(function(){
module('templates','app') ;
inject(function($injector){
$rootScope = $injector.get('$rootScope') ;
$compile = $injector.get('$compile') ;
$scope=$rootScope.$new();
el=$compile(angular.element(html))($scope)
controller =$injector.get('$controller')('first',{$scope:$scope})
})
$body.append(el);
$rootScope.$digest();
$el=$('.dir');
})
afterEach(function(){
$body.empty();
})
it('it should be one',function(){
expect($el.length).isEqual(1)
})
describe('Init value',function(){
it('check name value',function(){
expect($scope.name).toEqual('test');
})
})
it('it should be true',function(){
expect(true).toBeTruthy();
})
})
and there is karma-config file
// Karma configuration
// Generated on Fri Dec 18 2015 19:53:32 GMT+0530 (IST)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'bower_components/angular/angular.js' ,
'bower_components/jquery/dist/jquery.js' ,
'bower_components/angular-mocks/angular-mocks.js' ,
'bower_components/angular-resource/angular-resource.js' ,
'app/**/.html',
'app/*.js',
'test/**.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'app/**/.html':['ng-html2js']
},
ngHtml2JsPreprocessor:{
moduleName:'templates'
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultanous
concurrency: Infinity
})
}
I already declared the template module like this
ngHtml2JsPreprocessor:{
moduleName:'templates'
},
update 1
Connected on socket i5kkzULDwF1_ptvcAAAA with id 55433592
Chrome 47.0.2526 (Mac OS X 10.10.2) http controller test it should be one FAILED
Error: [$injector:modulerr] Failed to instantiate module templates due to:
Error: [$injector:nomod] Module 'templates' 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.4.8/$injector/nomod?p0=templates
at /Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:68:12
at /Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:2005:17
at ensure (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:1929:38)
at module (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:2003:14)
at /Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:4435:22
at forEach (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:340:20)
at loadModules (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:4419:5)
at Object.createInjector [as injector] (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular/angular.js:4344:11)
at Object.workFn (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular-mocks/angular-mocks.js:2428:52)
at window.inject.angular.mock.inject (/Users/naveenkumar/Documents/ionic_work/tes/bower_components/angular-mocks/angular-mocks.js:2411:37)
http://errors.angularjs.org/1.4.8/$injector/modulerr?p0=templates&p1=Error%3A%20%5B%24injector%3Anomod%5D%20Module%20'templates'%20is%20not%20available!%20You%20either%20misspelled%20the%20module%20name%20or%20forgot%20to%20load%20it.%20If%
I have no prior experiences with karma-ng-html2js-preprocessor so this is more like a guess - could it be that template module was not generated because no templates were found.
Could you try to change this part of files section of your karma-config from:
'app/**/.html'
to:
'app/**/*.html'
and preprocessors section from:
preprocessors: {
'app/**/.html':['ng-html2js']
}
to
preprocessors: {
'app/**/*.html':['ng-html2js']
}
Update:
If that doesn't work for you, you could set log level of Karma to
logLevel: config.LOG_DEBUG
and try to search for lines starting with DEBUG [preprocessor.html2js] to gather additional info related to html2js preprocessor.

Angular and ES6: Karma Testing with SystemJS

Afternoon all,
I have a MEAN stack app that I am developing tests for. The Angular code is written using ES6 so I have been trying to configure Karma and SystemJS with Babel as the transpiler to run my tests. Currently, when I karma start karma.conf.js the browser fires up, hangs—as in I cannot click debug or anything else—, and then the browser closes with the console error:
Uncaught TypeError: Cannot set property 'mock' of undefined.
The last line before this is DEBUG [web-server]: serving (cached): ( ... )
My current application structure works like this:
I have all of my module imported into one file app.js where they are injected into my app module:
import HomeController from './components/home/home.js';
import HomeService from './services/homeservice.js';
import HomeDirective from './directives/homedirective.js';
import DifferentController from './components/different/different.js';
// ### Filters
import slugifyFilter from './filters/slugify.js';
var moduleName = 'app';
angular.module(moduleName, ['ngNewRouter', 'ngMock', 'ngAnimate', 'ui.bootstrap', 'slugifyFilter'])
.config(['$componentLoaderProvider', SetTemplatesPath])
.controller('AppController', ['$router', AppController]);
function SetTemplatesPath ($componentLoaderProvider){
$componentLoaderProvider.setTemplateMapping(name => `components/${name}/${name}.html`);
}
function AppController ($router) {
$router.config([
// Component is just a template + controller
// in 'components' folder
{ path: '/', redirectTo: '/home' },
{ path: '/home', component: 'home' },
{ path: '/different/:id', component: 'different' }
]);
}
export default moduleName;
I use manual Angular bootstrapping in my index.html file as so:
import { default as AppModule } from './app.js';
angular.bootstrap(document, [ AppModule ]);
try {
$(document.body).attr("ng-app", "app");
} catch(e){};
I have Karma and SystemJS configured as so:
// Karma configuration
// Generated on Tue Jul 07 2015 19:56:15 GMT-0400 (Eastern Daylight Time)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: './',
files : [],
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['systemjs', 'jasmine'],
plugins : ['karma-systemjs', 'karma-jasmine', 'karma-chrome-launcher',
'karma-firefox-launcher', 'karma-ie-launcher' ],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: { "**/*.html": ['ngbootstrapfix'] },
systemjs : {
// Path to SystemJS config file
//configFile : 'public/system.conf.js',
// File patterns for application code, dependencies, and test suites
files : [
'public/bower_components/jquery/dist/jquery.js',
'public/bower_components/angular/angular.js',
'public/bower_components/angular-mocks/angular-mocks.js',
'public/bower_components/angular-animate/angular-animate.js',
'public/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'public/bower_components/angular-new-router/dist/router.es5.js',
'public/bower_components/angular-messages/angular-messages.js',
'public/**/*.js'
],
// SystemJS configuration specifically for tests, added after your config file.
// Good for adding test libraries and mock modules
config: {
baseURL : '/',
// Set path for third-party libraries as modules
paths : {
'jquery': 'public/bower_components/jquery/dist/jquery.js',
'angular-mocks': 'public/bower_components/angular-mocks/angular-mocks.js',
'angular' : 'public/bower_components/angular/angular.js',
'angular-animate' : 'public/bower_components/angular-animate/angular-animate.js',
'ui-bootstrap' : 'public/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'router' : 'public/bower_components/angular-new-router/dist/router.es5.js',
'angular-messages' : 'public/bower_components/angular-messages/angular-messages.js',
'babel': 'node_modules/babel-core/browser.js',
'es6-module-loader': 'node_modules/es6-module-loader/dist/es6-module-loader.js',
'systemjs': 'node_modules/systemjs/dist/system.js',
'system-polyfills': 'node_modules/systemjs/dist/system-polyfills.js'
},
transpiler: 'babel'
},
// Specify the suffix used for test suite file names. Defaults to .test.js, .spec.js, _test.js, and _spec.js
testFileSuffix: '-spec.js'
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_DEBUG,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
};
I have a filter here that I am trying to test:
let moduleName = 'slugifyFilter';
angular.module(moduleName, [])
.filter('slugify', () => {
return (input) => {
input = input || '';
return input.replace(/ /g, '-').toLowerCase();
};
});
export default moduleName;
And my test file:
import 'angular-mocks';
import '../bootstrap.js';
describe('slugify filter', function() {
beforeEach(function() {
angular.mock.module('app');
});
beforeEach(angular.mock.inject(function(_$filter_) {
var $filter = _$filter_;
}));
it('returns a slug when given a string', function() {
var slugify = $filter('slugify');
expect(slugify('Home Component 3')).toContain('home-component-3');
});
});
Yet whenever I try to run the tests I get the error described above. What really bothers me is that the browser freezes before the window says 'browser executing.' Any help would be really appreciated, I really want to write some unit tests for my code!
Add these files to the karma.files array:
'public/bower_components/jquery/dist/jquery.js',
'public/bower_components/angular-mocks/angular-mocks.js',
'public/bower_components/angular/angular.js'

Resources