Gulp: target to debug mocha tests - javascript

I have a set of gulp.js targets for running my mocha tests that work like a charm running through gulp-mocha. Question: how do I debug my mocha tests running through gulp? I would like to use something like node-inspector to set break points in my src and test files to see what's going on. I am already able to accomplish this by calling node directly:
node --debug-brk node_modules/gulp/bin/gulp.js test
But I'd prefer a gulp target that wraps this for me, e.g.:
gulp.task('test-debug', 'Run unit tests in debug mode', function (cb) {
// todo?
});
Ideas? I want to avoid a bash script or some other separate file since I'm trying to create a reusable gulpfile with targets that are usable by someone who doesn't know gulp.
Here is my current gulpfile.js
// gulpfile.js
var gulp = require('gulp'),
mocha = require('gulp-mocha'),
gutil = require('gulp-util'),
help = require('gulp-help');
help(gulp); // add help messages to targets
var exitCode = 0;
// kill process on failure
process.on('exit', function () {
process.nextTick(function () {
var msg = "gulp '" + gulp.seq + "' failed";
console.log(gutil.colors.red(msg));
process.exit(exitCode);
});
});
function testErrorHandler(err) {
gutil.beep();
gutil.log(err.message);
exitCode = 1;
}
gulp.task('test', 'Run unit tests and exit on failure', function () {
return gulp.src('./lib/*/test/**/*.js')
.pipe(mocha({
reporter: 'dot'
}))
.on('error', function (err) {
testErrorHandler(err);
process.emit('exit');
});
});
gulp.task('test-watch', 'Run unit tests', function (cb) {
return gulp.src('./lib/*/test/**/*.js')
.pipe(mocha({
reporter: 'min',
G: true
}))
.on('error', testErrorHandler);
});
gulp.task('watch', 'Watch files and run tests on change', function () {
gulp.watch('./lib/**/*.js', ['test-watch']);
});

With some guidance from #BrianGlaz I came up with the following task. Ends up being rather simple. Plus it pipes all output to the parent's stdout so I don't have to handle stdout.on manually:
// Run all unit tests in debug mode
gulp.task('test-debug', function () {
var spawn = require('child_process').spawn;
spawn('node', [
'--debug-brk',
path.join(__dirname, 'node_modules/gulp/bin/gulp.js'),
'test'
], { stdio: 'inherit' });
});

You can use Node's Child Process class to run command line commands from within a node app. In your case I would recommend childprocess.spawn(). It acts as an event emitter so you can subscribe to data to retrieve output from stdout. In terms of using this from within gulp, some work would probably need to be done to return a stream that could be piped to another gulp task.

Related

How to run function before run task in gulp?

