Grunt registerTask() Not Running Tasks in List - javascript

I have added the following registerTask calls to this Gruntfile.js
grunt.task.registerTask('runDebug', 'Run the app with debug flag', function() {
var done = this.async();
grunt.util.spawn({
cmd: 'node',
args: ['--debug', './node_modules/nodemon/nodemon.js', 'index.js'],
opts: {
stdio: 'inherit'
}
}, function (error, result, code) {
if (error) {
grunt.log.write (result);
grunt.fail.fatal(error);
}
done();
});
grunt.log.writeln ('node started');
grunt.util.spawn({
cmd: 'node-inspector',
args: ['&'],
opts: {
//cwd: current working directory
}
},
function (error, result, code) {
if (error) {
grunt.log.write (result);
grunt.fail.fatal(error);
}
done();
});
grunt.log.writeln ('inspector started');
});
grunt.task.registerTask('debug', ['runDebug', 'compile', 'watch']);
The new debug task is similar to the existing server task. However, grunt server command runs compile, watch, and runNode tasks, whereas grunt debug command only runs runDebug task.
What am I missing here? Why aren't the compile and watch tasks run with grunt debug command.

Your code is calling the done() function returned by this.async() more than once. This could be confusing Grunt. I would suggest calling a function of your own which could named spawned() instead of calling done() directly in your callbacks. The function could be something like:
var expected_spawns = 2;
function spawned() {
if (!--expected_spawns)
done();
if (expected_spawns < 0)
throw new Error("too many spawns!") // Or some of Grunt's fail functions.
}
This way done() will be called once.

Related

Gulp 4 Default Task with Series and Parallel

I've looked at many different posts here on SO using Gulp
CLI version: 2.3.0
Local version: 4.0.2
and have tried multiple approaches to the gulp 4 default task declaration:
exports.default = gulp.series(clean, (done) => {
gulp.parallel(styles, scripts);
done();
});
gulp.task('default',
gulp.series(clean, (done) => {
gulp.parallel(scripts, styles);
done();
});
);
function production () {
return gulp.series(clean, function (done) {
gulp.parallel(styles, scripts);
done();
})
}
exports.default = production
Clean function is simple:
function clean(cb) {
console.log("clean");
del(["dist"]);
cb();
}
For testing I have created a test function:
function test() {
console.log("in test");
return (
gulp.src(paths.styles.src)
.pipe(notify("Styles rendered"))
);
}
exports.test = test;
And a test default function:
exports.default = gulp.series(clean, (done) => {
console.log("before styles and scripts");
gulp.parallel(test);
console.log("after styles and scripts");
done();
});
Printed to the terminal are:
"clean"
"before styles and scripts"
"after styles and scripts"
But no "in test".
What am I missing here?
Not sure if this is the way Gulp is designed, but based on this answer, the code that works for me is:
exports.default = gulp.series(clean, (callbackA) => {
return gulp.parallel(styles, scripts, (callbackB) =>
{
callbackA();
callbackB();
})();
});
And the three tasks i'm calling are:
function clean(cb) {
del(["dist"]);
cb();
}
// Define tasks after requiring dependencies
function styles() {
console.log("in styles");
return (
gulp.src(paths.styles.src)
.pipe(sass())
.on("error", sass.logError)
.pipe(sourcemaps.init())
.pipe(sass())
.on("error", sass.logError)
.pipe(postcss([autoprefixer(), cssnano()]))
.pipe(sourcemaps.write())
.pipe(gulp.dest(paths.styles.dest))
// Add browsersync stream pipe after compilation
.pipe(browserSync.stream())
);
}
// Expose the task by exporting it
// This allows you to run it from the commandline using
// $ gulp style
exports.styles = styles;
function scripts() {
// Start by calling browserify with our entry pointing to our main javascript file
return ( gulp.src(paths.scripts.src)
.pipe(babel())
.pipe(uglify())
// Then write the resulting files to a folder
.pipe(gulp.dest(paths.scripts.dest))
);
}
// Expose the task, this allows us to call this task
// by running `$ gulp build' in the terminal
exports.scripts = scripts;
Aside from Gulp docs and here, this was a nice source.

