Is it possible to run a task after the watch task? - gruntjs

I have a PHP-based project that won't run on grunt-php. Instead, I use grunt-exec to run my MAMP server for development.
exec: {
serverup: {
command: '/Applications/MAMP/bin/start.sh'
},
serverdown: {
command: '/Applications/MAMP/bin/stop.sh'
}
}
In my custom development task, I run the MAMP start script just before my watch task. Then, I'm trying to stop the MAMP server after I've exited the watch task.
grunt.registerTask('default', ['jshint', 'concat', 'compass:dev', 'exec:serverup', 'watch', 'exec:serverdown']);
However, if I exit the task with Ctrl-C, the exec:serverdown task never seems to run. Is there any way to make this work? Since the server never goes down, that port is tied up until I manually run the stop script, and I get errors if I try to run the default task again before bringing it down.
If not, is there some other way I could accomplish the same thing?

You could listen on SIGINT and run the script:
var exec = require('child_process').exec;
process.on('SIGINT', function () {
exec('/Applications/MAMP/bin/stop.sh', function () {
process.exit();
});
});
module.exports = function (grunt) {};

Related

Filter output of a grunt task

I have several grunt tasks which internally use grunt-shell to execute various CLI commands.
I want to hide certain logs printed to the output console by these CLI commands.
Am trying to use grunt-reporter for this but unable to get it working.
Gruntfile.js
reporter: {
shell:{
options: {
tasks: ['shell'],
header: false
}
}
}
The short answer... It's not possible for grunt-reporter by itself to hide logs generated by a grunt-shell command.
The long answer including workaround... The logs from a grunt-shell command are generated by the shell/bash command itself and not via a node package/script. The examples shown on the grunt-reporter homepage are intercepting/manipulating a message from a node package written to stdout.
Consider the following...
Simple gist
module.exports = function(grunt) {
grunt.initConfig({
shell: {
listFiles: {
command: 'ls src/js/*.js'
}
}
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', [
'shell:listFiles'
]);
};
Running $ grunt via the CLI outputs something like this:
Running "shell:listFiles" (shell) task
src/js/a.js
src/js/b.js
src/js/c.js
Done.
Hide the header...
Utilizing grunt-reporter it's possible, (at best for this scenario), to hide the header using a config as follows:
module.exports = function(grunt) {
grunt.initConfig({
reporter: {
shell: {
options: {
tasks: ['shell:listFiles'],
header: false
}
}
},
shell: {
listFiles: {
command: 'ls src/js/*.js'
}
}
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', [
'reporter:shell', //<-- Note: The reporter task is called first.
'shell:listFiles'
]);
};
Running $ grunt via the CLI will now output something like this (Note: the header has been hidden, however the log from the ls command persists as it directly comes from the bash/shell command):
src/js/a.js
src/js/b.js
src/js/c.js
Done.
Even after adding the suppress: true to the reporter options the paths logs from the ls command persist.
Workaround
I think the only way to hide the logs from a CLI command will be to redirect the output messages to /dev/null in the 'grunt-shell' commands:
module.exports = function(grunt) {
grunt.initConfig({
reporter: {
shell: {
options: {
tasks: ['shell:listFiles'],
header: false,
}
}
},
shell: {
listFiles: {
command: 'ls src/js/*.js > /dev/null' //<-- redirect the output messages
}
}
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', [
'reporter:shell', //<-- Note: The reporter task is called first.
'shell:listFiles'
]);
};
This time running $ grunt via the CLI successfully hides the messages/logs and only reports:
Done.
Note: The addition of > /dev/null will only redirect the messages/logs and any errors will continue to get reported. Using > /dev/null 2>&1 would also hide any errors too.

Was not able to run nightwatch.js tests with mocha "Ensure the done() callback is being called"