guys how to run another function in task before run main task? AS u can see in function have stream, and i know about syntax (gulp.task('task', ['tast'], func... ) But i dont want to see 999 tasks in list, thats why im trying to use functions for tasks
function cssBuild() {
var dt = gulp
.src('app/html-dev/styl/framework/style.styl')
.pipe(plumber({ errorHandler: onError }))
.pipe(stylus({ use: nib(), 'include css': true, import: ['nib'], compress: false }))
.pipe(gulp.dest('app/cache/css'))
.pipe(browserSync.stream());
return dt;
}
function htmlBuild() {
var dt = gulp
.src('app/html-dev/**/*.pug')
.pipe(plumber({ errorHandler: onError }))
.pipe(pug({
pretty: true
}))
.pipe(gulp.dest('app/cache'))
.pipe(browserSync.stream());
return dt;
}
gulp.task('build', function() {
var removeDist = del.sync('app/dist');
cssBuild();
htmlBuild();
jsBuild();
return merge (
gulp
.src('app/cache/css/*.css')
.pipe(cssnano())
.pipe(gulp.dest('app/dist/css')),
gulp
.src(['app/html-dev/img/**/*', '!app/html-dev/img/empty.jpg'])
.pipe(gulp.dest('app/dist/img')),
gulp
.src(["app/html-dev/fonts/**/*", '!app/html-dev/fonts/empty.woff'])
.pipe(gulp.dest('app/dist/fonts')),
gulp
.src("app/cache/js/**/*")
.pipe(gulp.dest('app/dist/js')),
gulp
.src("app/cache/*.html")
.pipe(gulp.dest('app/dist'))
);
});
The problem you are probably running into is that the tasks aren't necessarily synchronous, so you need to treat them appropriately (i.e., wait for them to complete).
It's probably better to use gulp as it is intended and to have several separate tasks (or ditch gulp entirely and just script something normally). Trying to half use gulp is only going to cause you headaches.
If you are worried about having one massive gulp task list, what you can do instead is group tasks together and then call them.
For example:
gulp.task('html', () => { /* do something */ });
gulp.task('css', () => { /* do something */ });
gulp.task('js', () => { /* do something */ });
gulp.task('clean', () => { /* do something */ });
// Group the build ones into one call
gulp.task('build', ['html', 'css', 'js']);
// Group the default into one
gulp.task('default', ['clean', 'build']);
By grouping them together, you can keep them nice and organized without having to have 100 things in one task. This also lets the benefits of gulp show.

Gulp task for ng-constant multiple environments

I have been trying to get this to work maybe I'm missing something. I am using ng-constant and setting up different environments end point as mentioned in the ng-constants issue
However I am using gulp and the configuration looks like
gulp.task('environmentsapi', function () {
return ngConstant({
stream: true,
development: {
constants: {
"ENV": {"api": "http://1.1.1.1:8082/"}
}
},
production: {
constants: {
"ENV": {"api": "https://productionapplink/"}
}
}
})
// Writes config.js to dist/ folder
.pipe(gulp.dest('dist/scripts/config'));
});
I cant figure out how to call the different end points in the different gulp tasks like the example in the link ngconstant:development etc. How can i run this within the task environmentsapi, since this task is shared in all environment builds. Please let me know how to do this.
gulp.task('build', function () {
runSequence('clean', ['sass', 'scripts', 'bower_components', 'environmentsapi' //How can I run ngconstant:development here? ], 'wiredep')
});
Simply create new tasks that set flags!
Here I'm using the development flag that defaults to true.
var development = true;
gulp.task('prod', function () {
development = false;
});
gulp.task('environmentsapi', function () {
const apiEndpoint = development ? 'http://1.1.1.1:8082/' : 'https://productionapplink/';
return ngConstant({
stream: true,
constants: {
'ENV': {api: apiEndpoint}
}
});
});
Now, using gulp build will build your application with the ENV.api set to 'http://1.1.1.1:8082/', your development endpoint.
And calling gulp prod build will make your output use an ENV.api set to 'https://productionapplink/'.
As discussed in the comments section, the solution above is quite perfect when you only have two environments, but it quickly gets out of hand when the number of environment grows.
In that case, I suggest using a different approach, the Pirate way, using yargs.
Here would be your new gulpfile.js:
const argv = require('yargs').argv;
const endpoints = {
'dev': 'http://1.1.1.1:8082/',
'prod-org': 'https://productionapplink.org/',
'prod-com': 'https://productionapplink.com/',
'prod-gov': 'https://productionapplink.gov/'
};
gulp.task('enviornmentsapi', function () {
const apiEnpdoint = typeof argv.env === 'undefined' ? endpoints.dev : endpoints[argv.env];
return ngConstant({
stream: true,
constants: {
ENV: { api: apiEnpdoint }
}
}).pipe(gulp.dest('dist/scripts/config'));
});
Use it like follows:
gulp build uses the default api URL: 'http://1.1.1.1:8082/'
gulp build --env=prod-org uses 'https://productionapplink.org/'
gulp build --env=prod-com uses 'https://productionapplink.com/'
I hope this could work for you this time!

Gulp doesnt watch for any SCSS changes. Do I have to use gulp-ruby-sass? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have gulp file set up to watch for changes. I'm developing an application in ReactJS using Redux architecture. What I've noticed is that the gulp does not watch for any changes in the SCSS files.
/*eslint-disable */
var path = require('path');
var runSequence = require('run-sequence');
var install = require('gulp-install');
var spawn = require('child_process').spawn;
var $ = require('gulp-load-plugins')({
pattern: [
'gulp',
'gulp-*',
'gulp.*',
'merge-stream',
'del',
'browserify',
'watchify',
'vinyl-source-stream',
'vinyl-transform',
'vinyl-buffer',
'glob',
'lodash',
'less-plugin-*',
'mochify'
],
replaceString: /^gulp(-|\.)/,
rename: {
'merge-stream': 'mergeStream',
'del': 'delete'
}
});
var env = require('env-manager')({
argv: process.argv,
dir: path.join(__dirname, 'environments'),
base: 'base.js',
pattern: '{env}.js',
defaults: {
'env': 'development'
}
});
$.util.log($.util.colors.magenta('Running in ' + env.name + ' environment'));
require('gulp-tasks-registrator')({
gulp: $.gulp,
dir: path.join(__dirname, 'tasks'),
args: [$, env],
verbose: true,
panic: true,
group: true
});
$.gulp.task('clean', ['clean:server', 'clean:client'], function task(done) {
done();
});
$.gulp.task('install', function () {
return $.gulp.src([ './package.json']).pipe(install());
});
$.gulp.task('build', function task(done) {
return runSequence(
//'lint',
// 'install',
'clean',
'build:server',
'build:client:images',
'build:client:fonts',
[
'build:client:scripts',
'build:client:styles'
],
'build:client:html',
done
);
});
$.gulp.task('run-wrapper', function(done) {
var server = spawn('node', ['serviceWrapper.js'], {stdio: ['inherit']});
server.stderr.on('data', function(data){
process.stderr.write(data);
});
server.stdout.on('data', function(data) {
process.stdout.write(data);
});
server.unref();
});
$.gulp.task('default', function task(done) {
runSequence('build', ['serve', 'run-wrapper','watch'], done);
});
$.gulp.task('run', function task(done) {
runSequence('serve', done);
});
/*eslint-enable */
In what you've provided, there's no watch task or Sass task (though you do call a task named watch so if running gulp (the default task) isn't giving you an error you must have defined the task named watch somewhere).
There are two Sass plugins for gulp, one using Ruby Sass (gulp-ruby-sass) and one using LibSass (gulp-sass). You can read about the difference here, but in short gulp-sass will probably be faste. The best way to find out is to try one and then the other and compare gulp's console logs (where it says "finished task after x ms").
Here's a SASS-watching example, edited very slightly from the example in the gulp-sass readme (assumes that gulp-sass is in your package.json, in which case it will have been imported by your gulp-load-plugins call). $.s added to match the code you provided
$.gulp.task('sass', function () {
return gulp.src('yourstylespath/*.scss') // grab the .scss files
.pipe(sass().on('error', sass.logError)) // compile them into css, loggin any errors
.pipe(gulp.dest('yourcompiledcsspath')); // save them in yourcompiledcsspath
});
$.gulp.task('sass:watch', function () {
gulp.watch('yourstylespath/*.scss', ['sass']); // "run the task 'sass' when there's a change to any .scss file in yourstylespath
});
Side notes:
Considering all the packages you're using that don't follow the "gulp-packagename" naming scheme, it might be more efficient to just write them out individually like this (of course depends on how many packages you're using)
var delete = require('del'),
mergeStream = require('merge-stream'),
...;
Looks like your run task could just be this? $.gulp.task('run', ['serve']);

How to tell gulp.watch to wait until necessary tasks will not be finished before running new cycle?

I have an issue with gulp.watch.
TLDR:
How to tell gulp.watch to wait until necessary tasks will not be finished before running new cycle?
Reasons:
I have three tasks: clean, build, and watch.
Task clean deletes directory, task build produces files in the same directory (clean is dependency for build).
Task watch runs gulp.watch on directory and then it runs build (that runs clean).
But sometimes watch task runs new build before previous build is finished and an error occurs: build continues write to directory and clean tries to remove directory (of course, ENOTEMPTY error happens).
This issue happens when I run gulp watch command.
My Gulpfile.js:
var gulp = require('gulp');
var ts = require('gulp-typescript');
var tslint = require('gulp-tslint');
var rename = require('gulp-rename');
var del = require('del');
var tsProject = ts.createProject('tsconfig.json');
var tsSources = ['app/**/*.ts', 'app/**/*.tsx'];
gulp.task('clean', function() {
return del(['built']);
});
gulp.task('build', ['clean'], function() {
return gulp.src(tsSources)
.pipe(ts(tsProject)).js
.pipe(rename({extname: '.js'}))
.pipe(gulp.dest('built'));
});
gulp.task('tslint', ['clean'], function() {
return gulp.src(tsSources)
.pipe(tslint())
.pipe(tslint.report('msbuild', {
emitError: false,
summarizeFailureOutput: false
}));
});
gulp.task('watch', ['build', 'tslint'], function() {
return gulp.watch(tsProject.config.filesGlob, ['build', 'tslint']);
});
gulp.task('default', ['build', 'tslint']);
For cleaning the gulp use following code:-
gulp.task('clean', function() {
del.sync([
path.join(__dirname, builtPath, '**/*.js'),
], {
force: true
});
});

gulp.watch() not running subsequent task

Running into a bizarre bug when trying to make modular gulp tasks by splitting them into separate files. The following should execute the task css, but does not:
File: watch.js
var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
gulp.task('watch', function () {
plugins.watch('assets/styl/**/*.styl', ['css']); // PROBLEM
});
Declaring ['css'] in plugins.watch() should technically run the following task next:
File: css.js
var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
gulp.task('css', function () {
return gulp.src('assets/styl/*.styl')
.pipe(plugins.stylus())
.pipe(gulp.dest('/assets/css'));
});
File: gulpfile.js
var gulp = require('gulp');
var requireDir = require('require-dir');
requireDir('./gulp/tasks', { recurse: true });
gulp.task('develop', ['css', 'watch']);
Folder structure
- gulp/
- tasks/
- css.js
- watch.js
- gulpfile.js
Expected behavior
gulp develop should run tasks css and watch (it does). On file changes, watch should detect them (it does) and then run the css task (it's does not).
One solution
Not terribly fond of this solution as gulp.start() is being deprecated in the next release, but this does fix it:
File: watch.js
plugins.watch('assets/styl/**/*.styl', function() {
gulp.start('css');
});
Either use gulp's builtin watch with this syntax:
gulp.task('watch', function () {
gulp.watch('assets/styl/**/*.styl', ['css']);
});
Or gulp-watch plugin with this syntax:
gulp.task('watch', function () {
plugins.watch('assets/styl/**/*.styl', function (files, cb) {
gulp.start('css', cb);
});
});
There's also probably a typo in your gulp.dest path. Change it to relative:
.pipe(gulp.dest('assets/css'));
I am using Gulp 4, where gulp.start() is deprecated
So here's the solution
gulp.task('watch', gulp.series('some-task-name', function () {
browserSync.init({
server: {
baseDir: config.distFolder + ''
}
});
var watcher = gulp.watch([
'./src/views/*.html',
'./src/index.html',
'./src/assets/css/*.css',
'./src/**/*.js'],
gulp.series('some-task-name'));
watcher.on('change', async function (path, stats) {
console.log('you changed the code');
browserSync.notify("Compiling, please wait!");
browserSync.reload();
})
}));
Now, whenever there is a change in my code, my "some-task-name" gets executed and then the browser page is reloaded. I don't need to delay my browser-sync at all.

Categories

Resources