8

While executing gulp test-browser command, I got following warning message

WARN [reporter]: Can not load "mocha", it is not registered!
Perhaps you are missing some plugin?

but if i execute karma start command its working fine and it not shows any warning message.

Why do I get this warning message?
What am I missing here?

package.json

{
'''
 "dependencies": {
    "browser-sync": "^2.9.12",
    "gulp": "^3.9.0",
    "karma": "^0.13.15",   
    "karma-mocha": "^0.2.0",
    "mocha": "^2.3.3"
  },
  "devDependencies": {
    "karma-phantomjs-launcher": "^0.2.1",
    "phantomjs": "^1.9.18"
  }
}

gulpfile.js

gulp.task('test-browser', function () {
var config = {
    configFile: __dirname + '/karma.conf.js',
    singleRun: true,
    reporters: ['mocha']
};
var server = new Server(config);
server.start();
});

karma.conf.js

module.exports = function (config) {
config.set({
    browsers: ['PhantomJS'],        
    frameworks: ['mocha'],
    files: [
        "bower_components/angular/angular.js",
        "bower_components/chai/chai.js",
        "app/**/*.js",
        "test/*.spec.js"
        ]
    });
};
codeninja.sj
  • 3,452
  • 1
  • 20
  • 37

2 Answers2

16

The problem here is that you dont have karma-mocha-reporter installed or added in your karma.conf.js plugins.

If you dont have it installed.

npm install karma-mocha-reporter --save-dev

And add it to your karma.conf.js plugins.

module.exports = function(config){
config.set({
    plugins:['karma-mocha','karma-phantomjs-launcher','karma-mocha-reporter'],
    browsers:['PhantomJS'],
    frameworks:['mocha'],
    files:[
        "bower_components/angular/angular.js",
        "bower_components/angular-mocks/angular-mocks.js",
        "bower_components/chai/chai.js",

        "app/**/*.js",

        "test/*.js"
    ],
    colors: true,
})
}

It should resolve the warning and get it working.

Jun Bryl
  • 316
  • 2
  • 8
2

The only difference I have is I do not have mocha as a reporter, and I do have chai in the frameworks in karma.conf.js

gulpfile.js (note: My watch is for code changes, I build and test before deploy, so this does not autorun).

gulp.task('Tests', function(done) {
    karma.start({
        configFile: __dirname + '/karma.conf.js',
        coverageReporter: {
            type : 'html',
            dir: RootDir.docs + DocumentationPath.CodeCoverage,
        },
        singleRun: true
    }, function() {
        done();
    });

karma.conf.js

module.exports = function(config) {

    var SourceCode = [
        'app/app.js',
        ...
    ];

    var Libraries = [
        'app/bower_components/angular/angular.js',
        ...
    ];

    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: ['mocha', 'chai'],

        // list of files / patterns to load in the browser
        files: Libraries.concat(SourceCode),


        // 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/**/*.js': ['coverage']
        },

        // test results reporter to use available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress', 'coverage'],    

        coverageReporter: {
            type : 'html',
            dir : 'docs/coverage/'
        },

        logLevel: 'LOG_DEBUG',

        // 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: false,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['PhantomJS'],    // 'Chrome', 

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true
    })
}

My complete gulpfile.js. This has been modified against various projects, and not everything is used. It also uses the source code structure that we follow. This tool monitors and prepares our release directory on the developer machine at the same time as the local copy of data.

var gulp = require('gulp');
var AppSync = require('browser-sync').create();
var mainBowerFiles = require('main-bower-files');
var concat = require('gulp-concat');
var del = require('del');
var fs = require('fs');
var GoogleCDN = require('gulp-google-cdn');
var Graph = require('gulp-angular-architecture-graph');
var csslint = require('gulp-csslint');
var header = require('gulp-header');
var hhint = require('gulp-htmlhint');
var hlint = require('gulp-htmllint');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var istanbul = require('gulp-istanbul');
var jscs = require('gulp-jscs');
var stylish = require('gulp-jscs-stylish');
var jshint = require('gulp-jshint');
var jsonlint = require('gulp-jsonlint');
var karma = require('karma').Server;
var mocha = require('gulp-mocha');
var minifyCss = require("gulp-minify-css");
var minifyHtml = require("gulp-minify-html");
var notify = require("gulp-notify");
var plumber = require('gulp-plumber');
var run = require('gulp-run');
var size = require('gulp-size');
var sourcemaps = require('gulp-sourcemaps');
var stripdebug = require('gulp-strip-debug');
var uglify = require('gulp-uglify');
var util = require('gulp-util');
var watch = require('gulp-watch');

// Get Information using NodeJs file system from files for the Application
var getApplicationName  = function()    { return ReadLocalFile( RootDir.config + 'Application', __dirname); };
var getBuildGraphic     = function()    { return ReadLocalFile( RootDir.config + 'BuildGraphic', ''); };
var getCopyright        = function()    { return ReadLocalFile( RootDir.config + 'Copyright', 'Copyright (c) 2015 - Steven Scott'); };
var getVersion          = function()    { return ReadLocalFile( RootDir.config + 'Version', '0.0.1'); };

var getAppInfo = function() {
    var Text = [
        "/**",
        " * " + getApplicationName(),
        " * Version: " + getVersion(),
        " * " + getCopyright(),
        " */",
        ""
    ];
    return Text.join('\n');
};

var getBuildInfo = function() {
    var Text = [
        '',
        util.colors.yellow.bold(getBuildGraphic()),
        getApplicationName(),
        getCopyright(),
        'Build (' + util.colors.green(getVersion()) + ')',
        '',
    ];
    return Text.join('\n');
}

var NoOp = function() { };
var OnErrorHandler = function(err) {
    util.log(util.colors.white.bold(err + '!'));
    this.emit('end');
};

var Paths = {
    CDN: 'CDN',
    Images: 'images/',
    JavaScript: 'js/',
    JSON: 'data/',
    Libraries: 'ExternalLibraries/',
    Modules: 'Modules/',
    Styles: 'css/'
};  

var RootDir = { config: './', dist: 'dist/', docs: 'docs/', home: 'app/' };
var DocumentationPath = { API: 'API.v' + getVersion() + '/', CodeCoverage: 'Coverage/', Graphs: 'Diagrams.v' + getVersion() + '/' };

var SourcePath = {
    BowerComponents: ['bower_components/**'],
    ExtraFiles: ['favicon.ico'],
    ExtraStyleFiles: ['ExternalLibraries/ui.Grid/*.woff','ExternalLibraries/ui.Grid/*.ttf', 'ExternalLibraries/ui.Grid/*.svg'],
    HTML: ['*.html'],
    HTMLPages: ['Modules/**/*.html'],
    Images: ['graphics/**/*.gif','graphics/**/*.jpg','graphics/**/*.png',
        'Modules/**/*.gif', 'Modules/**/*.jpg', 'Modules/**/*.png'
    ],
    JSON: ['Modules/**/*.json'],

    Libraries: ['bower_components/angular-order-object-by/src/ng-order-object-by.js'],
    LibStyles: [],

    SourceCode: ['Modules/**/*.js'],
    Styles: ['Modules/**/*.css'],
    TestFiles: ['UnitTests/**/*.test.js'],
};

var ApplicationName = getApplicationName();
var BuildLogo = getBuildInfo();
var SourceCopyright = getAppInfo();

// ================ Gulp Tasks ================
// Package Bower Files into 1 Library
gulp.task('BowerFiles', function() {
    del([ RootDir.home + Paths.CDN + "*.js", RootDir.dist + Paths.CDN + "*.js" ]);
    // mainBowerFiles is used as a src for the task, usually you pipe stuff through a task
    return gulp.src(mainBowerFiles(), {cwd: RootDir.home})
        // Then pipe it to wanted directory
        .pipe(gulp.dest(RootDir.home + Paths.CDN))
        .pipe(gulp.dest(RootDir.dist + Paths.CDN))
});

// Convert Bower local files to CDN
gulp.task('BowerToCDN', ['BowerFiles'], function() {
    var CDNOptions = {
    };
    return gulp.src('index.html', {cwd: RootDir.home})
        .pipe(GoogleCDN(require(RootDir.config + 'bower.json'), CDNOptions))
        .pipe(gulp.dest(RootDir.dist));
});

// Remove Temporary files (bak, log, etc...)
gulp.task('DeleteBackupFiles', function(callback) {
    return del([ 
            RootDir.config + '**/*.bak',
            RootDir.config + 'lcov.info',
            RootDir.config + '*.log'
        ], callback)
    ;
});

// Document the API
gulp.task('Document-API', function() {
    var reportOptions = {
        err:    true,   // default = true, false means don't write err 
        stderr: true,   // default = true, false means don't write stderr 
        stdout: true    // default = true, false means don't write stdout 
    };

    del([ RootDir.docs + DocumentationPath.JavaScript ]);

    return run('node_modules\\.bin\\jsdoc' + 
                ' -c node_modules/angular-jsdoc/common/jsdoc.conf.json ' +   // config file
                ' -t node_modules/angular-jsdoc/default ' +    // template file
                ' -d ' + RootDir.docs + DocumentationPath.API +
                ' ./README.md ' +
                ' -r ' + RootDir.home + Paths.Modules
        ).exec();

});

// -=-=-=- Documentation - Do not wait to complete -=-=-=-
gulp.task('Documentation',['Document-API'], function() {
    del([ RootDir.docs + DocumentationPath.Graphs ]);

    return gulp.src(SourcePath.SourceCode, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(Graph({dest: RootDir.docs + DocumentationPath.Graphs})
    );
});

// -=-=-=- HTML Pages -=-=-=-   
gulp.task('HTMLPages', ['BowerToCDN'], function() {
    del([ RootDir.dist + "*.html" ]);
    gulp.src(SourcePath.HTML, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(hlint())
        //.pipe(hhint('htmlhint.json'))
            .pipe(hhint.reporter())         // FailReporter to fail build step
        .pipe(minifyHtml())
        .pipe(gulp.dest(RootDir.dist))
    ;

    del([ RootDir.dist + Paths.Modules + "**/*.html" ]);
    return gulp.src(SourcePath.HTMLPages, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(hlint())
        .pipe(hhint('htmlhint.json'))
            .pipe(hhint.reporter())         // FailReporter to fail build step
        .pipe(minifyHtml())
        .pipe(gulp.dest(RootDir.dist + Paths.Modules))
    ;
});

gulp.task('Images', function () {
    del([ RootDir.home + Paths.Images + "*.png" ]);
    del([ RootDir.dist + Paths.Images + "*.png" ]);
    return gulp.src(SourcePath.Images, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(imagemin( {
            progressive: true,
            svgoPlugins: [{removeViewBox: false}],
            use: [pngquant()]
        }))
        .pipe(gulp.dest(RootDir.home + Paths.Images))
        .pipe(gulp.dest(RootDir.dist + Paths.Images))
    ;
});

// -=-=-=- JSON Data -=-=-=-    
gulp.task('JSONChanges', function(callback) {
    del([ RootDir.dist + Paths.JSON]);
    return gulp.src(SourcePath.JSON, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(jsonlint())
        .pipe(jsonlint.reporter())
        .pipe(gulp.dest(RootDir.dist + Paths.JSON))
    ;
});

// -=-=-=- External Libraries -=-=-=-   
gulp.task('Libraries-CSS', function() {
    del([ RootDir.home + Paths.Libraries + 'ExternalLibraries.min.css' ]);
    return gulp.src(SourcePath.LibStyles, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
//      .pipe(minifyCss())
        .pipe(concat('ExternalLibraries.min.css'))
        .pipe(gulp.dest(RootDir.home + Paths.Libraries))
        .pipe(gulp.dest(RootDir.dist + Paths.Styles))
    ;
});

gulp.task('Libraries', ['Libraries-CSS', 'BowerToCDN'], function() {
    del([ RootDir.dist + Paths.JavaScript + 'ExternalLibraries.min.js' ]);
    return gulp.src(SourcePath.Libraries, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(concat('ExternalLibraries' + '.min.js'))
        .pipe(header(SourceCopyright))
        .pipe(size( { showFiles: false, gzip: true, title: 'Min ExternalLbraries' } ))
        .pipe(gulp.dest(RootDir.home + Paths.JavaScript))
        .pipe(gulp.dest(RootDir.dist + Paths.JavaScript))
    ;
});

// -=-=-=- Misc. File Moves -=-=-=-
gulp.task('OtherFileChanges', function() {
    gulp.src(SourcePath.ExtraFiles, {cwd: RootDir.home} )
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(gulp.dest(RootDir.dist))
    ;
    return gulp.src(SourcePath.ExtraStyleFiles, {cwd: RootDir.home} )
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(gulp.dest(RootDir.dist))
    ;
});

// -=-=-=- Source Code Processing -=-=-=-
gulp.task('SourceCode-CSS', function() {
    del([ RootDir.home + Paths.Styles + ApplicationName + ".min.css" ]);
    del([ RootDir.dist + Paths.Styles + ApplicationName + ".min.css" ]);

    return gulp.src(SourcePath.Styles, {cwd: RootDir.home})
        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(csslint('csslint.json'))
            .pipe(csslint.reporter())
        .pipe(concat(ApplicationName + '.min.css'))
        .pipe(gulp.dest(RootDir.home + Paths.Styles))
        .pipe(minifyCss())
        .pipe(gulp.dest(RootDir.dist + Paths.Styles));
    ;
});

// -=-=-=- Source Code Changed -=-=-=-
gulp.task('SourceCode', ['Documentation', 'JSONChanges', 'OtherFileChanges', 'SourceCodeTests'], function() {
    util.log(BuildLogo);

    del([ RootDir.home + Paths.JavaScript + ApplicationName + ".min.js" ]);
    del([ RootDir.dist + Paths.JavaScript + ApplicationName + ".min.js" ]);

    return gulp.src(SourcePath.SourceCode, {cwd: RootDir.home})
        .pipe(jshint())
            .pipe(jscs( 'jscs.json'))
            .on('error', NoOp)                              // Don't Stop on Errors
                .pipe(stylish.combineWithHintResults())     // combine with jshint results
                .pipe(jshint.reporter('jshint-stylish'))

        .pipe(plumber( { errorHandler: OnErrorHandler  } ))
        .pipe(concat(ApplicationName + '.min.js'))
        .pipe(header(SourceCopyright))
        .pipe(size({ showFiles: false, gzip: true, title: ApplicationName } ))
        .pipe(gulp.dest(RootDir.home + Paths.JavaScript) )

        .pipe(sourcemaps.init())
            .pipe(stripdebug())
            .pipe(uglify())

            .pipe(size({ showFiles: false, gzip: true, title: 'Min ' + ApplicationName } ))
        .pipe(sourcemaps.write())
        .pipe(gulp.dest(RootDir.dist + Paths.JavaScript) )
    ;
});

gulp.task('SourceCodeTests', function(done) {
    karma.start({
        configFile: __dirname + '/karma.conf.js',
        coverageReporter: {
            type : 'html',
            dir: RootDir.docs + DocumentationPath.CodeCoverage,
        },
        singleRun: true
    }, function() {
        done();
    });
});

// -=-=-=- Job Tasks -=-=-=-
// Browser Sync - Auto Reload/Refresh
gulp.task('BrowserSyncStartup', ['SourceCode', 'SourceCode-CSS', 'Libraries', 'HTMLPages'], function() {
    return AppSync.init({
        server: {
            baseDir: [RootDir.config], 
            index: 'index.html',
            directory: false,           // Set to True for Browsing Files, not launching index
            routes: {
                '/API': RootDir.docs + DocumentationPath.API,
                '/app': RootDir.home,
                '/Coverage': RootDir.docs + DocumentationPath.CodeCoverage + 'PhantomJS 1.9.8 (Windows 7 0.0.0)/'
            }
        },
        port: 3000,
        startPath: '/app'
    });
});

/* Watch Tasks */
gulp.task('WatchBowerFiles', ['BowerToCDN'], function() { });
gulp.task('WatchHTMLPages', ['HTMLPages'], function() { AppSync.reload(); });
gulp.task('WatchGraphics', ['Images'], function() { AppSync.reload(); });
gulp.task('WatchLibraries', ['Libraries'], function() { AppSync.reload(); });
gulp.task('WatchSourceCodeCSS', ['SourceCode-CSS'], function() { AppSync.reload(); });
gulp.task('WatchSourceCode', ['SourceCode', 'Documentation'], function() { AppSync.reload(); });
gulp.task('WatchSourceCodeTests', ['SourceCodeTests'], function() { AppSync.reload(); });

// A development task to run anytime a file changes
gulp.task('WatchSource', ['BrowserSyncStartup'], function() {
    gulp.watch([RootDir.home + SourcePath.HTML, RootDir.home + SourcePath.HTMLPages], ['WatchHTMLPages']);
    gulp.watch(RootDir.home + SourcePath.Images, ['WatchGraphics']);
    gulp.watch(RootDir.home + SourcePath.Libraries, ['WatchLibraries']);
    gulp.watch(RootDir.home + SourcePath.SourceCode, ['WatchSourceCode']);
    gulp.watch(RootDir.home + SourcePath.Styles, ['WatchSourceCodeCSS']);
    gulp.watch(RootDir.home + SourcePath.TestFiles, ['WatchSourceCodeTests']);
});

// The default task (called when you run `gulp` from cli) runs a sequence of the above tasks
gulp.task('default',['SourceCodeTests', 'WatchSource', 'DeleteBackupFiles']);

// Write a step of the build on the console
function ShowStepOnConsole(MsgText) {
    if(MsgText.length > 0)
    {
        var ConsoleMessage = [
            'Process',
            util.colors.magenta.bold(MsgText),
        ].join(' ');
        util.log(ConsoleMessage);
    }
}

// Return with a Syncronys Call the contents of a file
function ReadLocalFile( FileName, DefaultWhenNotFound)
{
    if ( fs.existsSync(FileName) )  {
            return fs.readFileSync(FileName);
    }
    else {
        return DefaultWhenNotFound;
    }
}
Steven Scott
  • 10,234
  • 9
  • 69
  • 117
  • Thanks for sharing your config files Steven. I don't get any warning message when I comment reporters section in karma config. But, I don't know, whats wrong in using mocha as a reporter! – codeninja.sj Nov 10 '15 at 18:30
  • Did it solve the problem? Maybe Mocha is not a valid reporter? Reporters tend to output the results colorfully, with dots, etc..., not Mocha's job, as it sets the status? – Steven Scott Nov 10 '15 at 22:56
  • I guess, we can use mocha for reporting purpose too; but I don't know how to configure it properly. Do you use any other reporting framework in your app? – codeninja.sj Nov 11 '15 at 10:10
  • 1
    At this point no, we just used the basic tools as listed, and AngularJS-Doc template for the API. Graphviz for the class relationships. We do use the JSHint stylish reported for jscs. – Steven Scott Nov 12 '15 at 15:55
  • Thanks for sharing the list of tools you used in your project. – codeninja.sj Nov 13 '15 at 13:56
  • Anything to try to help. I can post my gulpfile.js if you think it will help. – Steven Scott Nov 13 '15 at 14:30
  • I am a newbie in front-end technologies. I have recently started learning angularjs and it related BDD tools. At first, I would like to try myself if its not workout i will definitely ask your help and your gulpfile. Once again thanks for your helping mind :) – codeninja.sj Nov 13 '15 at 14:41
  • 1
    I am self taught recently as well. I use my gulp process different from others, where I have tasks for everything, but a source code change tends to get everything updated when saved. Test the code, document the code, build libraries, etc... – Steven Scott Nov 13 '15 at 14:52
  • It will definitely helps me as well as others if you post your full gulpfile.js – codeninja.sj Nov 13 '15 at 14:55
  • 1
    Hopefully the gulpfile.js will help solve your outstanding issues allowing you to accept the answer, even though it is done for how we work. Let me know if you have any questions on any part of it. – Steven Scott Nov 16 '15 at 16:00