Add some tests to increase coverage, fix some failures
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index b63e294..fcad622 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -712,7 +712,11 @@
   Call *call = ObjectWrap::Unwrap<Call>(info.This());
   grpc_status_code code = static_cast<grpc_status_code>(
       Nan::To<uint32_t>(info[0]).FromJust());
-  Utf8String details(info[0]);
+  if (code == GRPC_STATUS_OK) {
+    return Nan::ThrowRangeError(
+        "cancelWithStatus cannot be called with OK status");
+  }
+  Utf8String details(info[1]);
   grpc_call_cancel_with_status(call->wrapped_call, code, *details, NULL);
 }
 
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index cb55083..b506189 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -35,7 +35,6 @@
 
 var fs = require('fs');
 var path = require('path');
-var _ = require('lodash');
 var grpc = require('..');
 var testProto = grpc.load({
   root: __dirname + '/../../..',
diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js
index ddc094f..ff10a22 100644
--- a/src/node/src/credentials.js
+++ b/src/node/src/credentials.js
@@ -99,6 +99,9 @@
         if (error.hasOwnProperty('code')) {
           code = error.code;
         }
+        if (!metadata) {
+          metadata = new Metadata();
+        }
       }
       callback(code, message, metadata._getCoreRepresentation());
     });
diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js
index c316fe7..b7f4f56 100644
--- a/src/node/test/call_test.js
+++ b/src/node/test/call_test.js
@@ -108,6 +108,17 @@
       }, TypeError);
     });
   });
+  describe('deadline', function() {
+    it('should time out immediately with negative deadline', function(done) {
+      var call = new grpc.Call(channel, 'method', -Infinity);
+      var batch = {};
+      batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
+      call.startBatch(batch, function(err, response) {
+        assert.strictEqual(response.status.code, grpc.status.DEADLINE_EXCEEDED);
+        done();
+      });
+    });
+  });
   describe('startBatch', function() {
     it('should fail without an object and a function', function() {
       var call = new grpc.Call(channel, 'method', getDeadline(1));
@@ -192,6 +203,43 @@
       });
     });
   });
+  describe('cancelWithStatus', function() {
+    it('should reject anything other than an integer and a string', function() {
+      assert.doesNotThrow(function() {
+        var call = new grpc.Call(channel, 'method', getDeadline(1));
+        call.cancelWithStatus(1, 'details');
+      });
+      assert.throws(function() {
+        var call = new grpc.Call(channel, 'method', getDeadline(1));
+        call.cancelWithStatus();
+      });
+      assert.throws(function() {
+        var call = new grpc.Call(channel, 'method', getDeadline(1));
+        call.cancelWithStatus('');
+      });
+      assert.throws(function() {
+        var call = new grpc.Call(channel, 'method', getDeadline(1));
+        call.cancelWithStatus(5, {});
+      });
+    });
+    it('should reject the OK status code', function() {
+      assert.throws(function() {
+        var call = new grpc.Call(channel, 'method', getDeadline(1));
+        call.cancelWithStatus(0, 'details');
+      });
+    });
+    it('should result in the call ending with a status', function(done) {
+      var call = new grpc.Call(channel, 'method', getDeadline(1));
+      var batch = {};
+      batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
+      call.startBatch(batch, function(err, response) {
+        assert.strictEqual(response.status.code, 5);
+        assert.strictEqual(response.status.details, 'details');
+        done();
+      });
+      call.cancelWithStatus(5, 'details');
+    });
+  });
   describe('getPeer', function() {
     it('should return a string', function() {
       var call = new grpc.Call(channel, 'method', getDeadline(1));
diff --git a/src/node/test/channel_test.js b/src/node/test/channel_test.js
index 05269f7..5bcf63e 100644
--- a/src/node/test/channel_test.js
+++ b/src/node/test/channel_test.js
@@ -155,7 +155,6 @@
       deadline.setSeconds(deadline.getSeconds() + 1);
       channel.watchConnectivityState(old_state, deadline, function(err, value) {
         assert(err);
-        console.log('Callback from watchConnectivityState');
         done();
       });
     });
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index 7fc311a..960405a 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -169,6 +169,24 @@
       done();
     });
   });
