// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
// tslint:disable-next-line
///
import json2html = require('json-to-html');
import { simulate } from 'simulate-event';
import { ServiceManager } from '@jupyterlab/services';
import { ClientSession } from '@jupyterlab/apputils';
import { nbformat } from '@jupyterlab/coreutils';
import { UUID } from '@phosphor/coreutils';
import {
TextModelFactory,
DocumentRegistry,
Context
} from '@jupyterlab/docregistry';
import { INotebookModel, NotebookModelFactory } from '@jupyterlab/notebook';
import {
IRenderMime,
RenderMimeRegistry,
RenderedHTML,
standardRendererFactories
} from '@jupyterlab/rendermime';
/**
* Return a promise that resolves in the given milliseconds with the given value.
*/
export function sleep(milliseconds: number = 0, value?: T): Promise {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(value);
}, milliseconds);
});
}
/**
* Get a copy of the default rendermime instance.
*/
export function defaultRenderMime(): RenderMimeRegistry {
return Private.rendermime.clone();
}
/**
* Create a client session object.
*/
export async function createClientSession(
options: Partial = {}
): Promise {
const manager = options.manager || Private.manager.sessions;
await manager.ready;
return new ClientSession({
manager,
path: options.path || UUID.uuid4(),
name: options.name,
type: options.type,
kernelPreference: options.kernelPreference || {
shouldStart: true,
canStart: true,
name: manager.specs.default
}
});
}
/**
* Create a context for a file.
*/
export function createFileContext(
path?: string,
manager?: ServiceManager.IManager
): Context {
const factory = Private.textFactory;
manager = manager || Private.manager;
path = path || UUID.uuid4() + '.txt';
return new Context({ manager, factory, path });
}
/**
* Create a context for a notebook.
*/
export async function createNotebookContext(
path?: string,
manager?: ServiceManager.IManager
): Promise> {
const factory = Private.notebookFactory;
manager = manager || Private.manager;
path = path || UUID.uuid4() + '.ipynb';
await manager.ready;
return new Context({
manager,
factory,
path,
kernelPreference: { name: manager.specs.default }
});
}
/**
* Wait for a dialog to be attached to an element.
*/
export function waitForDialog(
host?: HTMLElement,
timeout?: number
): Promise {
return new Promise((resolve, reject) => {
let counter = 0;
const interval = 25;
const limit = Math.floor((timeout || 250) / interval);
const seek = () => {
if (++counter === limit) {
reject(new Error('Dialog not found'));
return;
}
if ((host || document.body).getElementsByClassName('jp-Dialog')[0]) {
resolve(undefined);
return;
}
setTimeout(seek, interval);
};
seek();
});
}
/**
* Accept a dialog after it is attached by accepting the default button.
*/
export async function acceptDialog(
host?: HTMLElement,
timeout?: number
): Promise {
host = host || document.body;
await waitForDialog(host, timeout);
const node = host.getElementsByClassName('jp-Dialog')[0];
if (node) {
simulate(node as HTMLElement, 'keydown', { keyCode: 13 });
}
}
/**
* Dismiss a dialog after it is attached.
*
* #### Notes
* This promise will always resolve successfully.
*/
export async function dismissDialog(
host?: HTMLElement,
timeout?: number
): Promise {
host = host || document.body;
try {
await waitForDialog(host, timeout);
} catch (error) {
return; // Ignore calls to dismiss the dialog if there is no dialog.
}
const node = host.getElementsByClassName('jp-Dialog')[0];
if (node) {
simulate(node as HTMLElement, 'keydown', { keyCode: 27 });
}
}
/**
* A namespace for private data.
*/
namespace Private {
export const manager = new ServiceManager();
export const textFactory = new TextModelFactory();
export const notebookFactory = new NotebookModelFactory({});
class JSONRenderer extends RenderedHTML {
mimeType = 'text/html';
renderModel(model: IRenderMime.IMimeModel): Promise {
let source = model.data['application/json'];
model.setData({ data: { 'text/html': json2html(source) } });
return super.renderModel(model);
}
}
const jsonRendererFactory = {
mimeTypes: ['application/json'],
safe: true,
createRenderer(
options: IRenderMime.IRendererOptions
): IRenderMime.IRenderer {
return new JSONRenderer(options);
}
};
export const rendermime = new RenderMimeRegistry({
initialFactories: standardRendererFactories
});
rendermime.addFactory(jsonRendererFactory, 10);
}
/**
* The default outputs used for testing.
*/
export const DEFAULT_OUTPUTS: nbformat.IOutput[] = [
{
name: 'stdout',
output_type: 'stream',
text: ['hello world\n', '0\n', '1\n', '2\n']
},
{
name: 'stderr',
output_type: 'stream',
text: ['output to stderr\n']
},
{
name: 'stderr',
output_type: 'stream',
text: ['output to stderr2\n']
},
{
output_type: 'execute_result',
execution_count: 1,
data: { 'text/plain': 'foo' },
metadata: {}
},
{
output_type: 'display_data',
data: { 'text/plain': 'hello, world' },
metadata: {}
},
{
output_type: 'error',
ename: 'foo',
evalue: 'bar',
traceback: ['fizz', 'buzz']
}
];