123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- import expect = require('expect.js');
- import {
- KernelMessage, utils, Session
- } from '@jupyterlab/services';
- import {
- Signal
- } from '@phosphor/signaling';
- import {
- Panel
- } from '@phosphor/widgets';
- import {
- IClientSession
- } from '@jupyterlab/apputils';
- import {
- ForeignHandler
- } from '@jupyterlab/console';
- import {
- CodeCellModel, CodeCellWidget
- } from '@jupyterlab/cells';
- import {
- createCodeCellFactory
- } from '../notebook/utils';
- import {
- createClientSession, defaultRenderMime
- } from '../utils';
- class TestParent extends Panel implements ForeignHandler.IReceiver {
- addCell(cell: CodeCellWidget): void {
- this.addWidget(cell);
- }
- }
- class TestHandler extends ForeignHandler {
- injected = new Signal<this, void>(this);
- received = new Signal<this, void>(this);
- rejected = new Signal<this, void>(this);
- methods: string[] = [];
- protected onIOPubMessage(sender: IClientSession, msg: KernelMessage.IIOPubMessage): boolean {
- let injected = super.onIOPubMessage(sender, msg);
- this.received.emit(void 0);
- if (injected) {
- this.injected.emit(void 0);
- } else {
- // If the message was not injected but otherwise would have been, emit
- // a rejected signal. This should only happen if `enabled` is `false`.
- let session = (msg.parent_header as KernelMessage.IHeader).session;
- let msgType = msg.header.msg_type;
- if (session !== this.session.kernel.clientId && relevantTypes.has(msgType)) {
- this.rejected.emit(void 0);
- }
- }
- return injected;
- }
- }
- const rendermime = defaultRenderMime();
- function cellFactory(): CodeCellWidget {
- let contentFactory = createCodeCellFactory();
- let model = new CodeCellModel({});
- let cell = new CodeCellWidget({ model, rendermime, contentFactory });
- return cell;
- };
- const relevantTypes = [
- 'execute_input',
- 'execute_result',
- 'display_data',
- 'stream',
- 'error',
- 'clear_output'
- ].reduce((acc, val) => {
- acc.add(val);
- return acc;
- }, new Set<string>());
- describe('@jupyterlab/console', () => {
- describe('ForeignHandler', () => {
- let local: Session.ISession;
- let foreign: Session.ISession;
- let handler: TestHandler;
- let session: IClientSession;
- before(() => {
- let path = utils.uuid();
- let sessions = [Session.startNew({ path }), Session.startNew({ path })];
- return Promise.all(sessions).then(([one, two]) => {
- local = one;
- foreign = two;
- }).then(() => {
- return createClientSession({ path: local.path });
- }).then(s => {
- session = s;
- return s.initialize();
- });
- });
- beforeEach(() => {
- let parent = new TestParent();
- handler = new TestHandler({ session, parent, cellFactory });
- });
- afterEach(() => {
- handler.dispose();
- });
- after(() => {
- local.dispose();
- foreign.dispose();
- return session.shutdown().then(() => {
- session.dispose();
- });
- });
- describe('#constructor()', () => {
- it('should create a new foreign handler', () => {
- expect(handler).to.be.a(ForeignHandler);
- });
- });
- describe('#enabled', () => {
- it('should default to `true`', () => {
- expect(handler.enabled).to.be(true);
- });
- it('should allow foreign cells to be injected if `true`', done => {
- let code = 'print("#enabled:true")';
- handler.injected.connect(() => { done(); });
- foreign.kernel.requestExecute({ code, stop_on_error: true });
- });
- it('should reject foreign cells if `false`', done => {
- let code = 'print("#enabled:false")';
- handler.enabled = false;
- handler.rejected.connect(() => { done(); });
- foreign.kernel.requestExecute({ code, stop_on_error: true });
- });
- });
- describe('#isDisposed', () => {
- it('should indicate whether the handler is disposed', () => {
- expect(handler.isDisposed).to.be(false);
- handler.dispose();
- expect(handler.isDisposed).to.be(true);
- });
- });
- describe('#session', () => {
- it('should be a client session object', () => {
- expect(handler.session.path).to.ok();
- });
- });
- describe('#parent', () => {
- it('should be set upon instantiation', () => {
- let parent = new TestParent();
- handler = new TestHandler({
- session: handler.session, parent, cellFactory
- });
- expect(handler.parent).to.be(parent);
- });
- });
- describe('#dispose()', () => {
- it('should dispose the resources held by the handler', () => {
- expect(handler.isDisposed).to.be(false);
- handler.dispose();
- expect(handler.isDisposed).to.be(true);
- });
- it('should be safe to call multiple times', () => {
- expect(handler.isDisposed).to.be(false);
- handler.dispose();
- handler.dispose();
- expect(handler.isDisposed).to.be(true);
- });
- });
- describe('#onIOPubMessage()', () => {
- it('should be called when messages come through', done => {
- let code = 'print("onIOPubMessage:disabled")';
- handler.enabled = false;
- handler.received.connect(() => { done(); });
- foreign.kernel.requestExecute({ code, stop_on_error: true });
- });
- it('should inject relevant cells into the parent', done => {
- let code = 'print("#onIOPubMessage:enabled")';
- let parent = handler.parent as TestParent;
- expect(parent.widgets.length).to.be(0);
- handler.injected.connect(() => {
- expect(parent.widgets.length).to.be.greaterThan(0);
- done();
- });
- foreign.kernel.requestExecute({ code, stop_on_error: true });
- });
- it('should not reject relevant iopub messages', done => {
- let code = 'print("#onIOPubMessage:relevant")';
- let called = 0;
- handler.rejected.connect(() => {
- done(new Error('rejected relevant iopub message'));
- });
- handler.injected.connect(() => {
- if (++called === 2) {
- done();
- }
- });
- foreign.kernel.requestExecute({ code, stop_on_error: true });
- });
- });
- });
- });
|