Nearly every single example i've found on web isn't well explained how mocha should be implemented and used with nightwatchJS.
Whatever i do i am not able to avoid that error message, even if i follow all steps from official nightwatch how-to use mocha
Only thing that i was able to do is to at least make google chrome browser open and thats it.
Here is the code i am trying to run
var nightwatch = require('nightwatch');
describe('Google', function() {
var client = nightwatch.initClient({
// Pass here options from nightwatch.json
// selenium logs; change it to true if you want to see them in console
silent : false,
desiredCapabilities: {
browserName: "chrome",
javascriptEnabled: true,
acceptSslCerts: true
}
});
var browser = client.api();
// Mocha timeout
this.timeout(15000);
it('Demo test Google', function (done) {
browser
.url('http://www.google.com')
.waitForElementVisible('body', 1000)
.setValue('input[type=text]', 'nightwatch')
.waitForElementVisible('button[name=btnG]', 1000)
.click('button[name=btnG]')
.pause(1000)
.assert.containsText('#main', 'Night Watch')
.end();
client.start(done);
});
});
And this is the error message that always happen to me after the browser pop up:
INFO Request: POST /wd/hub/session
- data: {"desiredCapabilities":{"browserName":"firefox","javascriptEnabled":true,"acceptSslCerts":true,"platform":"ANY"}}
- headers: {"Content-Type":"application/json; charset=utf-8","Content-Length":113}
1) Demo test Google
0 passing (15s)
1 failing
1) Google Demo test Google:
Error: timeout of 15000ms exceeded. Ensure the done() callback is being called in this test.
The original question states that there is no great documentation regarding how to set up nightwatch with mocha. I discovered this to be the case myself this weekend as I looked to set up my nightwatch tests with mocha.
I was able to set up my nightwatch tests without seeing the done callback error by doing the following:
I used a nightwatch.conf.js but I believe you can also do the following in nightwatch.json:
module.exports = {
src_folders : ["test"],
test_runner: {
type: 'mocha',
options: {
ui: 'bdd',
reporter: 'spec'
}
},
...
}
Simple right?
This allows mocha to run your nightwatch tests.
Much simpler, friendlier syntax IMO.
Here are the relevant parts of my package.json:
{
"name": "nightwatch-mocha",
"directories": {
"test": "test"
},
"scripts": {
"nightwatch": "nightwatch -c ./nightwatch.conf.js"
},
"devDependencies": {
"chromedriver": "^73.0.0",
"mocha": "^6.1.4",
"nightwatch": "^1.0.19"
}
}
I've installed chromedriver so I can run tests via chrome.
Mocha and Nightwatch are also installed.
I've created a script called nightwatch inside the scripts object.
This will run nightwatch with mocha when I run npm run nightwatch from the command line when I'm located in the root of the project.
In addition, using the nightwatch.json or nightwatch.conf.js keeps that configuration out of your tests - you don't want to have to initialize that whenever you are writing a new test suite when you can do it once and be done.
Try invoking the done() callback in the end of the chain instead. I'm not fully up to speed with client.start(), but I'm quite sure you want to signal the test is done when the chain has reached its end.
var nightwatch = require('nightwatch');
describe('Google', function() {
var client = nightwatch.initClient({
// Pass here options from nightwatch.json
// selenium logs; change it to true if you want to see them in console
silent : false,
desiredCapabilities: {
browserName: "chrome",
javascriptEnabled: true,
acceptSslCerts: true
}
});
var browser = client.api();
// Mocha timeout
this.timeout(15000);
it('Demo test Google', function (done) {
browser
.url('http://www.google.com')
.waitForElementVisible('body', 1000)
.setValue('input[type=text]', 'nightwatch')
.waitForElementVisible('button[name=btnG]', 1000)
.click('button[name=btnG]')
.pause(1000)
.assert.containsText('#main', 'Night Watch')
.end(done);
client.start();
});
});

Global grunt task error handling