+  it.skip('should propagate errors that the updater emits', function(done) {
+    var metadataUpdater = function(service_url, callback) {
+      var error = new Error('Authentication error');
+      error.code = grpc.status.UNAUTHENTICATED;
+      callback(error);
+    };
+    var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
+    var combined_creds = grpc.credentials.combineChannelCredentials(
+        client_ssl_creds, creds);
+    var client = new Client('localhost:' + port, combined_creds,
+                            client_options);
+    client.unary({}, function(err, data) {
+      assert(err);
+      assert.strictEqual(err.message, 'Authentication error');
+      assert.strictEqual(err.code, grpc.status.UNAUTHENTICATED);
+      done();
+    });
+  });
   describe('Per-rpc creds', function() {
     var client;
     var updater_creds;
diff --git a/src/node/test/health_test.js b/src/node/test/health_test.js
index a4dc24c..c93b528 100644
--- a/src/node/test/health_test.js
+++ b/src/node/test/health_test.js
@@ -45,11 +45,13 @@
     'grpc.test.TestServiceNotServing': 'NOT_SERVING',
     'grpc.test.TestServiceServing': 'SERVING'
   };
-  var healthServer = new grpc.Server();
-  healthServer.addProtoService(health.service,
-                               new health.Implementation(statusMap));
+  var healthServer;
+  var healthImpl;
   var healthClient;
   before(function() {
+    healthServer = new grpc.Server();
+    healthImpl = new health.Implementation(statusMap);
+    healthServer.addProtoService(health.service, healthImpl);
     var port_num = healthServer.bind('0.0.0.0:0',
                                      grpc.ServerCredentials.createInsecure());
     healthServer.start();
@@ -89,4 +91,16 @@
       done();
     });
   });
+  it('should get a different response if the status changes', function(done) {
+    healthClient.check({service: 'transient'}, function(err, response) {
+      assert(err);
+      assert.strictEqual(err.code, grpc.status.NOT_FOUND);
+      healthImpl.setStatus('transient', 'SERVING');
+      healthClient.check({service: 'transient'}, function(err, response) {
+        assert.ifError(err);
+        assert.strictEqual(response.status, 'SERVING');
+        done();
+      });
+    });
+  });
 });
diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js
index f8c0b14..f008a87 100644
--- a/src/node/test/interop_sanity_test.js
+++ b/src/node/test/interop_sanity_test.js
@@ -71,7 +71,7 @@
     interop_client.runTest(port, name_override, 'server_streaming', true, true,
                            done);
   });
-  it.only('should pass ping_pong', function(done) {
+  it('should pass ping_pong', function(done) {
     interop_client.runTest(port, name_override, 'ping_pong', true, true, done);
   });
   it('should pass empty_stream', function(done) {
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 395ea88..71801c3 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -382,7 +382,8 @@
       unary: function(call, cb) {
         var req = call.request;
         if (req.error) {
-          cb(new Error('Requested error'), null, trailer_metadata);
+          cb({code: grpc.status.UNKNOWN,
+              details: 'Requested error'}, null, trailer_metadata);
         } else {
           cb(null, {count: 1}, trailer_metadata);
         }
@@ -407,7 +408,8 @@
       serverStream: function(stream) {
         var req = stream.request;
         if (req.error) {
-          var err = new Error('Requested error');
+          var err = {code: grpc.status.UNKNOWN,
+                     details: 'Requested error'};
           err.metadata = trailer_metadata;
           stream.emit('error', err);
         } else {
diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh
index 0a11e87..85e3a38 100755
--- a/tools/run_tests/run_node.sh
+++ b/tools/run_tests/run_node.sh
@@ -45,7 +45,8 @@
   gcov Release/obj.target/grpc/ext/*.o
   lcov --base-directory . --directory . -c -o coverage.info
   genhtml -o ../reports/node_ext_coverage --num-spaces 2 \
-    -t 'Node gRPC test coverage' coverage.info
+    -t 'Node gRPC test coverage' coverage.info --rc genhtml_hi_limit=95 \
+    --rc genhtml_med_limit=80
   echo '<html><head><meta http-equiv="refresh" content="0;URL=lcov-report/index.html"></head></html>' > \
     ../reports/node_coverage/index.html
 else