Gulp pipe creating files and using those files

I'm playing with gulp and I stumbled on this issue that I can't really understand.
I have some tasks:
gulp.task('concat-js', (done) => {
gulp.src('src/app/**/*.js')
.pipe(concat('app-script.js'))
.pipe(gulp.dest('src/app/dist/'));
done();
});
gulp.task('minify-js', (done) => {
gulp.src('src/app/dist/*.js')
.pipe(minify({noSource: true, ignoreFiles: ['*-min.js']}))
.pipe(gulp.dest('src/app/dist/'));
done();
});
gulp.task('compress',
gulp.series('concat-js', 'minify-js', function(done) {
// default task code here
done();
})
);
gulp.task(
'run',
gulp.series('compress', () => {
...
}
));
My goal is that when run is executed, I get concatenated of my source files and then minifed version of that file. But I'm running in some kind of problem with executing those tasks in series.
When I execute run for the first time, application doesn't run and only app-script.js gets created. Running it for the second time creates app-script-min.js file.
As far as I understand minify-js doesn't wait for concat-js to finish creating file.
I think this might be because done() is called before gulp is completed. Try change
gulp.task('concat-js', (done) => {
gulp.src('src/app/**/*.js')
.pipe(concat('app-script.js'))
.pipe(gulp.dest('src/app/dist/'));
done();
});
to
gulp.task('concat-js', (done) => {
gulp.src('src/app/**/*.js')
.pipe(concat('app-script.js'))
.pipe(gulp.dest('src/app/dist/'))
.on('finish', function() {
done();
});
});
I also found this resource which might be interesting for you. http://www.ericcredeur.com/gulp/javascript/2015/07/15/cascading-gulp-tasks.html

Gulp Watch produces memory leak

I am having an issue where after several restarts triggered by gulp watch, I get a warning that states I may have a memory leak. I assume it's because I am starting a new instance of gulp watch with every restart, triggering a new server and another new watch, over and over. I am not sure that's the case and not sure how to fix it if it is.
Here is my gulpfile.js.
const gulp = require('gulp');
const exec = require('child_process').exec;
const gutil = require('gulp-util');
const eslint = require('gulp-eslint');
gulp.task('dev', (() => {
gulp.start('test');
gulp.start('lint');
gulp.start('server');
gulp.start('watch');
return gutil.log('Gulp is running!');
}));
gulp.task('server', (cb) => {
exec('npm start', (err, stdout, stderr) => {
gutil.log(stdout);
gutil.log(stderr);
cb(err);
});
});
gulp.task('test', (cb) => {
exec('npm test', (err, stdout, stderr) => {
gutil.log(stdout);
gutil.log(stderr);
cb(err);
});
});
gulp.task('watch', () => {
gulp.watch(['./app.js', './views/*', './routes/*'], ['dev']);
});
gulp.task('lint', () => {
return gulp.src(['**/*.js', '!node_modules/**'])
.pipe(eslint())
.pipe(eslint.format());
});
And my error is:
(node:808) Warning: Possible EventEmitter memory leak detected. 11 change listeners added. Use emitter.setMaxListeners() to increase limit
Your gulp.watch calls the task dev which in turn creates another gulp.watch. My money is on that.
As another user noted, you're calling gulp dev in gulp watch basically creating an inifinity loop, which would cause that.
To add, I would encourage using a default task:
gulp.task('default', ['dev', 'test', 'lint', 'watch', 'server']);

How to replace deprecated gulp-karma with new version of karma?

