Repository: fgnass/node-dev
Pull request #223 (2019-05-02 02:09:37)

Update dateformat to v3.0.3
- Update dependency `dateformat` from `~1.0.4-1.2.3` to `^3.0.3`
- Add tests for timestamps
- Use default text for timestamp instead of forcing black
- Add node 12 target for travis tests
- Add `lint` npm script
- Run lint script on travis
- Fix linting errors
- Log functions now return their output to enable testing
- Use tap directly so we can skip easier during iterative testing
- Remove commented out test code



Patch:
diff --git a/.travis.yml b/.travis.yml
index edbde4d..e249bcc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,11 @@
-sudo: false
+jobs:
+  include:
+    - stage: lint
+      script: npm run lint
 language: node_js
 node_js:
-  - 6
-  - 8
+  - 12
   - 10
-  - 11
+  - 8
+  - 6
+sudo: false
diff --git a/lib/cfg.js b/lib/cfg.js
index abca4a7..4cb7580 100644
--- a/lib/cfg.js
+++ b/lib/cfg.js
@@ -42,7 +42,7 @@ module.exports = function (main, opts) {
     clear: !!c.clear,
     dedupe: !!c.dedupe,
     graceful_ipc: c.graceful_ipc,
-    ms_win: process.platform === "win32",
+    ms_win: process.platform === 'win32',
     ignore: ignore,
     respawn: c.respawn || false,
     extensions: c.extensions || {
diff --git a/lib/index.js b/lib/index.js
index 2fb3c43..66f1e69 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -90,7 +90,7 @@ module.exports = function (script, scriptArgs, nodeArgs, opts) {
     child.respawn = true;
     if (!willTerminate) {
       if (cfg.ms_win && cfg.graceful_ipc) {
-        log.info(`Windows workaround, sending "${cfg.graceful_ipc}" message to child.`);
+        log.info('Windows workaround, sending "' + cfg.graceful_ipc + '" message to child.');
         child.send(cfg.graceful_ipc);
       } else {
         child.kill('SIGTERM');
@@ -103,7 +103,7 @@ module.exports = function (script, scriptArgs, nodeArgs, opts) {
   process.on('SIGTERM', function () {
     if (child) {
       if (cfg.ms_win && cfg.graceful_ipc) {
-        log.info(`Windows workaround, sending "${cfg.graceful_ipc}" message to child.`);
+        log.info('Windows workaround, sending "' + cfg.graceful_ipc + '" message to child.');
         child.send(cfg.graceful_ipc);
       } else {
         child.kill('SIGTERM');
diff --git a/lib/log.js b/lib/log.js
index e79febf..fd503ae 100644
--- a/lib/log.js
+++ b/lib/log.js
@@ -12,13 +12,6 @@ var colors = {
  * either bright red in case of an error or green otherwise.
  */
 module.exports = function (cfg) {
-
-  function log(msg, level) {
-    if (cfg.timestamp) msg = color(fmt(cfg.timestamp), '30;1') + ' ' + msg;
-    var c = colors[level.toLowerCase()] || '32';
-    console.log('[' + color(level.toUpperCase(), c) + '] ' + msg);
-  }
-
   function color(s, c) {
     if (process.stdout.isTTY) {
       return '\x1B[' + c + 'm' + s + '\x1B[0m';
@@ -26,16 +19,24 @@ module.exports = function (cfg) {
     return s;
   }
 
+  function log(msg, level) {
+    if (cfg.timestamp) msg = color(fmt(new Date(), cfg.timestamp), '39') + ' ' + msg;
+    var c = colors[level.toLowerCase()] || '32';
+    var output = '[' + color(level.toUpperCase(), c) + '] ' + msg;
+    console.log(output);
+    return output;
+  }
+
   log.info = function () {
-    log(util.format.apply(util, arguments), 'info');
+    return log(util.format.apply(util, arguments), 'info');
   };
 
   log.warn = function () {
-    log(util.format.apply(util, arguments), 'warn');
+    return log(util.format.apply(util, arguments), 'warn');
   };
 
   log.error = function () {
-    log(util.format.apply(util, arguments), 'error');
+    return log(util.format.apply(util, arguments), 'error');
   };
 
   return log;
diff --git a/package.json b/package.json
index 96d0a70..ee2c882 100644
--- a/package.json
+++ b/package.json
@@ -27,10 +27,11 @@
     "node": ">=6"
   },
   "scripts": {
+    "lint": "eslint lib test",
     "test": "tap test/*.js"
   },
   "dependencies": {
-    "dateformat": "~1.0.4-1.2.3",
+    "dateformat": "^3.0.3",
     "dynamic-dedupe": "^0.3.0",
     "filewatcher": "~3.0.0",
     "minimist": "^1.1.3",


Test patch:
diff --git a/test/fixture/catchNoSuchModule.js b/test/fixture/catchNoSuchModule.js
index 11ec5d5..f3c6c13 100644
--- a/test/fixture/catchNoSuchModule.js
+++ b/test/fixture/catchNoSuchModule.js
@@ -1,5 +1,6 @@
 try {
-  require('some_module_that_does_not_exits');
+  /* eslint-disable import/no-unresolved */
+  require('some_module_that_does_not_exist');
 } catch (err) {
   console.log('Caught', err);
 }
diff --git a/test/fixture/noSuchModule.js b/test/fixture/noSuchModule.js
index 0fab3b2..a2811b7 100644
--- a/test/fixture/noSuchModule.js
+++ b/test/fixture/noSuchModule.js
@@ -1,1 +1,2 @@
-require('some_module_that_does_not_exits');
+/* eslint-disable import/no-unresolved */
+require('some_module_that_does_not_exist');
diff --git a/test/fixture/vmtest.js b/test/fixture/vmtest.js
index 8d7ddfc..2597402 100644
--- a/test/fixture/vmtest.js
+++ b/test/fixture/vmtest.js
@@ -3,7 +3,7 @@ var fs = require('fs');
 var file = __dirname + '/log.js';
 var str = fs.readFileSync(file, 'utf8');
 
-if(process.argv.length > 2 && process.argv[2] === 'nofile') {
+if (process.argv.length > 2 && process.argv[2] === 'nofile') {
   vm.runInNewContext(str, { module: {}, require: require, console: console });
 } else {
   vm.runInNewContext(str, { module: {}, require: require, console: console }, file);
diff --git a/test/fixture/win_server.js b/test/fixture/win_server.js
index 602d2e6..f9d7458 100644
--- a/test/fixture/win_server.js
+++ b/test/fixture/win_server.js
@@ -16,8 +16,8 @@ server.on('listening', function () {
 .listen(0);
 
 process.on('message', function (data) {
-  if (data === "node-dev_restart") {
-    console.log("win_server.js - win restart IPC received");
+  if (data === 'node-dev_restart') {
+    console.log('win_server.js - win restart IPC received');
     server.close();
   }
 });
diff --git a/test/index.js b/test/index.js
index bae4865..9aa1051 100644
--- a/test/index.js
+++ b/test/index.js
@@ -1,5 +1,5 @@
 var child = require('child_process');
-var test = require('tap').test;
+var tap = require('tap');
 var touch = require('touch');
 
 var dir = __dirname + '/fixture';
@@ -65,18 +65,18 @@ function run(cmd, done) {
 
 // Tests
 
-test('should pass unknown args to node binary', function (t) {
+tap.test('should pass unknown args to node binary', function (t) {
   spawn('--expose_gc gc.js foo', function (out) {
     t.is(out.trim(), 'foo function');
     return { exit: t.end.bind(t) };
   });
 });
 
-test('should restart the server', function (t) {
+tap.test('should restart the server', function (t) {
   run('server.js', t.end.bind(t));
 });
 
-test('should restart the server twice', function (t) {
+tap.test('should restart the server twice', function (t) {
   spawn('server.js', function (out) {
     if (out.match(/touch message.js/)) {
       setTimeout(touchFile(), 500);
@@ -94,64 +94,23 @@ test('should restart the server twice', function (t) {
   });
 });
 
-/*
-test('should not restart the server for ignored modules', function (t) {
-  var ps = spawn('server.js', function (out) {
-    if (out.match(/touch message.js/)) {
-      setTimeout(touchFile(ignoredFile), 500);
-
-      var successTimeoutId = setTimeout(function () {
-        ps.removeAllListeners('exit');
-        ps.kill();
-
-        t.end();
-      }, 1000);
-
-      return function () {
-        clearTimeout(successTimeoutId);
-        t.fail('server restarted unexpectedly');
-
-        return { exit: t.end.bind(t) };
-      };
-    }
-  });
-});
-*/
-
-test('should restart the cluster', function (t) {
+tap.test('should restart the cluster', function (t) {
   run('cluster.js', t.end.bind(t));
 });
 
-test('should support vm functions', function (t) {
+tap.test('should support vm functions', function (t) {
   run('vmtest.js', t.end.bind(t));
 });
 
-test('should support vm functions with missing file argument', function (t) {
+tap.test('should support vm functions with missing file argument', function (t) {
   run('vmtest.js nofile', t.end.bind(t));
 });
 
-test('should support coffeescript', function (t) {
+tap.test('should support coffeescript', function (t) {
   run('server.coffee', t.end.bind(t));
 });
 
-/*
-test('should restart when a file is renamed', function (t) {
-  var tmp = dir + '/message.tmp';
-  fs.writeFileSync(tmp, MESSAGE);
-  spawn('log.js', function (out) {
-    if (out.match(/touch message.js/)) {
-      fs.renameSync(tmp, msgFile);
-      return function (out2) {
-        if (out2.match(/Restarting/)) {
-          return { exit: t.end.bind(t) };
-        }
-      };
-    }
-  });
-});
-*/
-
-test('should handle errors', function (t) {
+tap.test('should handle errors', function (t) {
   spawn('error.js', function (out) {
     if (out.match(/ERROR/)) {
       setTimeout(touchFile(), 500);
@@ -164,14 +123,14 @@ test('should handle errors', function (t) {
   });
 });
 
-test('should watch if no such module', function (t) {
+tap.test('should watch if no such module', function (t) {
   spawn('noSuchModule.js', function (out) {
     t.like(out, /ERROR/);
     return { exit: t.end.bind(t) };
   });
 });
 
-test('should run async code un uncaughtException handlers', function (t) {
+tap.test('should run async code un uncaughtException handlers', function (t) {
   spawn('uncaughtExceptionHandler.js', function (out) {
     if (out.match(/ERROR/)) {
       return function (out2) {
@@ -183,14 +142,14 @@ test('should run async code un uncaughtException handlers', function (t) {
   });
 });
 
-test('should ignore caught errors', function (t) {
+tap.test('should ignore caught errors', function (t) {
   spawn('catchNoSuchModule.js', function (out) {
     t.like(out, /Caught/);
     return { exit: t.end.bind(t) };
   });
 });
 
-test('should not show up in argv', function (t) {
+tap.test('should not show up in argv', function (t) {
   spawn('argv.js foo', function (out) {
     var argv = JSON.parse(out.replace(/'/g, '"'));
     t.like(argv[0], /.*?node(js|\.exe)?$/);
@@ -200,14 +159,14 @@ test('should not show up in argv', function (t) {
   });
 });
 
-test('should pass through the exit code', function (t) {
+tap.test('should pass through the exit code', function (t) {
   spawn('exit.js').on('exit', function (code) {
     t.is(code, 101);
     t.end();
   });
 });
 
-test('should conceal the wrapper', function (t) {
+tap.test('should conceal the wrapper', function (t) {
   // require.main should be main.js not wrap.js!
   spawn('main.js').on('exit', function (code) {
     t.is(code, 0);
@@ -215,14 +174,14 @@ test('should conceal the wrapper', function (t) {
   });
 });
 
-test('should relay stdin', function (t) {
+tap.test('should relay stdin', function (t) {
   spawn('echo.js', function (out) {
     t.is(out, 'foo');
     return { exit: t.end.bind(t) };
   }).stdin.write('foo');
 });
 
-test('should kill the forked processes', function (t) {
+tap.test('should kill the forked processes', function (t) {
   spawn('pid.js', function (out) {
     var pid = parseInt(out, 10);
     return { exit: function () {
@@ -238,16 +197,16 @@ test('should kill the forked processes', function (t) {
   });
 });
 
-test('should set NODE_ENV', function (t) {
+tap.test('should set NODE_ENV', function (t) {
   spawn('env.js', function (out) {
     t.like(out, /development/);
     return { exit: t.end.bind(t) };
   });
 });
 
-test('should allow graceful shutdowns', function (t) {
-  if (process.platform === "win32") {
-    t.pass("should allow graceful shutdowns", {skip: "Signals are not supported on Windows"});
+tap.test('should allow graceful shutdowns', function (t) {
+  if (process.platform === 'win32') {
+    t.pass('should allow graceful shutdowns', { skip: 'Signals are not supported on Windows' });
     t.end();
   } else {
     spawn('server.js', function (out) {
@@ -263,9 +222,9 @@ test('should allow graceful shutdowns', function (t) {
   }
 });
 
-test('should send IPC shutdown on Windows', function (t) {
-  if (process.platform !== "win32") {
-    t.pass("should send IPC shutdown on Windows", {skip: "IPC not needed on non-Windows"});
+tap.test('should send IPC shutdown on Windows', function (t) {
+  if (process.platform !== 'win32') {
+    t.pass('should send IPC shutdown on Windows', { skip: 'IPC not needed on non-Windows' });
     t.end();
   } else {
     spawn('--graceful_ipc=node-dev_restart win_server.js', function (out) {
@@ -281,9 +240,21 @@ test('should send IPC shutdown on Windows', function (t) {
   }
 });
 
-test('should be resistant to breaking `require.extensions`', function (t) {
+tap.test('should be resistant to breaking `require.extensions`', function (t) {
   spawn('modify-extensions.js', function (out) {
     t.notOk(/TypeError/.test(out));
   });
   setTimeout(t.end.bind(t), 500);
 });
+
+tap.test('Logs timestamp by default', function (t) {
+  spawn('server.js', function (out) {
+    if (out.match(/touch message.js/)) {
+      setTimeout(touchFile(), 500);
+      return function (out2) {
+        t.like(out2, /\[INFO\] \d{2}:\d{2}:\d{2} Restarting/);
+        return { exit: t.end.bind(t) };
+      };
+    }
+  });
+});
diff --git a/test/log.js b/test/log.js
new file mode 100644
index 0000000..bc9c22e
--- /dev/null
+++ b/test/log.js
@@ -0,0 +1,31 @@
+var tap = require('tap');
+
+var cfg = require('../lib/cfg.js')();
+var logFactory = require('../lib/log.js');
+var log = logFactory(cfg);
+
+tap.test('log.info', function (t) {
+  var out = log.info('hello');
+  t.like(out, /\[INFO\] \d{2}:\d{2}:\d{2} hello/);
+  t.done();
+});
+
+tap.test('log.warn', function (t) {
+  var out = log.warn('a warning');
+  t.like(out, /\[WARN\] \d{2}:\d{2}:\d{2} a warning/);
+  t.done();
+});
+
+tap.test('log.error', function (t) {
+  var out = log.error('an error');
+  t.like(out, /\[ERROR\] \d{2}:\d{2}:\d{2} an error/);
+  t.done();
+});
+
+tap.test('Disable the timestmap', function (t) {
+  var noTsCfg = Object.assign({}, cfg, { timestamp: false });
+  var noTsLog = logFactory(noTsCfg);
+  var out = noTsLog.info('no timestamp');
+  t.like(out, /\[INFO\] no timestamp/);
+  t.done();
+});