Grunt will output exit codes and that's fantastic for scripts executing grunt tasks but I want the ability to handle failed grunt tasks after grunt completes them.
I was expecting to find some type of error handling function that I could set in the initConfig somewhere but I don't see anything. Likewise, even a "finally" function would work nicely.
Basically, I have an alias task that is a set of tasks that I execute and one of them temporarily changes content of a file and I write the content back to disk after everything completes. I want to still be able to at least attempt to write the content back to disk even if tasks after the mutation occurs, fail.
Something to this affect would be great.
grunt.initConfig({
onError: function (error) {
// execute my file cleanup
},
// this is essentially a "finally" function that executes once grunt
// finishes with all tasks.
onComplete: function () {
// execute my file cleanup
}
});
I am pretty sure, that there is no such feature. But it is a popular request: 1, 2.
What can be done by now? You can write a custom grunt-task, something like the following:
var errorCb = function() { callback(); }
var doneCb = function() { callback(); }
grunt.initConfig({
task_runner: {
before: ...,
beforeEach: ...,
run: ['other_task1', 'other_task2'],
after: ...,
afterEach: ...,
onError: errorCb,
onComplete: doneCb
},
other_tasks: { ... }
});
And register your task:
grunt.registerTask('task_runner', "Tasks' lifecycle", function(task, message) {
// foreach task in tasks: grunt.task.run(task)
...
// except(`grunt.util.error`)
});
As I know, there is no beatiful way to get the result of a task run. So here comes the monkey-patching. It is possible to hook these functions: grunt.fail and grunt.log.error.
Here's some inspiration: 1, 2. Also, have a look at grunt-then.
All in all, I can not say that it is an easy task. I hope someday Grunt will have events (by now: "Note that Grunt doesn't yet emit any events, but can still be useful in your own tasks.").
P.S. Have you considered Gulp for your project?
P.S.S If you are going to write your custom task, feel free to ask me for a contribution.

GruntJs:how to bypass a task in grunt build process

is there a way to bypass the task in the grunt build process using options??
In below example i want to bypass the test and do only package and buildArtifacts tasks.
Example:
grunt.registerTask('test', [
'karma:continuous' ,
'e2e-test'
]);
grunt.registerTask('build', function (target) {
grunt.task.run(['force:on','package','test','force:off','buildArtifacts']);
});
Afterall its a .js file, i think you can write a custom js function to edit what you want to run based on "option"
As earlier said, you can edit the Gruntfile.js to create a new task.
grunt.registerTask('build-bypass-test', ['package','buildArtifacts']);
On command link just execute the below command.
grunt build-bypass-test
Updated Answer
var test = grunt.option('test');
grunt.registerTask('build',function() {
if(test) {
grunt.log.writeln('Running without test');
grunt.task.run(['force:on','package','force:off','buildArtifacts']);
} else {
grunt.log.writeln('Running with test');
grunt.task.run(['force:on','package','test','force:off','buildArtifacts']);
}
});
Hope this helps you. :)

grunt-php task springing open multiple browser instances

I'm building a Gruntfile.js.
I'm trying to create tasks for responding to php requests.
Other tasks include live compiling compass/sass and live-reload.
I've hit an interesting snag:
When I start grunt, I can see in the terminal that the watch tasks is running, and that the php server is running: I get messages in terminal about certain files not being in place.
Now heres the thing... a couple of seconds after I start grunt, firefox windows start opening. (I start the task without firefox running at all. I generally use chromium and chrome).
New windows keep opening. ff messages about firefox crashing sometimes pop up. I also get windows popping up telling me that my ff profile is inaccessible - which is what I'd expect if I try and run 'firefox' from the terminal while ff is already running.
They keep popping up until I stop grunt from running. They all close immediately when I stop the task, by Ctrl-c from the terminal.
What could be causing this?
Here is my gruntfile
module.exports = function (grunt){
grunt.initConfig({
compass : {
dist : {
options : {
cssDir : 'css',
sassDir : 'sass',
debugInfo : true
}
}
},
php :{
dist : {
options : {
keepalive : true,
port: 9000
}
},
watch : {
files : ['*.html', '*.php', 'js/*', 'sass/*', 'css/*'],
tasks : ['compass'],
options : {
livereload: true
}
}
},
});
grunt.loadNpmTasks('grunt-php');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.registerTask('default', ['php', 'watch']) ;
} ;
Your watch task specifies that you want to use livereload - so, that's (kind of) expected, right?
See here:
https://github.com/gruntjs/grunt-contrib-watch#optionslivereload
http://livereload.com/

Resources