Currently I am using gulp-karma for unit-testing in JS, but the current version is deprecated.
How can I replace this code so I can use the new version recommended?
Old version:
var karma = require('gulp-karma');
var testFiles = [
'client/todo.js',
'client/todo.util.js',
];
gulp.task('test', function() {
// Be sure to return the stream
return gulp.src(testFiles)
.pipe(karma({
configFile: 'karma.conf.js',
action: 'run'
}))
.on('error', function(err) {
// Make sure failed tests cause gulp to exit non-zero
throw err;
});
});
New recommended version (but not using pipes):
var gulp = require('gulp');
var karma = require('karma').server;
gulp.task('tests', function(done) {
return karma.start({
configFile: __dirname + '/test/karma.conf.js',
singleRun: true
}, done);
});
I specify I need to use pipes, but I always get some errors.
I've done a quick research, so I'm not 100% sure that this is going to work, but Id give it a try.
Requirements
* Promises support (native or via a third party library)
* stream-from-promise => npm install stream-from-promise --save-dev
First wrap your karma server into a promise (some third party libraries also offer a safer promisify fn for this):
function startKarma(){
return new Promise( function(resolve, reject){
karma.start({
configFile: __dirname + '/test/karma.conf.js',
singleRun: true
}, function(error){
return error ? reject(error) : resolve();
});
}
Now create a function to create a stream out of a promise:
var StreamFromPromise = require("stream-from-promise");
function makeStream( promise ){
return StreamFromPromise.obj( promise );
});
And now let's write your task:
gulp.task('tests', function() {
return gulp.src(testFiles)
.pipe( makeStream( startKarma() ))
.on('error', function(err) {
// Make sure failed tests cause gulp to exit non-zero
throw err;
});
});
var gulp = require('gulp');
var karma = require('karma').server;
var testFiles = [
'client/todo.js',
'client/todo.util.js',
];
gulp.task('tests', function(done) {
return karma.start({
configFile: __dirname + '/test/karma.conf.js',
singleRun: true,
files: testFiles
}, done);
});

Callbacks in Laika tests are not called

Meteor.collection.insert() accepts callback as an argument. As an example, one can create a brand new Meteor project and run the following code in the browser's console.
my_collection = new Meteor.Collection("myCollection");
my_collection.insert(
{some: "object"},
function() {
console.log("finished insertion");
})
When I take this same code and put it in a Laika test, the callback argument never gets called. Here is my test code:
suite('testing Laika out', function() {
test('inserting into collection', function(done, server, client) {
client.eval(function() {
my_collection = new Meteor.Collection("myCollection");
my_collection.insert(
{some: "object"},
function() {
console.log("finished insertion");
done();
})
})
})
})
Anyone know why the callback function isn't called in this Laika test? This seems to be an issue for more than just Meteor.collection.insert().
(I'm running Ubuntu 13.04, Meteor 0.7.0.1, Laika 0.3.1, PhantomJS 1.9.2-6)
The problem is that you're trying to call done(); inside of your insert callback, when it doesn't exist in that function scope. You actually need to listen for the insertion into my_collection and emit a signal which is picked up by either the client or server (the client in your case). Also, you obviously won't be initializing your collection in your test; that should be done in your production code.
Try this instead:
var assert = require("assert");
suite('testing Laika out', function() {
test('inserting into collection', function(done, server, client) {
client.eval(function() {
addedNew = function(newItem) {
console.log("finished insertion");
emit("done", newItem)
};
my_collection = new Meteor.Collection("myCollection");
my_collection.find().observe({
added: addedNew
});
my_collection.insert(
{some: "object"}
)
}).once("done", function(item) {
assert.equal(item.some, "object");
done();
});
});
})
Check out https://github.com/arunoda/hello-laika for the basic examples for testing.
Well, Mr. jonS90, if you were to run Laika with the --verbose flag, you would notice that an exception is quietly being thrown:
[client log] Exception in delivering result of invoking '/myCollection/insert': ReferenceError: Can't find variable: done
You see, you don't have access to done() in that context. Here's how you should revise your code:
test('inserting into collection', function(done, server, client) {
client.eval(function() {
my_collection = new Meteor.Collection("myCollection");
finishedInsertion = function () {
console.log("finished insertion");
emit('done')
}
my_collection.insert(
{some: "object"},
finishedInsertion)
})
client.once('done', function() {
done();
})
})

Categories