/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; import * as should from 'should'; import * as TypeMoq from 'typemoq'; import { nb } from 'sqlops'; import * as objects from 'vs/base/common/objects'; import { CellTypes } from 'sql/parts/notebook/models/contracts'; import { ModelFactory } from 'sql/parts/notebook/models/modelFactory'; import { NotebookModelStub } from '../common'; import { EmptyFuture } from 'sql/workbench/services/notebook/common/sessionManager'; import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces'; describe('Cell Model', function (): void { let factory = new ModelFactory(); it('Should set default values if none defined', async function (): Promise { let cell = factory.createCell(undefined, undefined); should(cell.cellType).equal(CellTypes.Code); should(cell.source).equal(''); }); it('Should update values', async function (): Promise { let cell = factory.createCell(undefined, undefined); cell.language = 'sql'; should(cell.language).equal('sql'); cell.source = 'abcd'; should(cell.source).equal('abcd'); }); it('Should match ICell values if defined', async function (): Promise { let output: nb.IStreamResult = { output_type: 'stream', text: 'Some output', name: 'stdout' }; let cellData: nb.ICellContents = { cell_type: CellTypes.Markdown, source: 'some *markdown*', outputs: [output], metadata: { language: 'python' }, execution_count: 1 }; let cell = factory.createCell(cellData, undefined); should(cell.cellType).equal(cellData.cell_type); should(cell.source).equal(cellData.source); should(cell.outputs).have.length(1); should(cell.outputs[0].output_type).equal('stream'); should((cell.outputs[0]).text).equal('Some output'); }); it('Should set cell language to python if defined as python in languageInfo', async function (): Promise { let cellData: nb.ICellContents = { cell_type: CellTypes.Code, source: 'print(\'1\')', metadata: { language: 'python' }, execution_count: 1 }; let notebookModel = new NotebookModelStub({ name: 'python', version: '', mimetype: '' }); let cell = factory.createCell(cellData, { notebook: notebookModel, isTrusted: false }); should(cell.language).equal('python'); }); it('Should set cell language to python if defined as pyspark in languageInfo', async function (): Promise { let cellData: nb.ICellContents = { cell_type: CellTypes.Code, source: 'print(\'1\')', metadata: { language: 'python' }, execution_count: 1 }; let notebookModel = new NotebookModelStub({ name: 'pyspark', version: '', mimetype: '' }); let cell = factory.createCell(cellData, { notebook: notebookModel, isTrusted: false }); should(cell.language).equal('python'); }); it('Should set cell language to scala if defined as scala in languageInfo', async function (): Promise { let cellData: nb.ICellContents = { cell_type: CellTypes.Code, source: 'print(\'1\')', metadata: {}, execution_count: 1 }; let notebookModel = new NotebookModelStub({ name: 'scala', version: '', mimetype: '' }); let cell = factory.createCell(cellData, { notebook: notebookModel, isTrusted: false }); should(cell.language).equal('scala'); }); it('Should keep cell language as python if cell has language override', async function (): Promise { let cellData: nb.ICellContents = { cell_type: CellTypes.Code, source: 'print(\'1\')', metadata: { language: 'python' }, execution_count: 1 }; let notebookModel = new NotebookModelStub({ name: 'scala', version: '', mimetype: '' }); let cell = factory.createCell(cellData, { notebook: notebookModel, isTrusted: false }); should(cell.language).equal('python'); }); it('Should set cell language to python if no language defined', async function (): Promise { let cellData: nb.ICellContents = { cell_type: CellTypes.Code, source: 'print(\'1\')', metadata: { language: 'python' }, execution_count: 1 }; let notebookModel = new NotebookModelStub({ name: '', version: '', mimetype: '' }); let cell = factory.createCell(cellData, { notebook: notebookModel, isTrusted: false }); should(cell.language).equal('python'); }); it('Should match cell language to language specified if unknown language defined in languageInfo', async function (): Promise { let cellData: nb.ICellContents = { cell_type: CellTypes.Code, source: 'std::cout << "hello world";', metadata: {}, execution_count: 1 }; let notebookModel = new NotebookModelStub({ name: 'cplusplus', version: '', mimetype: '' }); let cell = factory.createCell(cellData, { notebook: notebookModel, isTrusted: false }); should(cell.language).equal('cplusplus'); }); it('Should match cell language to mimetype name is not supplied in languageInfo', async function (): Promise { let cellData: nb.ICellContents = { cell_type: CellTypes.Code, source: 'print(\'1\')', metadata: {}, execution_count: 1 }; let notebookModel = new NotebookModelStub({ name: '', version: '', mimetype: 'x-scala' }); let cell = factory.createCell(cellData, { notebook: notebookModel, isTrusted: false }); should(cell.language).equal('scala'); }); describe('Model Future handling', function (): void { let future: TypeMoq.Mock; let cell: ICellModel; beforeEach(() => { future = TypeMoq.Mock.ofType(EmptyFuture); cell = factory.createCell({ cell_type: CellTypes.Code, source: 'print "Hello"', metadata: { language: 'python' }, execution_count: 1 }, { notebook: new NotebookModelStub({ name: '', version: '', mimetype: 'x-scala' }), isTrusted: false }); }); it('should send and handle incoming messages', async () => { // Given a future let onReply: nb.MessageHandler; let onIopub: nb.MessageHandler; future.setup(f => f.setReplyHandler(TypeMoq.It.isAny())).callback((handler) => onReply = handler); future.setup(f => f.setIOPubHandler(TypeMoq.It.isAny())).callback((handler) => onIopub = handler); let outputs: ReadonlyArray = undefined; cell.onOutputsChanged((o => outputs = o)); // When I set it on the cell cell.setFuture(future.object); // Then I expect outputs to have been cleared should(outputs).have.length(0); should(onReply).not.be.undefined(); // ... And when I send an IoPub message let message: nb.IIOPubMessage = { channel: 'iopub', type: 'iopub', parent_header: undefined, metadata: undefined, header: { msg_type: 'stream' }, content: { text: 'Printed hello world' } }; onIopub.handle(message); // Then I expect an output to be added should(outputs).have.length(1); should(outputs[0].output_type).equal('stream'); message = objects.deepClone(message); message.header.msg_type = 'display_data'; onIopub.handle(message); should(outputs[1].output_type).equal('display_data'); // ... TODO: And when I sent a reply I expect it to be processed. }); it('should delete transient tag while handling incoming messages', async () => { // Given a future let onIopub: nb.MessageHandler; future.setup(f => f.setIOPubHandler(TypeMoq.It.isAny())).callback((handler) => onIopub = handler); let outputs: ReadonlyArray = undefined; cell.onOutputsChanged((o => outputs = o)); //Set the future cell.setFuture(future.object); // ... And when I send an IoPub message let message: nb.IIOPubMessage = { channel: 'iopub', type: 'iopub', parent_header: undefined, metadata: undefined, header: { msg_type: 'display_data' }, content: { text: 'Printed hello world', transient: 'transient data' } }; onIopub.handle(message); //Output array's length should be 1 //'transient' tag should no longer exist in the output should(outputs).have.length(1); should(outputs[0]['transient']).be.undefined(); }); it('should dispose old future', async () => { let oldFuture = TypeMoq.Mock.ofType(EmptyFuture); cell.setFuture(oldFuture.object); cell.setFuture(future.object); oldFuture.verify(f => f.dispose(), TypeMoq.Times.once()); }); }); });