瀏覽代碼

All tests passing

Steven Silvester 8 年之前
父節點
當前提交
a36ce0f25e

+ 3 - 3
packages/services/package.json

@@ -39,9 +39,9 @@
     "build": "npm run build:src",
     "test:coverage": "istanbul cover --dir test/coverage _mocha -- --retries 3 test/build/**/*.spec.js test/build/*.spec.js --jupyter-config-data=./test/config.json",
     "test:integration": "cd test && python integration_test.py",
-    "test:devtool": "devtool node_modules/.bin/_mocha -qc test/build/**/*.spec.js test/build*.spec.js --jupyter-config-data=./test/config.json",
-    "test:debug": "mocha test/build/**/*.spec.js test/build*.spec.js  --jupyter-config-data=./test/config.json --debug-brk",
-    "test": "mocha --retries 3 test/build/**/*.spec.js test/build*.spec.js --jupyter-config-data=./test/config.json"
+    "test:devtool": "devtool node_modules/.bin/_mocha -qc ttest/build/**/*.spec.js test/build/*.spec.js --jupyter-config-data=./test/config.json --timeout=50000",
+    "test:debug": "mocha test/build/**/*.spec.js test/build/*.spec.js  --jupyter-config-data=./test/config.json --debug-brk",
+    "test": "mocha --retries 3 test/build/**/*.spec.js test/build/*.spec.js --jupyter-config-data=./test/config.json"
   },
   "repository": {
     "type": "git",

+ 1483 - 1483
packages/services/test/src/kernel/kernel.spec.ts

@@ -202,1488 +202,1488 @@ describe('kernel', () => {
 
   });
 
-  // describe('Kernel.connectTo()', () => {
-
-  //   it('should reuse an exisiting kernel', (done) => {
-  //     let id = uuid();
-  //     tester.runningKernels = [{ name: 'foo', id }];
-  //     Kernel.connectTo(id).then(k => {
-  //       kernel = k;
-  //       Kernel.connectTo(id).then(newKernel => {
-  //         expect(newKernel.name).to.be(kernel.name);
-  //         expect(newKernel.id).to.be(kernel.id);
-  //         newKernel.dispose();
-  //         done();
-  //       });
-  //     });
-  //   });
-
-  //   it('should connect to a running kernel if given kernel options', (done) => {
-  //     let id = uuid();
-  //     tester.runningKernels = [{ name: KERNEL_OPTIONS.name, id }];
-  //     Kernel.connectTo(id).then(k => {
-  //       kernel = k;
-  //       expect(kernel.name).to.be(KERNEL_OPTIONS.name);
-  //       expect(kernel.id).to.be(id);
-  //       done();
-  //     }).catch(done);
-  //   });
-
-  //   it('should accept server settings', (done) => {
-  //     let id = uuid();
-  //     tester.runningKernels = [{ name: KERNEL_OPTIONS.name, id }];
-  //     Kernel.connectTo(id, serverSettings).then(k => {
-  //       kernel = k;
-  //       expect(kernel.name).to.be(KERNEL_OPTIONS.name);
-  //       expect(kernel.id).to.be(id);
-  //       done();
-  //     }).catch(done);
-  //   });
-
-  //   it('should fail if no running kernel available', (done) => {
-  //     let id = uuid();
-  //     tester.onRequest = () => {
-  //       tester.respond(400, { });
-  //     };
-  //     let kernelPromise = Kernel.connectTo(id);
-  //     expectFailure(kernelPromise, done, 'No running kernel with id: ' + id);
-  //   });
-
-  // });
-
-  // describe('Kernel.shutdown()', () => {
-
-  //   it('should shut down a kernel by id', (done) => {
-  //     Kernel.shutdown('foo').then(done, done);
-  //   });
-
-  //   it('should handle a 404 error', (done) => {
-  //     tester.onRequest = () => {
-  //       tester.respond(404, { });
-  //     };
-  //     Kernel.shutdown('foo').then(done, done);
-  //   });
-
-  // });
-
-  // describe('Kernel.IKernel', () => {
-
-  //   beforeEach((done) => {
-  //     Kernel.startNew().then(k => {
-  //       kernel = k;
-  //       return kernel.ready;
-  //     }).then(() => {
-  //       done();
-  //     }).catch(done);
-  //   });
-
-  //   context('#terminated', () => {
-
-  //     it('should be emitted when the kernel is shut down', (done) => {
-  //       kernel.terminated.connect((sender, args) => {
-  //         expect(sender).to.be(kernel);
-  //         expect(args).to.be(void 0);
-  //         done();
-  //       });
-  //       kernel.shutdown();
-  //     });
-
-  //   });
-
-  //   context('#statusChanged', () => {
-
-  //     it('should be a signal following the Kernel status', (done) => {
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'busy') {
-  //           done();
-  //         }
-  //       });
-  //       tester.sendStatus('busy');
-  //     });
-
-  //   });
-
-  //   context('#iopubMessage', () => {
-
-  //     it('should be emitted for an iopub message', (done) => {
-  //       kernel.iopubMessage.connect((k, msg) => {
-  //         expect(msg.header.msg_type).to.be('status');
-  //         done();
-  //       });
-  //       let msg = KernelMessage.createMessage({
-  //         msgType: 'status',
-  //         channel: 'iopub',
-  //         session: kernel.clientId
-  //       }) as KernelMessage.IStatusMsg;
-  //       msg.content.execution_state = 'idle';
-  //       msg.parent_header = msg.header;
-  //       tester.send(msg);
-  //     });
-
-  //     it('should be emitted regardless of the sender', (done) => {
-  //       kernel.iopubMessage.connect((k, msg) => {
-  //         expect(msg.header.msg_type).to.be('status');
-  //         done();
-  //       });
-  //       let msg = KernelMessage.createMessage({
-  //         msgType: 'status',
-  //         channel: 'iopub',
-  //         session: 'baz'
-  //       }) as KernelMessage.IStatusMsg;
-  //       msg.content.execution_state = 'idle';
-  //       msg.parent_header = msg.header;
-  //       tester.send(msg);
-  //     });
-
-  //   });
-
-  //   context('#unhandledMessage', () => {
-
-  //     it('should be emitted for an unhandled message', (done) => {
-  //       kernel.unhandledMessage.connect((k, msg) => {
-  //         expect(msg.header.msg_type).to.be('foo');
-  //         done();
-  //       });
-  //       let msg = KernelMessage.createShellMessage({
-  //         msgType: 'foo',
-  //         channel: 'shell',
-  //         session: kernel.clientId
-  //       });
-  //       msg.parent_header = msg.header;
-  //       tester.send(msg);
-  //     });
-
-  //     it('should not be emitted for an iopub signal', () => {
-  //       let called = false;
-  //       kernel.unhandledMessage.connect((k, msg) => {
-  //         called = true;
-  //       });
-  //       let msg = KernelMessage.createMessage({
-  //         msgType: 'status',
-  //         channel: 'iopub',
-  //         session: kernel.clientId
-  //       }) as KernelMessage.IStatusMsg;
-  //       msg.content.execution_state = 'idle';
-  //       msg.parent_header = msg.header;
-  //       tester.send(msg);
-  //       expect(called).to.be(false);
-  //     });
-
-  //     it('should not be emitted for a different client session', () => {
-  //       let called = false;
-  //       kernel.unhandledMessage.connect((k, msg) => {
-  //         called = true;
-  //       });
-  //       let msg = KernelMessage.createShellMessage({
-  //         msgType: 'foo',
-  //         channel: 'shell',
-  //         session: 'baz'
-  //       });
-  //       msg.parent_header = msg.header;
-  //       tester.send(msg);
-  //       expect(called).to.be(false);
-  //     });
-
-  //   });
-
-  //   context('#id', () => {
-
-  //     it('should be a string', () => {
-  //       expect(typeof kernel.id).to.be('string');
-  //     });
-
-  //   });
-
-  //   context('#name', () => {
-
-  //     it('should be a string', () => {
-  //       expect(typeof kernel.name).to.be('string');
-  //     });
-
-  //   });
-
-  //   context('#model', () => {
-
-  //     it('should be an IModel', () => {
-  //       let model = kernel.model;
-  //       expect(typeof model.name).to.be('string');
-  //       expect(typeof model.id).to.be('string');
-  //     });
-
-  //   });
-
-  //   context('#username', () => {
-
-  //     it('should be a string', () => {
-  //       expect(typeof kernel.username).to.be('string');
-  //     });
-
-  //   });
-
-  //   context('#serverSettings', () => {
-
-  //     it('should be the server settings', () => {
-  //       expect(kernel.serverSettings.baseUrl).to.be(PageConfig.getBaseUrl());
-  //     });
-
-  //   });
-
-  //   context('#clientId', () => {
-
-  //     it('should be a string', () => {
-  //       expect(typeof kernel.clientId).to.be('string');
-  //     });
-  //   });
-
-  //   context('#status', () => {
-
-  //     it('should get an idle status', (done) => {
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'idle') {
-  //           done();
-  //         }
-  //       });
-  //       tester.sendStatus('idle');
-  //     });
-
-  //     it('should get a restarting status', (done) => {
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'restarting') {
-  //           done();
-  //         }
-  //       });
-  //       tester.sendStatus('restarting');
-  //     });
-
-  //     it('should get a busy status', (done) => {
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'busy') {
-  //           done();
-  //         }
-  //       });
-  //       tester.sendStatus('busy');
-  //     });
-
-  //     it('should get a reconnecting status', (done) => {
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'reconnecting') {
-  //           done();
-  //         }
-  //       });
-  //       tester.close();
-  //     });
-
-  //     it('should get a dead status', (done) => {
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'dead') {
-  //           done();
-  //         }
-  //       });
-  //       tester.sendStatus('dead');
-  //     });
-
-  //     it('should handle an invalid status', (done) => {
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'idle') {
-  //           done();
-  //         }
-  //       });
-  //       tester.sendStatus('celebrating');
-  //       tester.sendStatus('idle');
-  //     });
-  //   });
-
-  //   context('#info', () => {
-
-  //     it('should get the kernel info', () => {
-  //       return kernel.ready.then(() => {
-  //         let name = kernel.info.language_info.name;
-  //         expect(name).to.be(EXAMPLE_KERNEL_INFO.language_info.name);
-  //       });
-  //     });
-
-  //   });
-
-  //   context('#getSpec()', () => {
-
-  //     it('should resolve with the spec', () => {
-  //       return kernel.getSpec().then(spec => {
-  //         expect(spec.language).to.be('python');
-  //       });
-  //     });
-
-  //   });
-
-  //   context('#isReady', () => {
-
-  //     it('should test whether the kernel is ready', () => {
-  //       return kernel.shutdown().then (() => {
-  //         return Kernel.startNew();
-  //       }).then(k => {
-  //         kernel = k;
-  //         expect(kernel.isReady).to.be(false);
-  //         return kernel.ready;
-  //       }).then(() => {
-  //         expect(kernel.isReady).to.be(true);
-  //       });
-  //     });
-  //   });
-
-  //   context('#ready', () => {
-
-  //     it('should resolve when the kernel is ready', () => {
-  //       return kernel.ready;
-  //     });
-
-  //   });
-
-  //   context('#isDisposed', () => {
-
-  //     it('should be true after we dispose of the kernel', () => {
-  //       expect(kernel.isDisposed).to.be(false);
-  //       kernel.dispose();
-  //       expect(kernel.isDisposed).to.be(true);
-  //     });
-
-  //     it('should be safe to call multiple times', () => {
-  //       expect(kernel.isDisposed).to.be(false);
-  //       expect(kernel.isDisposed).to.be(false);
-  //       kernel.dispose();
-  //       expect(kernel.isDisposed).to.be(true);
-  //       expect(kernel.isDisposed).to.be(true);
-  //     });
-  //   });
-
-  //   context('#dispose()', () => {
-
-  //     it('should dispose of the resources held by the kernel', () => {
-  //       let future = kernel.requestExecute({ code: 'foo' });
-  //       let comm = kernel.connectToComm('foo');
-  //       expect(future.isDisposed).to.be(false);
-  //       expect(comm.isDisposed).to.be(false);
-  //       kernel.dispose();
-  //       expect(future.isDisposed).to.be(true);
-  //       expect(comm.isDisposed).to.be(true);
-  //     });
-
-  //     it('should be safe to call twice', () => {
-  //       let future = kernel.requestExecute({ code: 'foo' });
-  //       let comm = kernel.connectToComm('foo');
-  //       expect(future.isDisposed).to.be(false);
-  //       expect(comm.isDisposed).to.be(false);
-  //       kernel.dispose();
-  //       expect(future.isDisposed).to.be(true);
-  //       expect(comm.isDisposed).to.be(true);
-  //       expect(kernel.isDisposed).to.be(true);
-  //       kernel.dispose();
-  //       expect(future.isDisposed).to.be(true);
-  //       expect(comm.isDisposed).to.be(true);
-  //       expect(kernel.isDisposed).to.be(true);
-  //     });
-  //   });
-
-  //   context('#sendShellMessage()', () => {
-
-  //     it('should send a message to the kernel', (done) => {
-  //       let options: KernelMessage.IOptions = {
-  //         msgType: 'custom',
-  //         channel: 'shell',
-  //         username: kernel.username,
-  //         session: kernel.clientId
-  //       };
-  //       let msg = KernelMessage.createShellMessage(options);
-  //       kernel.sendShellMessage(msg, true);
-  //       tester.onMessage((msg) => {
-  //         expect(msg.header.msg_type).to.be('custom');
-  //         done();
-  //       });
-  //     });
-
-  //     it('should send a binary message', (done) => {
-  //       let options: KernelMessage.IOptions = {
-  //         msgType: 'custom',
-  //         channel: 'shell',
-  //         username: kernel.username,
-  //         session: kernel.clientId
-  //       };
-  //       let encoder = new TextEncoder('utf8');
-  //       let data = encoder.encode('hello');
-  //       let msg = KernelMessage.createShellMessage(options, {}, {}, [data, data.buffer]);
-  //       kernel.sendShellMessage(msg, true);
-
-  //       tester.onMessage((msg: any) => {
-  //         let decoder = new TextDecoder('utf8');
-  //         let item = msg.buffers[0] as DataView;
-  //         expect(decoder.decode(item)).to.be('hello');
-  //         done();
-  //       });
-  //     });
-
-  //     it('should fail if the kernel is dead', (done) => {
-  //       let options: KernelMessage.IOptions = {
-  //         msgType: 'custom',
-  //         channel: 'shell',
-  //         username: kernel.username,
-  //         session: kernel.clientId
-  //       };
-  //       let msg = KernelMessage.createShellMessage(options);
-  //       tester.sendStatus('dead');
-  //       kernel.statusChanged.connect(() => {
-  //         try {
-  //           kernel.sendShellMessage(msg, true);
-  //         } catch (err) {
-  //           expect(err.message).to.be('Kernel is dead');
-  //           done();
-  //         }
-  //       });
-  //     });
-
-  //     it('should handle out of order messages', (done) => {
-  //       let options: KernelMessage.IOptions = {
-  //         msgType: 'custom',
-  //         channel: 'shell',
-  //         username: kernel.username,
-  //         session: kernel.clientId
-  //       };
-  //       let msg = KernelMessage.createShellMessage(options);
-  //       let future = kernel.sendShellMessage(msg, true);
-  //       let newMsg: KernelMessage.IMessage;
-
-  //       tester.onMessage((msg) => {
-  //         // trigger onDone
-  //         options.msgType = 'status';
-  //         options.channel = 'iopub';
-  //         newMsg = KernelMessage.createMessage(options, { execution_state: 'idle' });
-  //         newMsg.parent_header = msg.header;
-  //         tester.send(newMsg);
-
-  //         future.onIOPub = () => {
-  //           options.msgType = 'custom';
-  //           options.channel = 'shell';
-  //           newMsg = KernelMessage.createShellMessage(options);
-  //           newMsg.parent_header = msg.header;
-  //           tester.send(newMsg);
-  //         };
-
-  //         future.onDone = () => {
-  //           done();
-  //         };
-  //       });
-  //     });
-  //   });
-
-  //   context('#interrupt()', () => {
-
-  //     it('should interrupt and resolve with a valid server response', (done) => {
-  //       kernel.interrupt().then(() => { done(); });
-  //     });
-
-  //     it('should throw an error for an invalid response', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(200,  { id: kernel.id, name: kernel.name });
-  //       };
-  //       let interrupt = kernel.interrupt();
-  //       expectAjaxError(interrupt, done, 'Invalid Status: 200');
-  //     });
-
-  //     it('should throw an error for an error response', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(500, { });
-  //       };
-  //       let interrupt = kernel.interrupt();
-  //       expectFailure(interrupt, done, '');
-  //     });
-
-  //     it('should fail if the kernel is dead', (done) => {
-  //       tester.sendStatus('dead');
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'dead') {
-  //           expectFailure(kernel.interrupt(), done, 'Kernel is dead');
-  //         }
-  //       });
-  //     });
-  //   });
-
-  //   context('#restart()', () => {
-
-  //     it('should restart and resolve with a valid server response', (done) => {
-  //       kernel.restart().then(() => { done(); });
-  //     });
-
-  //     it('should fail if the kernel does not restart', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(500, {});
-  //       };
-  //       let restart = kernel.restart();
-  //       expectFailure(restart, done, '');
-  //     });
-
-  //     it('should throw an error for an invalid response', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(205, { id: kernel.id, name: kernel.name });
-  //       };
-  //       let restart = kernel.restart();
-  //       expectAjaxError(restart, done, 'Invalid Status: 205');
-  //     });
-
-  //     it('should throw an error for an error response', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(500, { });
-  //       };
-  //       let restart = kernel.restart();
-  //       expectFailure(restart, done, '');
-  //     });
-
-  //     it('should throw an error for an invalid id', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(200, { });
-  //       };
-  //       let restart = kernel.restart();
-  //       expectFailure(restart, done);
-  //     });
-
-  //     it('should dispose of existing comm and future objects', (done) => {
-  //       let comm = kernel.connectToComm('test');
-  //       let future = kernel.requestExecute({ code: 'foo' });
-  //       tester.runningKernels = [{ id: kernel.id, name: kernel.name }];
-  //       kernel.restart().then(() => {
-  //         expect(comm.isDisposed).to.be(true);
-  //         expect(future.isDisposed).to.be(true);
-  //         done();
-  //       });
-  //     });
-
-  //   });
-
-  //   describe('#reconnect()', () => {
-
-  //     it('should reconnect the websocket', (done) => {
-  //       kernel.ready.then(() => {
-  //         return kernel.reconnect();
-  //       }).then(() => {
-  //         done();
-  //       }).catch(done);
-  //     });
-
-  //     it("should emit a `'reconnecting'` status", (done) => {
-  //       let called = false;
-  //       kernel.ready.then(() => {
-  //         return kernel.reconnect();
-  //       }).then(() => {
-  //         expect(called).to.be(true);
-  //         done();
-  //       }).catch(done);
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'reconnecting') {
-  //           called = true;
-  //         }
-  //       });
-  //     });
-
-  //   });
-
-  //   context('#shutdown()', () => {
-
-  //     it('should shut down and resolve with a valid server response', (done) => {
-  //       kernel.shutdown().then(() => { done(); });
-  //     });
-
-  //     it('should throw an error for an invalid response', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(200, { id: uuid(), name: KERNEL_OPTIONS.name });
-  //       };
-  //       let shutdown = kernel.shutdown();
-  //       expectAjaxError(shutdown, done, 'Invalid Status: 200');
-  //     });
-
-  //     it('should handle a 404 error', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(404, { });
-  //       };
-  //       kernel.shutdown().then(done, done);
-  //     });
-
-  //     it('should throw an error for an error response', (done) => {
-  //       tester.onRequest = () => {
-  //         tester.respond(500, { });
-  //       };
-  //       let shutdown = kernel.shutdown();
-  //       expectFailure(shutdown, done, '');
-  //     });
-
-  //     it('should fail if the kernel is dead', (done) => {
-  //       tester.sendStatus('dead');
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'dead') {
-  //           expectFailure(kernel.shutdown(), done, 'Kernel is dead');
-  //         }
-  //       });
-  //     });
-
-  //     it('should dispose of all kernel instances', (done) => {
-  //       let kernel2: Kernel.IKernel;
-  //       Kernel.connectTo(kernel.id).then(k => {
-  //         kernel2 = k;
-  //         return kernel.shutdown();
-  //       }).then(() => {
-  //         expect(kernel2.isDisposed).to.be(true);
-  //         done();
-  //       }).catch(done);
-  //     });
-
-  //   });
-
-  //   context('#requestKernelInfo()', () => {
-
-  //     it('should resolve the promise', (done) => {
-  //       // resolved by KernelTester
-  //       kernel.requestKernelInfo().then((msg) => {
-  //         let name = msg.content.language_info.name;
-  //         expect(name).to.be(EXAMPLE_KERNEL_INFO.language_info.name);
-  //         done();
-  //       });
-  //     });
-  //   });
-
-  //   context('#requestComplete()', () => {
-
-  //     it('should resolve the promise', (done) => {
-  //       let options: KernelMessage.ICompleteRequest = {
-  //         code: 'hello',
-  //         cursor_pos: 4
-  //       };
-  //       tester.onMessage((msg) => {
-  //         expect(msg.header.msg_type).to.be('complete_request');
-  //         msg.parent_header = msg.header;
-  //         tester.send(msg);
-  //       });
-  //       kernel.requestComplete(options).then(() => { done(); });
-  //     });
-
-  //     it('should reject the promise if the kernel is dead', (done) => {
-  //       let options: KernelMessage.ICompleteRequest = {
-  //         code: 'hello',
-  //         cursor_pos: 4
-  //       };
-  //       tester.sendStatus('dead');
-  //       kernel.statusChanged.connect(() => {
-  //         if (kernel.status === 'dead') {
-  //           let promise = kernel.requestComplete(options);
-  //           expectFailure(promise, done, 'Kernel is dead');
-  //         }
-  //       });
-  //     });
-  //   });
-
-  //   context('#requestInspect()', () => {
-
-  //     it('should resolve the promise', (done) => {
-  //       let options: KernelMessage.IInspectRequest = {
-  //         code: 'hello',
-  //         cursor_pos: 4,
-  //         detail_level: 0
-  //       };
-  //       tester.onMessage((msg) => {
-  //         expect(msg.header.msg_type).to.be('inspect_request');
-  //         msg.parent_header = msg.header;
-  //         tester.send(msg);
-  //       });
-  //       kernel.requestInspect(options).then(() => { done(); });
-  //     });
-
-  //   });
-
-  //   context('#requestIsComplete()', () => {
-
-  //     it('should resolve the promise', (done) => {
-  //       let options: KernelMessage.IIsCompleteRequest = {
-  //         code: 'hello'
-  //       };
-  //       let promise = kernel.requestIsComplete(options);
-  //       tester.onMessage((msg) => {
-  //         expect(msg.header.msg_type).to.be('is_complete_request');
-  //         msg.parent_header = msg.header;
-  //         tester.send(msg);
-  //       });
-  //       promise.then(() => { done(); });
-  //     });
-
-  //   });
-
-  //   context('#requestHistory()', () => {
-
-  //     it('should resolve the promise', (done) => {
-  //       let options: KernelMessage.IHistoryRequest = {
-  //         output: true,
-  //         raw: true,
-  //         hist_access_type: 'search',
-  //         session: 0,
-  //         start: 1,
-  //         stop: 2,
-  //         n: 1,
-  //         pattern: '*',
-  //         unique: true,
-  //       };
-  //       let promise = kernel.requestHistory(options);
-  //       tester.onMessage((msg) => {
-  //         expect(msg.header.msg_type).to.be('history_request');
-  //         msg.parent_header = msg.header;
-  //         tester.send(msg);
-  //       });
-  //       promise.then(() => { done(); });
-  //     });
-  //   });
-
-  //   context('#sendInputReply()', () => {
-
-  //     it('should resolve the promise', (done) => {
-  //       kernel.sendInputReply({ value: 'test' });
-  //       tester.onMessage((msg) => {
-  //         expect(msg.header.msg_type).to.be('input_reply');
-  //         done();
-  //       });
-  //     });
-
-  //     it('should fail if the kernel is dead', (done) => {
-  //       tester.sendStatus('dead');
-  //       kernel.statusChanged.connect(() => {
-  //         try {
-  //           kernel.sendInputReply({ value: 'test' });
-  //         } catch (err) {
-  //           expect(err.message).to.be('Kernel is dead');
-  //           done();
-  //         }
-  //       });
-  //     });
-  //   });
-
-  //   context('#requestExecute()', () => {
-
-  //     it('should send and handle incoming messages', (done) => {
-  //       let newMsg: KernelMessage.IMessage;
-  //       let content: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(content);
-  //       expect(future.onDone).to.be(null);
-  //       expect(future.onStdin).to.be(null);
-  //       expect(future.onReply).to.be(null);
-  //       expect(future.onIOPub).to.be(null);
-
-  //       let options: KernelMessage.IOptions = {
-  //         msgType: 'custom',
-  //         channel: 'shell',
-  //         username: kernel.username,
-  //         session: kernel.clientId
-  //       };
-
-  //       tester.onMessage((msg) => {
-  //         expect(msg.channel).to.be('shell');
-
-  //         // send a reply
-  //         options.channel = 'shell';
-  //         newMsg = KernelMessage.createMessage(options);
-  //         newMsg.parent_header = msg.header;
-  //         tester.send(newMsg);
-
-  //         future.onReply = () => {
-  //           // trigger onStdin
-  //           options.channel = 'stdin';
-  //           newMsg = KernelMessage.createMessage(options);
-  //           newMsg.parent_header = msg.header;
-  //           tester.send(newMsg);
-  //         };
-
-  //         future.onStdin = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           options.channel = 'iopub';
-  //           options.msgType = 'stream';
-  //           let streamContent: JSONObject = { name: 'stdout', text: '' };
-  //           newMsg = KernelMessage.createMessage(options, streamContent);
-  //           newMsg.parent_header = msg.header;
-  //           tester.send(newMsg);
-  //         };
-
-  //         future.onIOPub = (ioMsg) => {
-  //           if (ioMsg.header.msg_type === 'stream') {
-  //             // trigger onDone
-  //             options.msgType = 'status';
-  //             newMsg = KernelMessage.createMessage(options, { execution_state: 'idle' });
-  //             newMsg.parent_header = msg.header;
-  //             tester.send(newMsg);
-  //           }
-  //         };
-
-  //         future.onDone = () => {
-  //           doLater(() => {
-  //             expect(future.isDisposed).to.be(true);
-  //             done();
-  //           });
-  //         };
-  //       });
-
-  //     });
-
-  //     it('should not dispose of KernelFuture when disposeOnDone=false', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       expect(future.onDone).to.be(null);
-  //       expect(future.onStdin).to.be(null);
-  //       expect(future.onReply).to.be(null);
-  //       expect(future.onIOPub).to.be(null);
-
-  //       tester.onMessage((msg) => {
-  //         expect(msg.channel).to.be('shell');
-
-  //         // send a reply
-  //         msg.parent_header = msg.header;
-  //         msg.channel = 'shell';
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           msg.channel = 'iopub';
-  //           msg.header.msg_type = 'stream';
-  //           msg.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msg);
-  //         };
-
-  //         future.onIOPub = () => {
-  //           if (msg.header.msg_type === 'stream') {
-  //             // trigger onDone
-  //             msg.header.msg_type = 'status';
-  //             (msg as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //             tester.send(msg);
-  //           }
-  //         };
-
-  //         future.onDone = () => {
-  //           doLater(() => {
-  //             expect(future.isDisposed).to.be(false);
-  //             expect(future.onDone).to.be(null);
-  //             expect(future.onIOPub).to.not.be(null);
-  //             future.dispose();
-  //             expect(future.onIOPub).to.be(null);
-  //             expect(future.isDisposed).to.be(true);
-  //             done();
-  //           });
-  //         };
-
-  //       });
-  //     });
-
-  //   });
-
-  //   context('#registerMessageHook()', () => {
-
-  //     it('should have the most recently registered hook run first', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         kernel.registerMessageHook(parent_header.msg_id, (msg) => {
-  //           calls.push('last');
-  //           return true;
-  //         });
-
-  //         kernel.registerMessageHook(parent_header.msg_id, (msg) => {
-  //           calls.push('first');
-  //           // not returning should also continue handling
-  //           return void 0;
-  //         });
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           // the last hook was called for the stream and the status message.
-  //           expect(calls).to.eql(['first', 'last', 'iopub', 'first', 'last', 'iopub']);
-  //           doLater(() => {
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //     it('should abort processing if a hook returns false, but the done logic should still work', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         kernel.registerMessageHook(parent_header.msg_id, (msg) => {
-  //           calls.push('last');
-  //           return true;
-  //         });
-
-  //         kernel.registerMessageHook(parent_header.msg_id, (msg) => {
-  //           calls.push('first');
-  //           return false;
-  //         });
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           // the last hook was called for the stream and the status message.
-  //           expect(calls).to.eql(['first', 'first']);
-  //           doLater(() => {
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //     it('should process additions on the next run', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         kernel.registerMessageHook(parent_header.msg_id, (msg) => {
-  //           calls.push('last');
-  //           kernel.registerMessageHook(parent_header.msg_id, (msg) => {
-  //             calls.push('first');
-  //             return true;
-  //           });
-  //           return true;
-  //         });
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           expect(calls).to.eql(['last', 'iopub', 'first', 'last', 'iopub']);
-  //           doLater(() => {
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //     it('should deactivate a hook immediately on removal', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         let toDelete = (msg: KernelMessage.IIOPubMessage) => {
-  //           calls.push('delete');
-  //           return true;
-  //         }
-  //         let toDeleteHook = kernel.registerMessageHook(parent_header.msg_id, toDelete);
-
-  //         kernel.registerMessageHook(parent_header.msg_id, (msg) => {
-  //           if (calls.length > 0) {
-  //             // delete the hook the second time around
-  //             toDeleteHook.dispose();
-  //           }
-  //           calls.push('first');
-  //           return true;
-  //         });
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           expect(calls).to.eql(['first', 'delete', 'iopub', 'first', 'iopub']);
-  //           doLater(() => {
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //   });
-  // });
-
-  // describe('IFuture', () => {
-
-  //   beforeEach((done) => {
-  //     Kernel.startNew().then(k => {
-  //       kernel = k;
-  //       done();
-  //     }).catch(done);
-  //   });
-
-  //   it('should have a msg attribute', () => {
-  //     let future = kernel.requestExecute({ code: 'hello' });
-  //     expect(typeof future.msg.header.msg_id).to.be('string');
-  //   });
-
-  //   describe('Message hooks', () => {
-
-  //     it('should have the most recently registered hook run first', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         future.registerMessageHook((msg) => {
-  //           calls.push('last');
-  //           return true;
-  //         });
-
-  //         future.registerMessageHook((msg) => {
-  //           calls.push('first');
-  //           // Check to make sure we actually got the messages we expected.
-  //           if (msg.header.msg_type === 'stream') {
-  //             expect((msg as KernelMessage.IStreamMsg).content.text).to.be('foo1');
-  //           } else {
-  //             expect((msg as KernelMessage.IStatusMsg).content.execution_state).to.be('idle');
-  //           }
-  //           // not returning should also continue handling
-  //           return void 0;
-  //         });
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           // the last hook was called for the stream and the status message.
-  //           expect(calls).to.eql(['first', 'last', 'iopub', 'first', 'last', 'iopub']);
-  //           doLater(() => {
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //     it('should abort processing if a hook returns false, but the done logic should still work', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         future.registerMessageHook((msg) => {
-  //           calls.push('last');
-  //           return true;
-  //         });
-
-  //         future.registerMessageHook((msg) => {
-  //           calls.push('first');
-  //           return false;
-  //         });
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           // the last hook was called for the stream and the status message.
-  //           expect(calls).to.eql(['first', 'first']);
-  //           doLater(() => {
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //     it('should process additions on the next run', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         future.registerMessageHook((msg) => {
-  //           calls.push('last');
-  //           future.registerMessageHook((msg) => {
-  //             calls.push('first');
-  //             return true;
-  //           });
-  //           return true;
-  //         });
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           expect(calls).to.eql(['last', 'iopub', 'first', 'last', 'iopub']);
-  //           doLater(() => {
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //     it('should deactivate message hooks immediately on removal', (done) => {
-  //       let options: KernelMessage.IExecuteRequest = {
-  //         code: 'test',
-  //         silent: false,
-  //         store_history: true,
-  //         user_expressions: {},
-  //         allow_stdin: false,
-  //         stop_on_error: false
-  //       };
-  //       let future = kernel.requestExecute(options, false);
-  //       tester.onMessage((message) => {
-  //         // send a reply
-  //         let parent_header = message.header;
-  //         let msg = createMsg('shell', parent_header);
-  //         tester.send(msg);
-
-  //         future.onReply = () => {
-  //           // trigger onIOPub with a 'stream' message
-  //           let msgStream = createMsg('iopub', parent_header);
-  //           msgStream.header.msg_type = 'stream';
-  //           msgStream.content = { 'name': 'stdout', 'text': 'foo' };
-  //           tester.send(msgStream);
-  //           // trigger onDone
-  //           let msgDone = createMsg('iopub', parent_header);
-  //           msgDone.header.msg_type = 'status';
-  //           (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
-  //           tester.send(msgDone);
-  //         };
-
-  //         let calls: string[] = [];
-  //         let toDelete = (msg: KernelMessage.IIOPubMessage) => {
-  //           calls.push('delete');
-  //           return true;
-  //         }
-  //         future.registerMessageHook(toDelete);
-
-  //         let first = (msg: KernelMessage.IIOPubMessage) => {
-  //           if (calls.length > 0) {
-  //             // delete the hook the second time around
-  //             future.removeMessageHook(toDelete);
-  //           }
-  //           calls.push('first');
-  //           return true;
-  //         }
-  //         future.registerMessageHook(first);
-
-  //         future.onIOPub = () => {
-  //           calls.push('iopub')
-  //         };
-
-  //         future.onDone = () => {
-  //           expect(calls).to.eql(['first', 'delete', 'iopub', 'first', 'iopub']);
-  //           doLater(() => {
-  //             future.dispose();
-  //             future.removeMessageHook(first);
-  //             done();
-  //           });
-  //         };
-  //       });
-  //     });
-
-  //   });
-  // });
-
-  // describe('Kernel.getSpecs()', () => {
-
-  //   it('should load the kernelspecs', (done) => {
-  //     let ids = {
-  //       'python': PYTHON_SPEC,
-  //       'python3': PYTHON3_SPEC
-  //     };
-  //     tester.specs =  { 'default': 'python',
-  //                       'kernelspecs': ids };
-  //     Kernel.getSpecs().then(specs => {
-  //       let names = Object.keys(specs.kernelspecs);
-  //       expect(names[0]).to.be('python');
-  //       expect(names[1]).to.be('python3');
-  //       done();
-  //     }).catch(done);
-  //   });
-
-  //   it('should accept ajax options', (done) => {
-  //     let ids = {
-  //       'python': PYTHON_SPEC,
-  //       'python3': PYTHON3_SPEC
-  //     };
-  //     tester.specs = { 'default': 'python',
-  //                      'kernelspecs': ids };
-  //     Kernel.getSpecs(serverSettings).then(specs => {
-  //       let names = Object.keys(specs.kernelspecs);
-  //       expect(names[0]).to.be('python');
-  //       expect(names[1]).to.be('python3');
-  //       done();
-  //     }).catch(done);
-  //   });
-
-  //   it('should handle a missing default parameter', (done) => {
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'kernelspecs': { 'python': PYTHON_SPEC } });
-  //     };
-  //     Kernel.getSpecs().then(specs => {
-  //       expect(specs.default).to.be('python');
-  //     }).then(done, done);
-  //   });
-
-  //   it('should throw for a missing kernelspecs parameter', (done) => {
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'default': PYTHON_SPEC.name });
-  //     };
-  //     let promise = Kernel.getSpecs();
-  //     expectAjaxError(promise, done, 'No kernelspecs found');
-  //   });
-
-  //   it('should omit an invalid kernelspec', (done) => {
-  //     let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
-  //     R_SPEC.name = 1;
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'default': 'python',
-  //                              'kernelspecs': { 'R': R_SPEC,
-  //                                               'python': PYTHON_SPEC }
-  //       });
-  //     };
-  //     Kernel.getSpecs().then(specs => {
-  //       expect(specs.default).to.be('python');
-  //       expect(specs.kernelspecs['R']).to.be(void 0);
-  //     }).then(done, done);
-  //   });
-
-  //   it('should handle an improper name', (done) => {
-  //     let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
-  //     R_SPEC.name = 1;
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'default': 'R',
-  //                              'kernelspecs': { 'R': R_SPEC } });
-  //     };
-  //     let promise = Kernel.getSpecs();
-  //     expectAjaxError(promise, done, 'No valid kernelspecs found');
-  //   });
-
-  //   it('should handle an improper language', (done) => {
-  //     let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
-  //     R_SPEC.spec.language = 1;
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'default': 'R',
-  //                            'kernelspecs': { 'R': R_SPEC } });
-  //     };
-  //     let promise = Kernel.getSpecs();
-  //     expectAjaxError(promise, done, 'No valid kernelspecs found');
-  //   });
-
-  //   it('should handle an improper argv', (done) => {
-  //     let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
-  //     R_SPEC.spec.argv = 'hello';
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'default': 'R',
-  //                              'kernelspecs': { 'R': R_SPEC } });
-  //     };
-  //     let promise = Kernel.getSpecs();
-  //     expectAjaxError(promise, done, 'No valid kernelspecs found');
-  //   });
-
-  //   it('should handle an improper display_name', (done) => {
-  //     let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
-  //     R_SPEC.spec.display_name = ['hello'];
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'default': 'R',
-  //                              'kernelspecs': { 'R': R_SPEC } });
-  //     };
-  //     let promise = Kernel.getSpecs();
-  //     expectAjaxError(promise, done, 'No valid kernelspecs found');
-  //   });
-
-  //   it('should handle missing resources', (done) => {
-  //     let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
-  //     delete R_SPEC.resources;
-  //     tester.onRequest = () => {
-  //       tester.respond(200, { 'default': 'R',
-  //                            'kernelspecs': { 'R': R_SPEC } });
-  //     };
-  //     let promise = Kernel.getSpecs();
-  //     expectAjaxError(promise, done, 'No valid kernelspecs found');
-  //   });
-
-  //   it('should throw an error for an invalid response', (done) => {
-  //     tester.onRequest = () => {
-  //       tester.respond(201, { });
-  //     };
-  //     let promise = Kernel.getSpecs();
-  //     expectAjaxError(promise, done, 'Invalid Status: 201');
-  //   });
-
-  // });
+  describe('Kernel.connectTo()', () => {
+
+    it('should reuse an exisiting kernel', (done) => {
+      let id = uuid();
+      tester.runningKernels = [{ name: 'foo', id }];
+      Kernel.connectTo(id).then(k => {
+        kernel = k;
+        Kernel.connectTo(id).then(newKernel => {
+          expect(newKernel.name).to.be(kernel.name);
+          expect(newKernel.id).to.be(kernel.id);
+          newKernel.dispose();
+          done();
+        });
+      });
+    });
+
+    it('should connect to a running kernel if given kernel options', (done) => {
+      let id = uuid();
+      tester.runningKernels = [{ name: KERNEL_OPTIONS.name, id }];
+      Kernel.connectTo(id).then(k => {
+        kernel = k;
+        expect(kernel.name).to.be(KERNEL_OPTIONS.name);
+        expect(kernel.id).to.be(id);
+        done();
+      }).catch(done);
+    });
+
+    it('should accept server settings', (done) => {
+      let id = uuid();
+      tester.runningKernels = [{ name: KERNEL_OPTIONS.name, id }];
+      Kernel.connectTo(id, serverSettings).then(k => {
+        kernel = k;
+        expect(kernel.name).to.be(KERNEL_OPTIONS.name);
+        expect(kernel.id).to.be(id);
+        done();
+      }).catch(done);
+    });
+
+    it('should fail if no running kernel available', (done) => {
+      let id = uuid();
+      tester.onRequest = () => {
+        tester.respond(400, { });
+      };
+      let kernelPromise = Kernel.connectTo(id);
+      expectFailure(kernelPromise, done, 'No running kernel with id: ' + id);
+    });
+
+  });
+
+  describe('Kernel.shutdown()', () => {
+
+    it('should shut down a kernel by id', (done) => {
+      Kernel.shutdown('foo').then(done, done);
+    });
+
+    it('should handle a 404 error', (done) => {
+      tester.onRequest = () => {
+        tester.respond(404, { });
+      };
+      Kernel.shutdown('foo').then(done, done);
+    });
+
+  });
+
+  describe('Kernel.IKernel', () => {
+
+    beforeEach((done) => {
+      Kernel.startNew().then(k => {
+        kernel = k;
+        return kernel.ready;
+      }).then(() => {
+        done();
+      }).catch(done);
+    });
+
+    context('#terminated', () => {
+
+      it('should be emitted when the kernel is shut down', (done) => {
+        kernel.terminated.connect((sender, args) => {
+          expect(sender).to.be(kernel);
+          expect(args).to.be(void 0);
+          done();
+        });
+        kernel.shutdown();
+      });
+
+    });
+
+    context('#statusChanged', () => {
+
+      it('should be a signal following the Kernel status', (done) => {
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'busy') {
+            done();
+          }
+        });
+        tester.sendStatus('busy');
+      });
+
+    });
+
+    context('#iopubMessage', () => {
+
+      it('should be emitted for an iopub message', (done) => {
+        kernel.iopubMessage.connect((k, msg) => {
+          expect(msg.header.msg_type).to.be('status');
+          done();
+        });
+        let msg = KernelMessage.createMessage({
+          msgType: 'status',
+          channel: 'iopub',
+          session: kernel.clientId
+        }) as KernelMessage.IStatusMsg;
+        msg.content.execution_state = 'idle';
+        msg.parent_header = msg.header;
+        tester.send(msg);
+      });
+
+      it('should be emitted regardless of the sender', (done) => {
+        kernel.iopubMessage.connect((k, msg) => {
+          expect(msg.header.msg_type).to.be('status');
+          done();
+        });
+        let msg = KernelMessage.createMessage({
+          msgType: 'status',
+          channel: 'iopub',
+          session: 'baz'
+        }) as KernelMessage.IStatusMsg;
+        msg.content.execution_state = 'idle';
+        msg.parent_header = msg.header;
+        tester.send(msg);
+      });
+
+    });
+
+    context('#unhandledMessage', () => {
+
+      it('should be emitted for an unhandled message', (done) => {
+        kernel.unhandledMessage.connect((k, msg) => {
+          expect(msg.header.msg_type).to.be('foo');
+          done();
+        });
+        let msg = KernelMessage.createShellMessage({
+          msgType: 'foo',
+          channel: 'shell',
+          session: kernel.clientId
+        });
+        msg.parent_header = msg.header;
+        tester.send(msg);
+      });
+
+      it('should not be emitted for an iopub signal', () => {
+        let called = false;
+        kernel.unhandledMessage.connect((k, msg) => {
+          called = true;
+        });
+        let msg = KernelMessage.createMessage({
+          msgType: 'status',
+          channel: 'iopub',
+          session: kernel.clientId
+        }) as KernelMessage.IStatusMsg;
+        msg.content.execution_state = 'idle';
+        msg.parent_header = msg.header;
+        tester.send(msg);
+        expect(called).to.be(false);
+      });
+
+      it('should not be emitted for a different client session', () => {
+        let called = false;
+        kernel.unhandledMessage.connect((k, msg) => {
+          called = true;
+        });
+        let msg = KernelMessage.createShellMessage({
+          msgType: 'foo',
+          channel: 'shell',
+          session: 'baz'
+        });
+        msg.parent_header = msg.header;
+        tester.send(msg);
+        expect(called).to.be(false);
+      });
+
+    });
+
+    context('#id', () => {
+
+      it('should be a string', () => {
+        expect(typeof kernel.id).to.be('string');
+      });
+
+    });
+
+    context('#name', () => {
+
+      it('should be a string', () => {
+        expect(typeof kernel.name).to.be('string');
+      });
+
+    });
+
+    context('#model', () => {
+
+      it('should be an IModel', () => {
+        let model = kernel.model;
+        expect(typeof model.name).to.be('string');
+        expect(typeof model.id).to.be('string');
+      });
+
+    });
+
+    context('#username', () => {
+
+      it('should be a string', () => {
+        expect(typeof kernel.username).to.be('string');
+      });
+
+    });
+
+    context('#serverSettings', () => {
+
+      it('should be the server settings', () => {
+        expect(kernel.serverSettings.baseUrl).to.be(PageConfig.getBaseUrl());
+      });
+
+    });
+
+    context('#clientId', () => {
+
+      it('should be a string', () => {
+        expect(typeof kernel.clientId).to.be('string');
+      });
+    });
+
+    context('#status', () => {
+
+      it('should get an idle status', (done) => {
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'idle') {
+            done();
+          }
+        });
+        tester.sendStatus('idle');
+      });
+
+      it('should get a restarting status', (done) => {
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'restarting') {
+            done();
+          }
+        });
+        tester.sendStatus('restarting');
+      });
+
+      it('should get a busy status', (done) => {
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'busy') {
+            done();
+          }
+        });
+        tester.sendStatus('busy');
+      });
+
+      it('should get a reconnecting status', (done) => {
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'reconnecting') {
+            done();
+          }
+        });
+        tester.close();
+      });
+
+      it('should get a dead status', (done) => {
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'dead') {
+            done();
+          }
+        });
+        tester.sendStatus('dead');
+      });
+
+      it('should handle an invalid status', (done) => {
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'idle') {
+            done();
+          }
+        });
+        tester.sendStatus('celebrating');
+        tester.sendStatus('idle');
+      });
+    });
+
+    context('#info', () => {
+
+      it('should get the kernel info', () => {
+        return kernel.ready.then(() => {
+          let name = kernel.info.language_info.name;
+          expect(name).to.be(EXAMPLE_KERNEL_INFO.language_info.name);
+        });
+      });
+
+    });
+
+    context('#getSpec()', () => {
+
+      it('should resolve with the spec', () => {
+        return kernel.getSpec().then(spec => {
+          expect(spec.language).to.be('python');
+        });
+      });
+
+    });
+
+    context('#isReady', () => {
+
+      it('should test whether the kernel is ready', () => {
+        return kernel.shutdown().then (() => {
+          return Kernel.startNew();
+        }).then(k => {
+          kernel = k;
+          expect(kernel.isReady).to.be(false);
+          return kernel.ready;
+        }).then(() => {
+          expect(kernel.isReady).to.be(true);
+        });
+      });
+    });
+
+    context('#ready', () => {
+
+      it('should resolve when the kernel is ready', () => {
+        return kernel.ready;
+      });
+
+    });
+
+    context('#isDisposed', () => {
+
+      it('should be true after we dispose of the kernel', () => {
+        expect(kernel.isDisposed).to.be(false);
+        kernel.dispose();
+        expect(kernel.isDisposed).to.be(true);
+      });
+
+      it('should be safe to call multiple times', () => {
+        expect(kernel.isDisposed).to.be(false);
+        expect(kernel.isDisposed).to.be(false);
+        kernel.dispose();
+        expect(kernel.isDisposed).to.be(true);
+        expect(kernel.isDisposed).to.be(true);
+      });
+    });
+
+    context('#dispose()', () => {
+
+      it('should dispose of the resources held by the kernel', () => {
+        let future = kernel.requestExecute({ code: 'foo' });
+        let comm = kernel.connectToComm('foo');
+        expect(future.isDisposed).to.be(false);
+        expect(comm.isDisposed).to.be(false);
+        kernel.dispose();
+        expect(future.isDisposed).to.be(true);
+        expect(comm.isDisposed).to.be(true);
+      });
+
+      it('should be safe to call twice', () => {
+        let future = kernel.requestExecute({ code: 'foo' });
+        let comm = kernel.connectToComm('foo');
+        expect(future.isDisposed).to.be(false);
+        expect(comm.isDisposed).to.be(false);
+        kernel.dispose();
+        expect(future.isDisposed).to.be(true);
+        expect(comm.isDisposed).to.be(true);
+        expect(kernel.isDisposed).to.be(true);
+        kernel.dispose();
+        expect(future.isDisposed).to.be(true);
+        expect(comm.isDisposed).to.be(true);
+        expect(kernel.isDisposed).to.be(true);
+      });
+    });
+
+    context('#sendShellMessage()', () => {
+
+      it('should send a message to the kernel', (done) => {
+        let options: KernelMessage.IOptions = {
+          msgType: 'custom',
+          channel: 'shell',
+          username: kernel.username,
+          session: kernel.clientId
+        };
+        let msg = KernelMessage.createShellMessage(options);
+        kernel.sendShellMessage(msg, true);
+        tester.onMessage((msg) => {
+          expect(msg.header.msg_type).to.be('custom');
+          done();
+        });
+      });
+
+      it('should send a binary message', (done) => {
+        let options: KernelMessage.IOptions = {
+          msgType: 'custom',
+          channel: 'shell',
+          username: kernel.username,
+          session: kernel.clientId
+        };
+        let encoder = new TextEncoder('utf8');
+        let data = encoder.encode('hello');
+        let msg = KernelMessage.createShellMessage(options, {}, {}, [data, data.buffer]);
+        kernel.sendShellMessage(msg, true);
+
+        tester.onMessage((msg: any) => {
+          let decoder = new TextDecoder('utf8');
+          let item = msg.buffers[0] as DataView;
+          expect(decoder.decode(item)).to.be('hello');
+          done();
+        });
+      });
+
+      it('should fail if the kernel is dead', (done) => {
+        let options: KernelMessage.IOptions = {
+          msgType: 'custom',
+          channel: 'shell',
+          username: kernel.username,
+          session: kernel.clientId
+        };
+        let msg = KernelMessage.createShellMessage(options);
+        tester.sendStatus('dead');
+        kernel.statusChanged.connect(() => {
+          try {
+            kernel.sendShellMessage(msg, true);
+          } catch (err) {
+            expect(err.message).to.be('Kernel is dead');
+            done();
+          }
+        });
+      });
+
+      it('should handle out of order messages', (done) => {
+        let options: KernelMessage.IOptions = {
+          msgType: 'custom',
+          channel: 'shell',
+          username: kernel.username,
+          session: kernel.clientId
+        };
+        let msg = KernelMessage.createShellMessage(options);
+        let future = kernel.sendShellMessage(msg, true);
+        let newMsg: KernelMessage.IMessage;
+
+        tester.onMessage((msg) => {
+          // trigger onDone
+          options.msgType = 'status';
+          options.channel = 'iopub';
+          newMsg = KernelMessage.createMessage(options, { execution_state: 'idle' });
+          newMsg.parent_header = msg.header;
+          tester.send(newMsg);
+
+          future.onIOPub = () => {
+            options.msgType = 'custom';
+            options.channel = 'shell';
+            newMsg = KernelMessage.createShellMessage(options);
+            newMsg.parent_header = msg.header;
+            tester.send(newMsg);
+          };
+
+          future.onDone = () => {
+            done();
+          };
+        });
+      });
+    });
+
+    context('#interrupt()', () => {
+
+      it('should interrupt and resolve with a valid server response', (done) => {
+        kernel.interrupt().then(() => { done(); });
+      });
+
+      it('should throw an error for an invalid response', (done) => {
+        tester.onRequest = () => {
+          tester.respond(200,  { id: kernel.id, name: kernel.name });
+        };
+        let interrupt = kernel.interrupt();
+        expectAjaxError(interrupt, done, 'Invalid Status: 200');
+      });
+
+      it('should throw an error for an error response', (done) => {
+        tester.onRequest = () => {
+          tester.respond(500, { });
+        };
+        let interrupt = kernel.interrupt();
+        expectFailure(interrupt, done, '');
+      });
+
+      it('should fail if the kernel is dead', (done) => {
+        tester.sendStatus('dead');
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'dead') {
+            expectFailure(kernel.interrupt(), done, 'Kernel is dead');
+          }
+        });
+      });
+    });
+
+    context('#restart()', () => {
+
+      it('should restart and resolve with a valid server response', (done) => {
+        kernel.restart().then(() => { done(); });
+      });
+
+      it('should fail if the kernel does not restart', (done) => {
+        tester.onRequest = () => {
+          tester.respond(500, {});
+        };
+        let restart = kernel.restart();
+        expectFailure(restart, done, '');
+      });
+
+      it('should throw an error for an invalid response', (done) => {
+        tester.onRequest = () => {
+          tester.respond(205, { id: kernel.id, name: kernel.name });
+        };
+        let restart = kernel.restart();
+        expectAjaxError(restart, done, 'Invalid Status: 205');
+      });
+
+      it('should throw an error for an error response', (done) => {
+        tester.onRequest = () => {
+          tester.respond(500, { });
+        };
+        let restart = kernel.restart();
+        expectFailure(restart, done, '');
+      });
+
+      it('should throw an error for an invalid id', (done) => {
+        tester.onRequest = () => {
+          tester.respond(200, { });
+        };
+        let restart = kernel.restart();
+        expectFailure(restart, done);
+      });
+
+      it('should dispose of existing comm and future objects', (done) => {
+        let comm = kernel.connectToComm('test');
+        let future = kernel.requestExecute({ code: 'foo' });
+        tester.runningKernels = [{ id: kernel.id, name: kernel.name }];
+        kernel.restart().then(() => {
+          expect(comm.isDisposed).to.be(true);
+          expect(future.isDisposed).to.be(true);
+          done();
+        });
+      });
+
+    });
+
+    describe('#reconnect()', () => {
+
+      it('should reconnect the websocket', (done) => {
+        kernel.ready.then(() => {
+          return kernel.reconnect();
+        }).then(() => {
+          done();
+        }).catch(done);
+      });
+
+      it("should emit a `'reconnecting'` status", (done) => {
+        let called = false;
+        kernel.ready.then(() => {
+          return kernel.reconnect();
+        }).then(() => {
+          expect(called).to.be(true);
+          done();
+        }).catch(done);
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'reconnecting') {
+            called = true;
+          }
+        });
+      });
+
+    });
+
+    context('#shutdown()', () => {
+
+      it('should shut down and resolve with a valid server response', (done) => {
+        kernel.shutdown().then(() => { done(); });
+      });
+
+      it('should throw an error for an invalid response', (done) => {
+        tester.onRequest = () => {
+          tester.respond(200, { id: uuid(), name: KERNEL_OPTIONS.name });
+        };
+        let shutdown = kernel.shutdown();
+        expectAjaxError(shutdown, done, 'Invalid Status: 200');
+      });
+
+      it('should handle a 404 error', (done) => {
+        tester.onRequest = () => {
+          tester.respond(404, { });
+        };
+        kernel.shutdown().then(done, done);
+      });
+
+      it('should throw an error for an error response', (done) => {
+        tester.onRequest = () => {
+          tester.respond(500, { });
+        };
+        let shutdown = kernel.shutdown();
+        expectFailure(shutdown, done, '');
+      });
+
+      it('should fail if the kernel is dead', (done) => {
+        tester.sendStatus('dead');
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'dead') {
+            expectFailure(kernel.shutdown(), done, 'Kernel is dead');
+          }
+        });
+      });
+
+      it('should dispose of all kernel instances', (done) => {
+        let kernel2: Kernel.IKernel;
+        Kernel.connectTo(kernel.id).then(k => {
+          kernel2 = k;
+          return kernel.shutdown();
+        }).then(() => {
+          expect(kernel2.isDisposed).to.be(true);
+          done();
+        }).catch(done);
+      });
+
+    });
+
+    context('#requestKernelInfo()', () => {
+
+      it('should resolve the promise', (done) => {
+        // resolved by KernelTester
+        kernel.requestKernelInfo().then((msg) => {
+          let name = msg.content.language_info.name;
+          expect(name).to.be(EXAMPLE_KERNEL_INFO.language_info.name);
+          done();
+        });
+      });
+    });
+
+    context('#requestComplete()', () => {
+
+      it('should resolve the promise', (done) => {
+        let options: KernelMessage.ICompleteRequest = {
+          code: 'hello',
+          cursor_pos: 4
+        };
+        tester.onMessage((msg) => {
+          expect(msg.header.msg_type).to.be('complete_request');
+          msg.parent_header = msg.header;
+          tester.send(msg);
+        });
+        kernel.requestComplete(options).then(() => { done(); });
+      });
+
+      it('should reject the promise if the kernel is dead', (done) => {
+        let options: KernelMessage.ICompleteRequest = {
+          code: 'hello',
+          cursor_pos: 4
+        };
+        tester.sendStatus('dead');
+        kernel.statusChanged.connect(() => {
+          if (kernel.status === 'dead') {
+            let promise = kernel.requestComplete(options);
+            expectFailure(promise, done, 'Kernel is dead');
+          }
+        });
+      });
+    });
+
+    context('#requestInspect()', () => {
+
+      it('should resolve the promise', (done) => {
+        let options: KernelMessage.IInspectRequest = {
+          code: 'hello',
+          cursor_pos: 4,
+          detail_level: 0
+        };
+        tester.onMessage((msg) => {
+          expect(msg.header.msg_type).to.be('inspect_request');
+          msg.parent_header = msg.header;
+          tester.send(msg);
+        });
+        kernel.requestInspect(options).then(() => { done(); });
+      });
+
+    });
+
+    context('#requestIsComplete()', () => {
+
+      it('should resolve the promise', (done) => {
+        let options: KernelMessage.IIsCompleteRequest = {
+          code: 'hello'
+        };
+        let promise = kernel.requestIsComplete(options);
+        tester.onMessage((msg) => {
+          expect(msg.header.msg_type).to.be('is_complete_request');
+          msg.parent_header = msg.header;
+          tester.send(msg);
+        });
+        promise.then(() => { done(); });
+      });
+
+    });
+
+    context('#requestHistory()', () => {
+
+      it('should resolve the promise', (done) => {
+        let options: KernelMessage.IHistoryRequest = {
+          output: true,
+          raw: true,
+          hist_access_type: 'search',
+          session: 0,
+          start: 1,
+          stop: 2,
+          n: 1,
+          pattern: '*',
+          unique: true,
+        };
+        let promise = kernel.requestHistory(options);
+        tester.onMessage((msg) => {
+          expect(msg.header.msg_type).to.be('history_request');
+          msg.parent_header = msg.header;
+          tester.send(msg);
+        });
+        promise.then(() => { done(); });
+      });
+    });
+
+    context('#sendInputReply()', () => {
+
+      it('should resolve the promise', (done) => {
+        kernel.sendInputReply({ value: 'test' });
+        tester.onMessage((msg) => {
+          expect(msg.header.msg_type).to.be('input_reply');
+          done();
+        });
+      });
+
+      it('should fail if the kernel is dead', (done) => {
+        tester.sendStatus('dead');
+        kernel.statusChanged.connect(() => {
+          try {
+            kernel.sendInputReply({ value: 'test' });
+          } catch (err) {
+            expect(err.message).to.be('Kernel is dead');
+            done();
+          }
+        });
+      });
+    });
+
+    context('#requestExecute()', () => {
+
+      it('should send and handle incoming messages', (done) => {
+        let newMsg: KernelMessage.IMessage;
+        let content: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(content);
+        expect(future.onDone).to.be(null);
+        expect(future.onStdin).to.be(null);
+        expect(future.onReply).to.be(null);
+        expect(future.onIOPub).to.be(null);
+
+        let options: KernelMessage.IOptions = {
+          msgType: 'custom',
+          channel: 'shell',
+          username: kernel.username,
+          session: kernel.clientId
+        };
+
+        tester.onMessage((msg) => {
+          expect(msg.channel).to.be('shell');
+
+          // send a reply
+          options.channel = 'shell';
+          newMsg = KernelMessage.createMessage(options);
+          newMsg.parent_header = msg.header;
+          tester.send(newMsg);
+
+          future.onReply = () => {
+            // trigger onStdin
+            options.channel = 'stdin';
+            newMsg = KernelMessage.createMessage(options);
+            newMsg.parent_header = msg.header;
+            tester.send(newMsg);
+          };
+
+          future.onStdin = () => {
+            // trigger onIOPub with a 'stream' message
+            options.channel = 'iopub';
+            options.msgType = 'stream';
+            let streamContent: JSONObject = { name: 'stdout', text: '' };
+            newMsg = KernelMessage.createMessage(options, streamContent);
+            newMsg.parent_header = msg.header;
+            tester.send(newMsg);
+          };
+
+          future.onIOPub = (ioMsg) => {
+            if (ioMsg.header.msg_type === 'stream') {
+              // trigger onDone
+              options.msgType = 'status';
+              newMsg = KernelMessage.createMessage(options, { execution_state: 'idle' });
+              newMsg.parent_header = msg.header;
+              tester.send(newMsg);
+            }
+          };
+
+          future.onDone = () => {
+            doLater(() => {
+              expect(future.isDisposed).to.be(true);
+              done();
+            });
+          };
+        });
+
+      });
+
+      it('should not dispose of KernelFuture when disposeOnDone=false', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        expect(future.onDone).to.be(null);
+        expect(future.onStdin).to.be(null);
+        expect(future.onReply).to.be(null);
+        expect(future.onIOPub).to.be(null);
+
+        tester.onMessage((msg) => {
+          expect(msg.channel).to.be('shell');
+
+          // send a reply
+          msg.parent_header = msg.header;
+          msg.channel = 'shell';
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            msg.channel = 'iopub';
+            msg.header.msg_type = 'stream';
+            msg.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msg);
+          };
+
+          future.onIOPub = () => {
+            if (msg.header.msg_type === 'stream') {
+              // trigger onDone
+              msg.header.msg_type = 'status';
+              (msg as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+              tester.send(msg);
+            }
+          };
+
+          future.onDone = () => {
+            doLater(() => {
+              expect(future.isDisposed).to.be(false);
+              expect(future.onDone).to.be(null);
+              expect(future.onIOPub).to.not.be(null);
+              future.dispose();
+              expect(future.onIOPub).to.be(null);
+              expect(future.isDisposed).to.be(true);
+              done();
+            });
+          };
+
+        });
+      });
+
+    });
+
+    context('#registerMessageHook()', () => {
+
+      it('should have the most recently registered hook run first', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          kernel.registerMessageHook(parent_header.msg_id, (msg) => {
+            calls.push('last');
+            return true;
+          });
+
+          kernel.registerMessageHook(parent_header.msg_id, (msg) => {
+            calls.push('first');
+            // not returning should also continue handling
+            return void 0;
+          });
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            // the last hook was called for the stream and the status message.
+            expect(calls).to.eql(['first', 'last', 'iopub', 'first', 'last', 'iopub']);
+            doLater(() => {
+              done();
+            });
+          };
+        });
+      });
+
+      it('should abort processing if a hook returns false, but the done logic should still work', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          kernel.registerMessageHook(parent_header.msg_id, (msg) => {
+            calls.push('last');
+            return true;
+          });
+
+          kernel.registerMessageHook(parent_header.msg_id, (msg) => {
+            calls.push('first');
+            return false;
+          });
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            // the last hook was called for the stream and the status message.
+            expect(calls).to.eql(['first', 'first']);
+            doLater(() => {
+              done();
+            });
+          };
+        });
+      });
+
+      it('should process additions on the next run', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          kernel.registerMessageHook(parent_header.msg_id, (msg) => {
+            calls.push('last');
+            kernel.registerMessageHook(parent_header.msg_id, (msg) => {
+              calls.push('first');
+              return true;
+            });
+            return true;
+          });
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            expect(calls).to.eql(['last', 'iopub', 'first', 'last', 'iopub']);
+            doLater(() => {
+              done();
+            });
+          };
+        });
+      });
+
+      it('should deactivate a hook immediately on removal', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          let toDelete = (msg: KernelMessage.IIOPubMessage) => {
+            calls.push('delete');
+            return true;
+          }
+          let toDeleteHook = kernel.registerMessageHook(parent_header.msg_id, toDelete);
+
+          kernel.registerMessageHook(parent_header.msg_id, (msg) => {
+            if (calls.length > 0) {
+              // delete the hook the second time around
+              toDeleteHook.dispose();
+            }
+            calls.push('first');
+            return true;
+          });
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            expect(calls).to.eql(['first', 'delete', 'iopub', 'first', 'iopub']);
+            doLater(() => {
+              done();
+            });
+          };
+        });
+      });
+
+    });
+  });
+
+  describe('IFuture', () => {
+
+    beforeEach((done) => {
+      Kernel.startNew().then(k => {
+        kernel = k;
+        done();
+      }).catch(done);
+    });
+
+    it('should have a msg attribute', () => {
+      let future = kernel.requestExecute({ code: 'hello' });
+      expect(typeof future.msg.header.msg_id).to.be('string');
+    });
+
+    describe('Message hooks', () => {
+
+      it('should have the most recently registered hook run first', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          future.registerMessageHook((msg) => {
+            calls.push('last');
+            return true;
+          });
+
+          future.registerMessageHook((msg) => {
+            calls.push('first');
+            // Check to make sure we actually got the messages we expected.
+            if (msg.header.msg_type === 'stream') {
+              expect((msg as KernelMessage.IStreamMsg).content.text).to.be('foo1');
+            } else {
+              expect((msg as KernelMessage.IStatusMsg).content.execution_state).to.be('idle');
+            }
+            // not returning should also continue handling
+            return void 0;
+          });
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            // the last hook was called for the stream and the status message.
+            expect(calls).to.eql(['first', 'last', 'iopub', 'first', 'last', 'iopub']);
+            doLater(() => {
+              done();
+            });
+          };
+        });
+      });
+
+      it('should abort processing if a hook returns false, but the done logic should still work', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          future.registerMessageHook((msg) => {
+            calls.push('last');
+            return true;
+          });
+
+          future.registerMessageHook((msg) => {
+            calls.push('first');
+            return false;
+          });
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            // the last hook was called for the stream and the status message.
+            expect(calls).to.eql(['first', 'first']);
+            doLater(() => {
+              done();
+            });
+          };
+        });
+      });
+
+      it('should process additions on the next run', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          future.registerMessageHook((msg) => {
+            calls.push('last');
+            future.registerMessageHook((msg) => {
+              calls.push('first');
+              return true;
+            });
+            return true;
+          });
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            expect(calls).to.eql(['last', 'iopub', 'first', 'last', 'iopub']);
+            doLater(() => {
+              done();
+            });
+          };
+        });
+      });
+
+      it('should deactivate message hooks immediately on removal', (done) => {
+        let options: KernelMessage.IExecuteRequest = {
+          code: 'test',
+          silent: false,
+          store_history: true,
+          user_expressions: {},
+          allow_stdin: false,
+          stop_on_error: false
+        };
+        let future = kernel.requestExecute(options, false);
+        tester.onMessage((message) => {
+          // send a reply
+          let parent_header = message.header;
+          let msg = createMsg('shell', parent_header);
+          tester.send(msg);
+
+          future.onReply = () => {
+            // trigger onIOPub with a 'stream' message
+            let msgStream = createMsg('iopub', parent_header);
+            msgStream.header.msg_type = 'stream';
+            msgStream.content = { 'name': 'stdout', 'text': 'foo' };
+            tester.send(msgStream);
+            // trigger onDone
+            let msgDone = createMsg('iopub', parent_header);
+            msgDone.header.msg_type = 'status';
+            (msgDone as KernelMessage.IStatusMsg).content.execution_state = 'idle';
+            tester.send(msgDone);
+          };
+
+          let calls: string[] = [];
+          let toDelete = (msg: KernelMessage.IIOPubMessage) => {
+            calls.push('delete');
+            return true;
+          }
+          future.registerMessageHook(toDelete);
+
+          let first = (msg: KernelMessage.IIOPubMessage) => {
+            if (calls.length > 0) {
+              // delete the hook the second time around
+              future.removeMessageHook(toDelete);
+            }
+            calls.push('first');
+            return true;
+          }
+          future.registerMessageHook(first);
+
+          future.onIOPub = () => {
+            calls.push('iopub')
+          };
+
+          future.onDone = () => {
+            expect(calls).to.eql(['first', 'delete', 'iopub', 'first', 'iopub']);
+            doLater(() => {
+              future.dispose();
+              future.removeMessageHook(first);
+              done();
+            });
+          };
+        });
+      });
+
+    });
+  });
+
+  describe('Kernel.getSpecs()', () => {
+
+    it('should load the kernelspecs', (done) => {
+      let ids = {
+        'python': PYTHON_SPEC,
+        'python3': PYTHON3_SPEC
+      };
+      tester.specs =  { 'default': 'python',
+                        'kernelspecs': ids };
+      Kernel.getSpecs().then(specs => {
+        let names = Object.keys(specs.kernelspecs);
+        expect(names[0]).to.be('python');
+        expect(names[1]).to.be('python3');
+        done();
+      }).catch(done);
+    });
+
+    it('should accept ajax options', (done) => {
+      let ids = {
+        'python': PYTHON_SPEC,
+        'python3': PYTHON3_SPEC
+      };
+      tester.specs = { 'default': 'python',
+                       'kernelspecs': ids };
+      Kernel.getSpecs(serverSettings).then(specs => {
+        let names = Object.keys(specs.kernelspecs);
+        expect(names[0]).to.be('python');
+        expect(names[1]).to.be('python3');
+        done();
+      }).catch(done);
+    });
+
+    it('should handle a missing default parameter', (done) => {
+      tester.onRequest = () => {
+        tester.respond(200, { 'kernelspecs': { 'python': PYTHON_SPEC } });
+      };
+      Kernel.getSpecs().then(specs => {
+        expect(specs.default).to.be('python');
+      }).then(done, done);
+    });
+
+    it('should throw for a missing kernelspecs parameter', (done) => {
+      tester.onRequest = () => {
+        tester.respond(200, { 'default': PYTHON_SPEC.name });
+      };
+      let promise = Kernel.getSpecs();
+      expectAjaxError(promise, done, 'No kernelspecs found');
+    });
+
+    it('should omit an invalid kernelspec', (done) => {
+      let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
+      R_SPEC.name = 1;
+      tester.onRequest = () => {
+        tester.respond(200, { 'default': 'python',
+                               'kernelspecs': { 'R': R_SPEC,
+                                                'python': PYTHON_SPEC }
+        });
+      };
+      Kernel.getSpecs().then(specs => {
+        expect(specs.default).to.be('python');
+        expect(specs.kernelspecs['R']).to.be(void 0);
+      }).then(done, done);
+    });
+
+    it('should handle an improper name', (done) => {
+      let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
+      R_SPEC.name = 1;
+      tester.onRequest = () => {
+        tester.respond(200, { 'default': 'R',
+                               'kernelspecs': { 'R': R_SPEC } });
+      };
+      let promise = Kernel.getSpecs();
+      expectAjaxError(promise, done, 'No valid kernelspecs found');
+    });
+
+    it('should handle an improper language', (done) => {
+      let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
+      R_SPEC.spec.language = 1;
+      tester.onRequest = () => {
+        tester.respond(200, { 'default': 'R',
+                             'kernelspecs': { 'R': R_SPEC } });
+      };
+      let promise = Kernel.getSpecs();
+      expectAjaxError(promise, done, 'No valid kernelspecs found');
+    });
+
+    it('should handle an improper argv', (done) => {
+      let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
+      R_SPEC.spec.argv = 'hello';
+      tester.onRequest = () => {
+        tester.respond(200, { 'default': 'R',
+                               'kernelspecs': { 'R': R_SPEC } });
+      };
+      let promise = Kernel.getSpecs();
+      expectAjaxError(promise, done, 'No valid kernelspecs found');
+    });
+
+    it('should handle an improper display_name', (done) => {
+      let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
+      R_SPEC.spec.display_name = ['hello'];
+      tester.onRequest = () => {
+        tester.respond(200, { 'default': 'R',
+                               'kernelspecs': { 'R': R_SPEC } });
+      };
+      let promise = Kernel.getSpecs();
+      expectAjaxError(promise, done, 'No valid kernelspecs found');
+    });
+
+    it('should handle missing resources', (done) => {
+      let R_SPEC = JSON.parse(JSON.stringify(PYTHON_SPEC));
+      delete R_SPEC.resources;
+      tester.onRequest = () => {
+        tester.respond(200, { 'default': 'R',
+                             'kernelspecs': { 'R': R_SPEC } });
+      };
+      let promise = Kernel.getSpecs();
+      expectAjaxError(promise, done, 'No valid kernelspecs found');
+    });
+
+    it('should throw an error for an invalid response', (done) => {
+      tester.onRequest = () => {
+        tester.respond(201, { });
+      };
+      let promise = Kernel.getSpecs();
+      expectAjaxError(promise, done, 'Invalid Status: 201');
+    });
+
+  });
 
 });

+ 1 - 1
packages/services/test/src/session/manager.spec.ts

@@ -79,7 +79,7 @@ describe('session/manager', () => {
       it('should get the server settings', () => {
         manager.dispose();
         let serverSettings = ServerConnection.makeSettings({ baseUrl: 'foo' });
-        manager = new SessionManager(serverSettings);
+        manager = new SessionManager({ serverSettings });
         expect(manager.serverSettings.baseUrl).to.be('foo');
       });
 

+ 2 - 6
packages/services/test/src/session/session.spec.ts

@@ -11,10 +11,6 @@ import {
   toArray
 } from '@phosphor/algorithm';
 
-import {
-  IAjaxError
-} from '../../../lib/utils';
-
 import {
   KernelMessage
 } from '../../../lib/kernel';
@@ -666,9 +662,9 @@ describe('session', () => {
         tester.onRequest = () => {
           tester.respond(410, { });
         };
-        session.shutdown().catch((err: IAjaxError) => {
+        session.shutdown().catch(err => {
           let text ='The kernel was deleted but the session was not';
-          expect(err.throwError).to.contain(text);
+          expect(err.message).to.contain(text);
         }).then(done, done);
       });