Gruntjs - Running Multiple Blocking Tasks in a Specific Order ( Mongo & Node.js ) - node.js

I've recently taken a love to Gruntjs and have been happily throwing in at every opportunity to make my development life that much easier. I currently have it compiling my SASS files, running watches, and using nodemon to keep my node server updating as I work on the app.
So here's where I've spent the morning driving myself nuts. I would like to start MongoDB prior to the Node application running. In the Node app's setup, I check for any values in the databases, and if it's empty, push a test file full of information into the tables.
I've currently tried using grunt-concurrent and grunt-shell-spawn to run the necessary mongo and node commands.
grunt.initConfig({
shell: {
mongo: {
command: 'mongo'
},
node: {
command: 'node app.js'
}
},
concurrent: {
dev: {
tasks: ['shell:mongo','shell:node'],
options: { logConcurrentOutput: true }
}
}
});
grunt.loadNpmTasks('grunt-concurrent');
grunt.loadNpmTasks('grunt-shell-spawn');
Is there a way to ensure that the mongo command reaches it's "blocking" state prior to running the node task? I'm guessing that this could be done by running the node task async on a setTimeout function, but I don't want to have to constantly be waiting to see changes in the development process take effect. Currently I have been keeping a separate shell tab open for the database and would really like to integrate this into Grunt to keep everything in one place.
I'm not sure about it's importance on a broad scale, but anyone that's utilizing Node.js and MongoDB would really find this useful.
Thanks

Trying using grunt-nodemon with shell:mongo while specifying "options: { async: true }"
concurrent: {
tasks: ['shell', 'nodemon'],
options: {
logConcurrentOutput: true
}
},
shell: {
mongo: {
command: 'mongod',
options: {
async: true
}
}
},
nodemon: {
dev: {
script: "server.js",
}
}
This worked for me.

You can interval check the mongodb's service port to see if it is accessible?\

Related

Run protractor on live-server via grunt

