Support Notebook integration testing by adding APIs & fixing others (#3848)

- Added `runCell` API. Updated runCell button to listen to events on the model so it'll reflect run cell when called from other sources
- Plumbed through kernelspec info to the extension side so when changed, it's updated
- Fixed bug in ConnectionProfile where it didn't copy from options but instead overrode with empty wrapper functions

Here's the rough test code (it's in the sql-vnext extension and will be out in a separate PR)
```ts

    it('Should connect to local notebook server with result 2', async function() {
        this.timeout(60000);
        let pythonNotebook = Object.assign({}, expectedNotebookContent, { metadata: { kernelspec: { name: "python3", display_name: "Python 3" }}});
        let uri = writeNotebookToFile(pythonNotebook);
        await ensureJupyterInstalled();

        let notebook = await sqlops.nb.showNotebookDocument(uri);
        should(notebook.document.cells).have.length(1);
        let ran = await notebook.runCell(notebook.document.cells[0]);
        should(ran).be.true('Notebook runCell failed');
        let cellOutputs = notebook.document.cells[0].contents.outputs;
        should(cellOutputs).have.length(1);
        let result = (<sqlops.nb.IExecuteResult>cellOutputs[0]).data['text/plain'];
        should(result).equal('2');

        try {
            // TODO support closing the editor. Right now this prompts and there's no override for this. Need to fix in core
            // Close the editor using the recommended vscode API
            //await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
        }
        catch (e) {}
    });

    it('Should connect to remote spark server with result 2', async function() {
        this.timeout(240000);
        let uri = writeNotebookToFile(expectedNotebookContent);
        await ensureJupyterInstalled();

        // Given a connection to a server exists
        let connectionId = await connectToSparkIntegrationServer();

        // When I open a Spark notebook and run the cell
        let notebook = await sqlops.nb.showNotebookDocument(uri, {
            connectionId: connectionId
        });
        should(notebook.document.cells).have.length(1);
        let ran = await notebook.runCell(notebook.document.cells[0]);
        should(ran).be.true('Notebook runCell failed');

        // Then I expect to get the output result of 1+1, executed remotely against the Spark endpoint
        let cellOutputs = notebook.document.cells[0].contents.outputs;
        should(cellOutputs).have.length(4);
        let sparkResult = (<sqlops.nb.IStreamResult>cellOutputs[3]).text;
        should(sparkResult).equal('2');

        try {
            // TODO support closing the editor. Right now this prompts and there's no override for this. Need to fix in core
            // Close the editor using the recommended vscode API
            //await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
        }
        catch (e) {}
    });
});
```
This commit is contained in:
Kevin Cunnane
2019-01-30 14:24:14 -08:00
committed by GitHub
parent 3ddc5e7846
commit d1fef24723
21 changed files with 321 additions and 111 deletions

View File

@@ -1488,6 +1488,12 @@ declare module 'sqlops' {
*/
readonly cells: NotebookCell[];
/**
* The spec for current kernel, if applicable. This will be undefined
* until a kernel has been started
*/
readonly kernelSpec: IKernelSpec;
/**
* Save the underlying file.
*
@@ -1558,6 +1564,15 @@ declare module 'sqlops' {
* @return A promise that resolves with a value indicating if the edits could be applied.
*/
edit(callback: (editBuilder: NotebookEditorEdit) => void, options?: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable<boolean>;
/**
* Kicks off execution of a cell. Thenable will resolve only once the full execution is completed.
*
*
* @param cell A cell in this notebook which should be executed
* @return A promise that resolves with a value indicating if the cell was run or not.
*/
runCell(cell: NotebookCell): Thenable<boolean>;
}
export interface NotebookCell {
@@ -1801,7 +1816,7 @@ declare module 'sqlops' {
export interface ICellContents {
cell_type: CellType;
source: string | string[];
metadata: {
metadata?: {
language?: string;
};
execution_count?: number;
@@ -2189,7 +2204,6 @@ declare module 'sqlops' {
handle(message: T): void | Thenable<void>;
}
/**
* A Future interface for responses from the kernel.
*
@@ -2285,6 +2299,20 @@ declare module 'sqlops' {
sendInputReply(content: IInputReply): void;
}
export interface IExecuteReplyMsg extends IShellMessage {
content: IExecuteReply;
}
/**
* The content of an `execute-reply` message.
*
* See [Messaging in Jupyter](https://jupyter-client.readthedocs.io/en/latest/messaging.html#execution-results).
*/
export interface IExecuteReply {
status: 'ok' | 'error' | 'abort';
execution_count: number | null;
}
/**
* The valid channel names.
*/