Does anyone know the best solution for automatically restarting node and running tests after the restart every time a file changes?
I am currently using grunt-contrib-watch with grunt-develop. I am getting an ECONNREFUSED error on the some restarts. I think it is because my tests are running before the server is fully online.
Any ideas on how best to achieve what I want?
What I want: Restart node and then run all integration tests after each file change.
I am taking a BDD approach to testing (as opposed to regular unit tests) with cucumber.js. I wanted to make sure that each test run against the API I was building started on a fresh boot-up of the application.
I figured it out. Here is what I used:
grunt-contrib-watch to monitor for file changes.
It in turn calls
grunt-develop to restart the application
grunt-cucumberjs to run the cucumber tests
I then modified my index.js (starts the app) so that it doesn't start the app if the NODE_ENV is set to test. That way the cucumber tests actually start the server and can wait till the start process has finished before running the tests.
Here is the GruntFile and Index file:
Gruntfile.js
/*jslint node: true */
"use strict";
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
env: {
dev: {
APP_DIR_FOR_CODE_COVERAGE: 'coverage/instrument/',
NODE_ENV: 'dev',
PORT: 8080
},
test: {
APP_DIR_FOR_CODE_COVERAGE: 'coverage/instrument/',
NODE_ENV: 'test',
PORT: 8081
},
coverage: {
APP_DIR_FOR_CODE_COVERAGE: 'coverage/instrument/',
NODE_ENV: 'test',
PORT: 8081
}
},
watch: {
js: {
files: [
'index.js',
'features/**/*.js',
'server/**/*.js'
],
tasks: ['develop', 'cucumberjs', 'jshint'],
options: {
nospawn: true
}
}
},
jshint: {
all: ['Gruntfile.js', 'index.js', 'server/**/*.js', 'features/**/*.js']
},
nodemon: {
dev: {
script: 'index.js'
}
},
cucumberjs: {
src: './features',
},
develop: {
server: {
file: 'index.js'
}
},
instrument: {
files: ['index.js', 'server/**/*.*'],
options: {
lazy: true,
basePath: 'coverage/instrument/'
}
},
storeCoverage: {
options: {
dir: 'coverage'
}
},
makeReport: {
src: 'coverage/coverage.json',
options: {
type: 'lcov',
dir: 'coverage/reports',
print: 'detail'
}
},
coverage: {
options: {
thresholds: {
'statements': 90,
'branches': 90,
'lines': 90,
'functions': 90
},
dir: 'coverage',
root: ''
}
}
});
grunt.loadNpmTasks('grunt-env');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-develop');
grunt.loadNpmTasks('grunt-cucumber');
grunt.loadNpmTasks('grunt-istanbul');
grunt.loadNpmTasks('grunt-istanbul-coverage');
grunt.loadNpmTasks('grunt-nodemon');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['env:dev', 'nodemon']);
grunt.registerTask('test', ['env:test', 'watch']);
grunt.registerTask('testcoverage', ['env:test', 'jshint', 'instrument', 'cucumberjs', 'storeCoverage', 'makeReport', 'coverage']);
};
Index.js
/*jslint node: true */
"use strict";
var Hapi = require('hapi');
var Good = require('good');
var server = {};
exports.server = {
start: function(callback) {
/* istanbul ignore next */
var port = process.env.PORT || 8080;
server = new Hapi.Server(port);
var routes = require('./server/routes');
routes.register(server);
var exceptionHandling = require('./server/exceptionHandling');
exceptionHandling.register(server);
server.pack.register(Good, function(err) {
/* istanbul ignore if */
if (err) {
throw err; // something bad happened loading the plugin
}
/* istanbul ignore next */
server.log('info', 'Server starting at ' + server.info.uri);
server.start(callback);
});
},
stop: function(callback) {
server.log('info', 'Server stopping.');
server.stop(null, callback);
},
rootUrl: function() { return server.info.uri; }
};
/* istanbul ignore if */
if (process.env.NODE_ENV != 'test') {
exports.server.start(function() {});
}
Related
this is my gruntfile.
i run $ grunt default
actuall i want to up my index.html on some port and want it to open in chrom directly
module.exports = function(grunt) {
grunt.initConfig({
connect: {
server: {
options: {
port: 9001,
base: {
path: 'Dev',
options: {
index: 'index.html',
maxAge: 300000
}
}
}
}
},
open: {
delayed: {
path: 'http://localhost:9001'
app: 'Google Chrome'
options: {
openOn: 'serverListening'
}
}
}
});
grunt.registerTask('default', ['connect', 'open']);
};
You need to load the task:
grunt.loadNpmTasks('grunt-contrib-connect');
I have grunt-contrib-watch configured like this:
watch: {
tasks: ['copyFiles'],
js: {
files: [
path.join(__dirname, "../gscm-js/src/**/*.js"),
path.join(__dirname, "../gscm-js/templates/**/*.*")]
},
options: {
debounceDelay: 250,
}
}
And I have my copyFiles task looking like this;
grunt.registerTask('copyFiles', 'copy templates and js', function () {
console.log('in copyFiles');
var done = this.async();
var sourceScripts = path.join(__dirname, "../gscm-js/src");
var sourceTemplates = path.join(__dirname, "../gscm-js/templates");
ncp(sourceScripts, scriptsDirectory, function () {
ncp(sourceTemplates, templatesDirectory, done);
});
});
BUt the log message is never outputted to the console even though the watch task outputs that a file has changed.
grunt-contrib-watch is a Grunt multi-task, and js is the name of one of its multiple tasks.
You need to move the tasks configuration setting into the js task:
watch: {
js: {
files: [
path.join(__dirname, "../gscm-js/src/**/*.js"),
path.join(__dirname, "../gscm-js/templates/**/*.*")
],
tasks: ['copyFiles']
},
options: {
debounceDelay: 250
}
}
options can remain where it is - it's given special treatment and is shared between multiple tasks.
I am using : https://github.com/gruntjs/grunt-contrib-connect
"grunt-contrib-connect": "^1.0.2",
After run: grunt connect
Running "connect:server" (connect) task
Started connect web server on http://localhost:8000
Done.
So when I check in my browser: localhost:8000 , does not open anything.
can someone help on this?
gruntfile pastenbin : http://pastebin.com/nL771d5j
Gruntfile.js
module.exports = function (grunt) {
var config = {};
//setup the configuration object
var jshint;
//all tasks that must be loaded.
var tasks = [
,'grunt-contrib-watch'
,'grunt-contrib-concat'
,'grunt-contrib-sass'
,'grunt-contrib-connect'
];
//src ===============================
var src;
config.src = src = {
sassMain : 'scss/main.scss',
distFolder : 'public/stylesheets/dist.css',
devFolder : 'public/stylesheets/dev.css',
sassFolder : 'scss/**/*.scss',
serverPort: 9000,
serverHost: '0.0.0.0'
};
//Concat ===============================
var concat
config.concat = concat = {};
concat.dev = {
files: {
"public/myapp.development.js": [
"with-bootstrap/public/js/vendor"
,"with-bootstrap/public/js/**/*.js"
]
}
};
//Watch ===============================
config.watch = {
scripts: {
files: ["<%= src.sassFolder %>"]
,tasks: ["sass:dist"]
}
}
//Sass ===============================
var sass;
config.sass = sass = {};
//distribution
sass.dist = {
options: {
style: "compressed",
noCache: true,
sourcemap: 'none',
update:true
}
, files: {
"<%= src.distFolder %>" : "<%= src.sassMain %>"
}
};
//development env.
sass.dev = {
options: {
style: "expanded",
lineNumber: true,
}
, files: {
"<%= src.devFolder %>" : "<%= src.sassMain %>"
}
};
//grunt serve ===============================
config.connect = {
server: {
options: {
port: 8000,
base: {
path: 'SITE',
options: {
index: 'index.html',
maxAge: 300000
}
}
}
}
};
//Register custom tasks ===============================
grunt.registerTask('default',['dev']);
grunt.registerTask('dev', ['concat:dev','sass:dev']);
grunt.registerTask('dist',['concat:dev','sass:dist']);
//General setup ===============================
grunt.initConfig(config);
tasks.forEach(grunt.loadNpmTasks);
};
If you're running the grunt-contrib-connect plugin by itself, you'll need the property keepalive set to true in your grunt config:
config.connect = {
server: {
options: {
port: 8000,
keepAlive: true,
base: {
path: 'SITE',
options: {
index: 'index.html',
maxAge: 300000
}
}
}
}
};
Worth Noting if you want to use your connect config as part of a chain of tasks, keepAlive will need to be set to false, otherwise tasks after connect task won't run. You can also keep connect running by pairing it with the watch task w/o using the keepAlive option.
For some reason running grunt from the terminal doesn't work. When I run grunt dev and open http://localhost:8000/ it works, but when I just use grunt it says This site can’t be reached. localhost refused to connect.
Any ideas what I am missing?
'use strict';
var path = require('path');
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var folderMount = function folderMount(connect, point) {
return connect.static(path.resolve(point));
};
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: {
build: {
src: [".sass-cache"]
}
}, // end clean
sass: {
dist: {
options: {
style: 'expanded',
noCache: true
},
files: {
'app/production/css/style.css': 'app/scss/style.scss'
}
}
}, // end sass
cssmin: {
target: {
files: [{
expand: true,
cwd: 'app/production/css',
src: ['*.css', '!*.min.css'],
dest: 'app/production/css',
ext: '.min.css'
}]
}
}, //end cssmin
connect: {
server: {
options: {
port: 8000
}
}
}, // end connect
uglify: {
options: {
mangle: false
},
my_target: {
files: {
'app/production/js/app.min.js': ['app/js/module.js', 'app/js/config.js', 'app/js/factory.js', 'app/js/filter.js', 'app/js/PotatoAppController.js']
}
}
}, // end js minify
watch: { // this is a watcher, to run this in terminal write: grunt watch
options: {
dateFormat: function(time) {
grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString());
grunt.log.writeln('Waiting for new changes ...');
},
livereload: true
},
css: {
files: 'app/scss/style.scss',
tasks: ['sass', 'cssmin']
},
jsmin: {
files: 'app/js/*.js',
tasks: ['uglify']
},
html: {
files: ['app/views/**/*.html'],
options: {
livereload: true
}
}
} // end watch
});
grunt.loadNpmTasks('grunt-contrib-watch'); // Load the plugin that provides the "watch" task.
grunt.loadNpmTasks('grunt-contrib-cssmin'); // Load the plugin that provides the "cssmin" task.
grunt.loadNpmTasks('grunt-contrib-sass'); // Load the plugin that provides the "sass" task.
grunt.loadNpmTasks('grunt-contrib-uglify'); // Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-livereload'); // Load the plugin that provides the "livereload" task.
grunt.loadNpmTasks('grunt-contrib-connect'); // Load the plugin that provides the "connect" task.
grunt.loadNpmTasks('grunt-contrib-clean'); // Load the plugin that provides the "clean" task.
grunt.registerTask('default', ['watch']); // this is the default command, use in terminal 'grunt'
grunt.registerTask('dev', ['connect', 'sass', 'cssmin', 'uglify', 'clean', 'watch']); // use 'grunt dev' for development
};
Once you execute 'grunt', 'default' command will be executed.
In your case, only 'watch' task is executed.
grunt.registerTask('default', ['watch']);
If you want to reach 'localhost', you need to run 'connect' module.
'watch' task is just watching file changes. not launch web-server.
'connect' is for launching web-server.
Thanks.
I can't get Grunt's browser sync to update my changes. I have not use Grunt much so I am a bit new to this. Maybe some of you know what could be wrong?
I am using XAMPP and runs a wordpress site at:
http://localhost:10080/wp_demo2/
(I use port 10080 to avoid conflict with Skype)
Here is my gruntfile.js (updated)
var root = './htdocs/wp_demo2/wp-content/themes/isak/';
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
options: {
style: 'expanded',
precision: 5
},
all: {
files: {
'css/output.css': 'scss/input.scss'
}
}
},
watch: {
files: 'scss/**/*.scss',
tasks: ['sass']
},
browserSync: {
dev: {
bsFiles:
{
src: [root+'css/output.css', root + '**/*.php']
},
options: {
watchTask: true,
proxy: "localhost:10080/wp_demo2"
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browser-sync');
grunt.registerTask('default', ['browserSync', 'watch']);
};
files inside Browsersync's options is a local path, not a URL. I would set port in the path and move the routes to the files outside options.
// ...
browserSync: {
dev: {
bsFiles: {
src: ['css/output.css', '**/*.php']
},
options: {
watchTask: true,
proxy: 'localhost:10080/wp_demo2'
}
}
}
// ...
grunt.registerTask('dev', ['sass', 'browserSync', 'watch']);
Browsersync should update when output.css is modified.
Your Gruntfile.js should be located in . path.
**/* means "search in all folders".