I am trying to run my portractor tests on live-server via one grunt task.
I have installed live-server (https://www.npmjs.com/package/live-server) and grunt-execute. With grunt execute I managed to start live-server with a grunt command in 2 steps:
1st I created a node script (liveServer.js)
var liveServer = require("live-server");
var params = {
port: 8080,
host: "localhost",
open: true,
wait: 1000
};
liveServer.start(params);
2nd I created a task in my grunt file to start the script:
(in grunt.initConfig)
execute: {
liveserver: {
src: ['liveServer.js']
},
}
and registered a command to trigger it:
grunt.registerTask('live', [
'execute:liveserver'
]);
Now if I run "grunt live" in my commandline live-server starts, opens a browser, and I can browse my application.
I also created a protractor task in my grunt file, which works just fine as well.
(in grunt.initConfig)
protractor: {
options: {
keepAlive: false,
noColor: false
},
e2e: {
options: {
configFile: 'protractor.conf.js',
}
}
},
If I trigger it with a registered task the protractor tests run just fine, only I have to make sure live-server is running first.
So ofcourse I want to combine the two in one command that starts live-server and then runs my protractor tests.
So I tried:
grunt.registerTask('runProtractor', [
'execute:liveserver',
'protractor'
]);
But unfortunately this does not work, live-server starts and then ... nothing happens, the protractor tests aren't run. I tried changing some of the live-server parameters such as open and wait, but without any luck. There are no error messages either.
As I said before separately the tasks work both fine (with two command windows, first start live-server in one and then protractor in the other)
Does anybody have a clue why my does not continue after the live-server has started?
The execution of live-server blocks all subsequent tasks, since it doesn't "finish", i.e. to grunt the task is still running, which is why it won't proceed to the next task. You can use grunt-concurrent to run tasks in parallel.

Grunt-contrib-watch with grunt-contrib-connect

Unfortunately, grunt-contrib-watch and grunt-contrib-connect don't seem to be playing nice.
On the grunt-contrib-connect readme it says:
Note that this server only runs as long as grunt is running. Once grunt's tasks have completed, the web server stops. This behavior can be changed with the keepalive option, and can be enabled ad-hoc by running the task like grunt connect::keepalive.
Fine. But what if I want to run my watch task in tandem with the connect server? Like so:
connect: {
server: {
options: {
port: 8000,
hostname: 'localhost',
keepalive: true
}
}
},
watch: {
options: {
livereload: true
},
files: ['**'],
tasks: ['connect'],
}
Here, the connect task runs when a file is changed. If I set the connect's keepalive option to true, then grunt-contrib-watch stops watching because it technically hasn't finished it's task. If I falsify the keepalive option, then the connect server dies after it has finished the tasks.
Yes, I could run the commands...
$ grunt connect
$ grunt watch
...in separate shells, but is there no way of running them with one command?
Livereload in grunt-contrib-watch informs for changes in files at a port here below you can see it is at 35729.
On the other hand the livereload in grunt-contrib-connect listens for changes at the port 35729.
So we should should configure them as -
connect: {
server: {
options: {
port: 8000,
hostname: 'localhost',
livereload: 35729
}
}
},
watch: {
options: {
livereload: 35729
},
files: ['**'],
tasks: []
}
You need not provide "connect" as a task here. As the work of reloading is done by livereload here.
Now to make these two work with a single command we will register them as -
grunt.registerTask("server", ["connect", "watch"]);
Now the connect is run and then watch is run. Now normally registerTasks works by finishing the first task then the second task and so on. But due to the behaviour of connect as stated by you -
Note that this server only runs as long as grunt is running
Connect is run only once. But watch will keep on running looking for changes (keeping grunt running) and thus keeping the connect server up.
Now when you try
grunt server
things will work like a charm.
I use grunt-nodemon, which encapsulates watch and a nodejs launcher in a single task:
nodemon: {
dev: {
script: 'app.js',
options: {
ignore: [
'node_modules/**',
'public/**'
],
ext: 'js'
}
}
}
Then executed with:
$ grunt nodemon:dev
Now, nodemon only launches the app.js script with nodejs, so you will need a small app.js to load a static static express server:
var express = require('express');
var server = express(); // better instead
server.configure(function(){
server.use(express.static(__dirname + '/public'));
});
server.listen(3000);

Creating test groups with grunt-mocha-test

I'm using grunt-mocha-test to run node server side tests.
My Gruntfile.js looks like this
module.exports = function(grunt) {
// Add the grunt-mocha-test tasks.
grunt.loadNpmTasks('grunt-mocha-test');
grunt.initConfig({
// Configure a mochaTest task
mochaTest: {
test: {
options: {
reporter: 'dot'
},
src: [ 'test/setup.js', 'test/*.test.js' ]
}
},
});
grunt.registerTask('default', 'mochaTest');
};
What I want to do is this, I want to be able to run different test groups with different commands as follows
grunt will run all tests
grunt test1 runs a subset of tests in the test folder, and
grunt test2 runs another subset of tests
I don't know if this is possible, and I haven't been able to find anything about this in the documentation for grunt-mocha-test
I could sure use some help here.
Thanks
At the moment you have one group called test. Just add another object inside mochaTest and call grunt mochaTest:test2.

How can I run one particular CucumberJS feature using GruntJS?

I'm using CucumberJS to run tests on my NodeJS web app.
At the moment, I can run all of my grunt tasks by executing grunt, or only the CucumberJS tasks, using grunt cucumberjs.
But now I want to only execute particular features.
For example, say I have the following feature files:
Signin.feature
Favourite.feature
I want to only run the Favourite feature tests, using a command such as:
grunt cucumberjs Favourite
Is this possible?
BTW, here's my gruntfile.js:
'use strict';
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
...
cucumberjs: {
src: 'features',
options: {
steps: 'features/step_definitions',
format: 'pretty'
}
}
});
...
grunt.loadNpmTasks('grunt-cucumber');
grunt.registerTask('default', [... 'cucumberjs']);
};
I finally figured out a solution that seems to work well enough, based on tags.
So for each of my feature files, I've added a tag.
For example, for Favourite.feature:
#favourite
Feature: Favourite
As a user of the system
I would like to favourite items
Then I've used a GruntJS option to specify the tags I want to run via a command-line argument.
I do this through a grunt.option() call in my gruntfile:
cucumberjs: {
src: 'features',
options: {
steps: 'features/step_definitions',
format: 'pretty',
tags: grunt.option('cucumbertags')
}
}
So now I can run GruntJS from the command-line like this:
grunt cucumberjs --cucumbertags=#favourite
And it will only run the feature with the #favourite tag. Yay!
here is my task that allows you to filter by feature.name:
https://github.com/webforge-labs/cuked-zombie/blob/master/tasks/cucumber.js
(download it into a "tasks" folder and you can load it with: grunt.loadTasks('tasks'))
configure it like this (Gruntfile.js):
grunt.loadNpmTasks('grunt-cucumber');
grunt.initConfig({
cucumberjs: {
// config for all features when called with: `grunt cucumber`
all: {
src: 'features',
options: {
steps: "tests/js/cucumber/bootstrap.js",
format: "pretty"
}
},
// config for single features when called with `grunt --filter some-feature`
features: {
src: 'features',
options: {
steps: "tests/js/cucumber/bootstrap.js",
format: "pretty"
}
}
}
});
use it with:
grunt cucumber --filter post
which will run the post.feature (somewhere in your feature directory)
With the new cucumber-js Version it is possible to run it by feature-line:
https://github.com/cucumber/cucumber-js/pull/168
I haven't tested it with grunt but cucumber has an option for executing a scenario without modifying the gherkin file. Just call cucumber-js --name "Scenario Name", therefore I assume that sending the same argument to grant it will do its job.

watch doesn't refresh the page on file change (express site)

It would be nice to have the browser automatically reload the page when I change a project file. I have this node-express site with the server being defined in 'server.js'
However, I've tried different grunt configurations, but none of them caused the browser to reload on a file change although the 'watch' task prints a message that the file changed!
Here is the relevant grunt configuration:
watch: {
all: {
files: 'views/index.ejs', // for now only watch this file!
options: {
livereload: true
}
}
},
express: {
options: {
background: true,
error: function(err, result, code) {},
fallback: function() {},
port: 3000
delay: 0,
output: ".+",
debug: false
},
dev: {
options: {
script: './server.js',
node_env: 'development',
livereload: true
}
}
}
....
grunt.registerTask('server', [
'express:dev',
'open',
'watch'
])
};
And to run the task I do
$> grunt server
Can someone explain what is wrong with this configuration ?
thnx
You need to install the livereload browser plugin from http://livereload.com/
I am trying to use grunt livereload to reload css changes on my node.js pages. I am getting closer to solve my problem which is similar to yours. So from what i know so far and please correct me if i'm wrong you dont need to install "livereload browser plugin" right? I used grunt alone without node.js and i could just use livereload without installing "livereload browser plugin" i just had to add a line in my .html (the problem i run into with node is how to reload .ejs and i found this page/question on the way solving it) : so i dont know if installing the livereload thing is another way to do the script part or if this is the case like i mentioned in my problem if i want to live reload .ejs i have to install the plugin.

Resources