mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-26 09:35:38 -05:00
Notebook Service tests (#13181)
This commit is contained in:
@@ -3,10 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EOL } from 'os';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { getErrorMessage } from './common/utils';
|
||||
import { ResourceTypeCategories } from './constants';
|
||||
import { FieldType, OptionsType } from './interfaces';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export const account = localize('azure.account', "Azure Account");
|
||||
@@ -45,6 +46,10 @@ export const multipleValidationErrors = localize("validation.multipleValidationE
|
||||
|
||||
export const scriptToNotebook = localize('ui.ScriptToNotebookButton', "Script");
|
||||
export const deployNotebook = localize('ui.DeployButton', "Run");
|
||||
export const viewErrorDetail = localize('resourceDeployment.ViewErrorDetail', "View error detail");
|
||||
export const failedToOpenNotebook = (error: any) => localize('resourceDeployment.FailedToOpenNotebook', "An error occurred opening the output notebook. {1}{2}.", EOL, getErrorMessage(error));
|
||||
export const backgroundExecutionFailed = (taskName: string) => localize('resourceDeployment.BackgroundExecutionFailed', "The task \"{0}\" has failed.", taskName);
|
||||
export const taskFailedWithNoOutputNotebook = (taskName: string) => localize('resourceDeployment.TaskFailedWithNoOutputNotebook', "The task \"{0}\" failed and no output Notebook was generated.", taskName);
|
||||
|
||||
export function getResourceTypeCategoryLocalizedString(resourceTypeCategory: string): string {
|
||||
switch (resourceTypeCategory) {
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import { EOL } from 'os';
|
||||
|
||||
import * as path from 'path';
|
||||
import { isString } from 'util';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { NotebookPathInfo } from '../interfaces';
|
||||
import { getDateTimeString, getErrorMessage } from '../common/utils';
|
||||
import { NotebookPathInfo } from '../interfaces';
|
||||
import { IPlatformService } from './platformService';
|
||||
import * as loc from '../localizedConstants';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export interface Notebook {
|
||||
@@ -42,6 +42,7 @@ export interface INotebookService {
|
||||
backgroundExecuteNotebook(taskName: string | undefined, notebookInfo: string | NotebookPathInfo | Notebook, tempNotebookPrefix: string, platformService: IPlatformService, env?: NodeJS.ProcessEnv): void;
|
||||
}
|
||||
|
||||
|
||||
export class NotebookService implements INotebookService {
|
||||
|
||||
constructor(private platformService: IPlatformService, private extensionPath: string) { }
|
||||
@@ -145,21 +146,20 @@ export class NotebookService implements INotebookService {
|
||||
} else {
|
||||
op.updateStatus(azdata.TaskStatus.Failed, result.errorMessage);
|
||||
if (result.outputNotebook) {
|
||||
const viewErrorDetail = localize('resourceDeployment.ViewErrorDetail', "View error detail");
|
||||
const taskFailedMessage = localize('resourceDeployment.BackgroundExecutionFailed', "The task \"{0}\" has failed.", taskName);
|
||||
const selectedOption = await vscode.window.showErrorMessage(taskFailedMessage, viewErrorDetail);
|
||||
const taskFailedMessage = loc.backgroundExecutionFailed(taskName);
|
||||
const selectedOption = await vscode.window.showErrorMessage(taskFailedMessage, loc.viewErrorDetail);
|
||||
platformService.logToOutputChannel(taskFailedMessage);
|
||||
if (selectedOption === viewErrorDetail) {
|
||||
if (selectedOption === loc.viewErrorDetail) {
|
||||
try {
|
||||
await this.openNotebookWithContent(`${tempNotebookPrefix}-${getDateTimeString()}`, result.outputNotebook);
|
||||
} catch (error) {
|
||||
const openNotebookError = localize('resourceDeployment.FailedToOpenNotebook', "An error occurred opening the output notebook. {1}{2}.", EOL, getErrorMessage(error));
|
||||
const openNotebookError = loc.failedToOpenNotebook(error);
|
||||
platformService.logToOutputChannel(openNotebookError);
|
||||
vscode.window.showErrorMessage(openNotebookError);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const errorMessage = localize('resourceDeployment.TaskFailedWithNoOutputNotebook', "The task \"{0}\" failed and no output Notebook was generated.", taskName);
|
||||
const errorMessage = loc.taskFailedWithNoOutputNotebook(taskName);
|
||||
platformService.logToOutputChannel(errorMessage);
|
||||
vscode.window.showErrorMessage(errorMessage);
|
||||
}
|
||||
@@ -192,7 +192,7 @@ export class NotebookService implements INotebookService {
|
||||
*/
|
||||
getNotebookPath(notebook: string | NotebookPathInfo): string {
|
||||
let notebookPath;
|
||||
if (notebook && !isString(notebook)) {
|
||||
if (notebook && (typeof notebook !== 'string')) {
|
||||
const platform = this.platformService.platform();
|
||||
if (platform === 'win32') {
|
||||
notebookPath = notebook.win32;
|
||||
|
||||
@@ -3,38 +3,64 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as azdata from 'azdata';
|
||||
import 'mocha';
|
||||
import { NotebookService } from '../../services/notebookService';
|
||||
import assert = require('assert');
|
||||
import * as path from 'path';
|
||||
import * as should from 'should';
|
||||
import * as sinon from 'sinon';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as vscode from 'vscode';
|
||||
import { NotebookPathInfo } from '../../interfaces';
|
||||
import { Notebook, NotebookService } from '../../services/notebookService';
|
||||
import { IPlatformService } from '../../services/platformService';
|
||||
import * as loc from '../../localizedConstants';
|
||||
import assert = require('assert');
|
||||
import { Deferred } from '../utils';
|
||||
|
||||
describe('Notebook Service Tests', function (): void {
|
||||
describe('NotebookService', function (): void {
|
||||
const notebookInput = 'test-notebook.ipynb';
|
||||
const sourceNotebookContent = '{ "cells": [] }';
|
||||
const notebookFileName = 'mynotebook.ipynb';
|
||||
const expectedTargetFileName = 'mynotebook';
|
||||
const extensionPath = path.resolve(__dirname, '..', '..', '..');
|
||||
const sourceNotebookRelativePath = `./notebooks/${notebookFileName}`;
|
||||
const sourceNotebookAbsolutePath = path.resolve(extensionPath, sourceNotebookRelativePath);
|
||||
const notebookWin32 = 'test-notebook-win32.ipynb';
|
||||
const notebookDarwin = 'test-notebook-darwin.ipynb';
|
||||
const notebookLinux = 'test-notebook-linux.ipynb';
|
||||
const storagePath = __dirname;
|
||||
let mockPlatformService: TypeMoq.IMock<IPlatformService>, notebookService: NotebookService;
|
||||
|
||||
it('getNotebook with string parameter', () => {
|
||||
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
|
||||
const notebookService = new NotebookService(mockPlatformService.object, '');
|
||||
const notebookInput = 'test-notebook.ipynb';
|
||||
beforeEach('NotebookService Setup', () => {
|
||||
mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
|
||||
notebookService = new NotebookService(mockPlatformService.object, extensionPath);
|
||||
});
|
||||
|
||||
afterEach('NotebookService cleanup', () => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('getNotebook with string parameter', async () => {
|
||||
mockPlatformService.setup(x => x.fileExists(notebookInput)).returns(async () => true);
|
||||
mockPlatformService.setup(x => x.readTextFile(notebookInput)).returns(async () => sourceNotebookContent);
|
||||
let returnValue = await notebookService.getNotebook(notebookInput);
|
||||
returnValue.should.deepEqual(JSON.parse(sourceNotebookContent), 'returned notebook does not match expected value');
|
||||
});
|
||||
|
||||
it('getNotebookPath with string parameter', () => {
|
||||
mockPlatformService.setup((service) => service.platform()).returns(() => { return 'win32'; });
|
||||
let returnValue = notebookService.getNotebookPath(notebookInput);
|
||||
assert.equal(returnValue, notebookInput, 'returned notebook name does not match expected value');
|
||||
returnValue.should.equal(notebookInput, 'returned notebook name does not match expected value');
|
||||
mockPlatformService.verify((service) => service.platform(), TypeMoq.Times.never());
|
||||
|
||||
mockPlatformService.reset();
|
||||
mockPlatformService.setup((service) => service.platform()).returns(() => { return 'win32'; });
|
||||
returnValue = notebookService.getNotebookPath('');
|
||||
assert.equal(returnValue, '', 'returned notebook name does not match expected value is not an empty string');
|
||||
returnValue.should.equal('', 'returned notebook name does not match expected value is not an empty string');
|
||||
mockPlatformService.verify((service) => service.platform(), TypeMoq.Times.never());
|
||||
});
|
||||
|
||||
it('getNotebook with NotebookInfo parameter', () => {
|
||||
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
|
||||
const notebookService = new NotebookService(mockPlatformService.object, '');
|
||||
const notebookWin32 = 'test-notebook-win32.ipynb';
|
||||
const notebookDarwin = 'test-notebook-darwin.ipynb';
|
||||
const notebookLinux = 'test-notebook-linux.ipynb';
|
||||
|
||||
const notebookInput: NotebookPathInfo = {
|
||||
darwin: notebookDarwin,
|
||||
win32: notebookWin32,
|
||||
@@ -42,43 +68,32 @@ describe('Notebook Service Tests', function (): void {
|
||||
};
|
||||
mockPlatformService.setup((service) => service.platform()).returns(() => { return 'win32'; });
|
||||
let returnValue = notebookService.getNotebookPath(notebookInput);
|
||||
assert.equal(returnValue, notebookWin32, 'returned notebook name does not match expected value for win32 platform');
|
||||
returnValue.should.equal(notebookWin32, 'returned notebook name does not match expected value for win32 platform');
|
||||
mockPlatformService.verify((service) => service.platform(), TypeMoq.Times.once());
|
||||
|
||||
mockPlatformService.reset();
|
||||
mockPlatformService.setup((service) => service.platform()).returns(() => { return 'darwin'; });
|
||||
returnValue = notebookService.getNotebookPath(notebookInput);
|
||||
assert.equal(returnValue, notebookDarwin, 'returned notebook name does not match expected value for darwin platform');
|
||||
returnValue.should.equal(notebookDarwin, 'returned notebook name does not match expected value for darwin platform');
|
||||
mockPlatformService.verify((service) => service.platform(), TypeMoq.Times.once());
|
||||
|
||||
mockPlatformService.reset();
|
||||
mockPlatformService.setup((service) => service.platform()).returns(() => { return 'linux'; });
|
||||
returnValue = notebookService.getNotebookPath(notebookInput);
|
||||
assert.equal(returnValue, notebookLinux, 'returned notebook name does not match expected value for linux platform');
|
||||
returnValue.should.equal(notebookLinux, 'returned notebook name does not match expected value for linux platform');
|
||||
mockPlatformService.verify((service) => service.platform(), TypeMoq.Times.once());
|
||||
});
|
||||
|
||||
it('findNextUntitledEditorName with no name conflict', () => {
|
||||
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
|
||||
const notebookService = new NotebookService(mockPlatformService.object, '');
|
||||
const notebookFileName = 'mynotebook.ipynb';
|
||||
const sourceNotebookPath = `./notebooks/${notebookFileName}`;
|
||||
|
||||
const expectedTargetFile = 'mynotebook';
|
||||
mockPlatformService.setup((service) => service.isNotebookNameUsed(TypeMoq.It.isAnyString()))
|
||||
.returns((path) => { return false; });
|
||||
const actualFileName = notebookService.findNextUntitledEditorName(sourceNotebookPath);
|
||||
const actualFileName = notebookService.findNextUntitledEditorName(sourceNotebookRelativePath);
|
||||
mockPlatformService.verify((service) => service.isNotebookNameUsed(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
||||
assert.equal(actualFileName, expectedTargetFile, 'target file name is not correct');
|
||||
actualFileName.should.equal(expectedTargetFileName, 'target file name is not correct');
|
||||
});
|
||||
|
||||
it('findNextUntitledEditorName with name conflicts', () => {
|
||||
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
|
||||
const notebookService = new NotebookService(mockPlatformService.object, '');
|
||||
const notebookFileName = 'mynotebook.ipynb';
|
||||
const sourceNotebookPath = `./notebooks/${notebookFileName}`;
|
||||
const expectedFileName = 'mynotebook-2';
|
||||
|
||||
const expected1stAttemptTargetFile = 'mynotebook';
|
||||
const expected2ndAttemptTargetFile = 'mynotebook-1';
|
||||
mockPlatformService.setup((service) => service.isNotebookNameUsed(TypeMoq.It.isAnyString()))
|
||||
@@ -90,8 +105,177 @@ describe('Notebook Service Tests', function (): void {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
const actualFileName = notebookService.findNextUntitledEditorName(sourceNotebookPath);
|
||||
const actualFileName = notebookService.findNextUntitledEditorName(sourceNotebookRelativePath);
|
||||
mockPlatformService.verify((service) => service.isNotebookNameUsed(TypeMoq.It.isAnyString()), TypeMoq.Times.exactly(3));
|
||||
assert.equal(actualFileName, expectedFileName, 'target file name is not correct');
|
||||
assert.strictEqual(actualFileName, expectedFileName, 'target file name is not correct');
|
||||
});
|
||||
|
||||
it('showNotebookAsUntitled', async () => {
|
||||
const { showNotebookStub } = showNotebookSetup(sourceNotebookContent);
|
||||
await notebookService.showNotebookAsUntitled(sourceNotebookRelativePath);
|
||||
showNotebookVerify(showNotebookStub, expectedTargetFileName, sourceNotebookContent);
|
||||
});
|
||||
|
||||
describe('openNotebook', () => {
|
||||
beforeEach('openNotebook setup', () => {
|
||||
mockPlatformService.setup(x => x.fileExists(sourceNotebookAbsolutePath)).returns(async () => true); // fileExists returns true when called with sourceNotebookAbsolutePath
|
||||
mockPlatformService.setup(x => x.fileExists(TypeMoq.It.isAnyString())).returns(async () => false); // fileExists returns false when called with any other string
|
||||
});
|
||||
[sourceNotebookRelativePath, sourceNotebookAbsolutePath].forEach((notebookPath) => {
|
||||
it(`notebookPath: ${notebookPath}`, async () => {
|
||||
const { showNotebookStub } = showNotebookSetup(sourceNotebookContent);
|
||||
await notebookService.openNotebook(notebookPath);
|
||||
showNotebookVerify(showNotebookStub, expectedTargetFileName, sourceNotebookContent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('openNotebookWithEdits', async () => {
|
||||
mockPlatformService.setup(x => x.fileExists(sourceNotebookAbsolutePath)).returns(async () => true); // fileExists returns true when called with sourceNotebookAbsolutePath
|
||||
const editorBuilder = <azdata.nb.NotebookEditorEdit>{
|
||||
insertCell(value: azdata.nb.ICellContents, index?: number, collapsed?: boolean): void { }
|
||||
};
|
||||
const editorBuilderStub = sinon.stub(editorBuilder, 'insertCell').returns();
|
||||
const { showNotebookStub, notebookEditorStub } = showNotebookSetup(sourceNotebookContent, editorBuilder);
|
||||
const cellStatements: string[] = [];
|
||||
await notebookService.openNotebookWithEdits(sourceNotebookAbsolutePath, cellStatements);
|
||||
notebookEditorStub.callCount.should.equal(1);
|
||||
editorBuilderStub.callCount.should.equal(1);
|
||||
const valueInserted = editorBuilderStub.getCall(0).args[0];
|
||||
valueInserted.cell_type.should.equal('code');
|
||||
valueInserted.source.should.equal(cellStatements);
|
||||
const insertionPosition = editorBuilderStub.getCall(0).args[1];
|
||||
should(insertionPosition).be.equal(0, 'default insertion point should be 0');
|
||||
showNotebookVerify(showNotebookStub, expectedTargetFileName, sourceNotebookContent);
|
||||
});
|
||||
|
||||
it('openNotebookWithContent', async () => {
|
||||
const title = 'title';
|
||||
const { showNotebookStub } = showNotebookSetup(sourceNotebookContent);
|
||||
await notebookService.openNotebookWithContent(title, sourceNotebookContent);
|
||||
showNotebookVerify(showNotebookStub, undefined, sourceNotebookContent);
|
||||
});
|
||||
|
||||
describe('executeNotebook', () => {
|
||||
it('success', async () => {
|
||||
executeNotebookSetup({ mockPlatformService, storagePath });
|
||||
const result = await notebookService.executeNotebook(<Notebook>{}, process.env);
|
||||
result.succeeded.should.be.true();
|
||||
});
|
||||
it('fails', async () => {
|
||||
const errorMessage = 'errorMessage';
|
||||
executeNotebookSetup({ mockPlatformService, storagePath, errorMessage, sourceNotebookContent });
|
||||
const result = await notebookService.executeNotebook(<Notebook>{}, process.env);
|
||||
result.succeeded.should.be.false('executeNotebook should return an object with succeeded set to false when an error occurs during execution');
|
||||
result.outputNotebook!.should.equal(sourceNotebookContent);
|
||||
result.errorMessage!.should.equal(errorMessage);
|
||||
});
|
||||
});
|
||||
|
||||
describe('backgroundExecuteNotebook', () => {
|
||||
const taskName = 'taskName';
|
||||
const deferred = new Deferred<void>();
|
||||
it('success', async () => {
|
||||
executeNotebookSetup({ mockPlatformService, storagePath, deferred });
|
||||
const stub = sinon.stub(azdata.tasks, 'startBackgroundOperation').callThrough();
|
||||
notebookService.backgroundExecuteNotebook(taskName, <Notebook>{ cells: [] }, 'deploy'/*tempNotebookPrefix*/, mockPlatformService.object, process.env);
|
||||
verifyBackgroundExecuteNotebookKickoff(stub, taskName);
|
||||
await deferred.promise;
|
||||
});
|
||||
[true, false].forEach(outputProduced => {
|
||||
it(`fails, with outputGenerated = ${outputProduced}`, async () => {
|
||||
const deferred = new Deferred<void>();
|
||||
const errorMessage = 'errorMessage';
|
||||
executeNotebookSetup({ mockPlatformService, storagePath, errorMessage, sourceNotebookContent: outputProduced ? sourceNotebookContent : '' });
|
||||
const stub = sinon.stub(azdata.tasks, 'startBackgroundOperation').callThrough();
|
||||
sinon.stub(azdata.nb, 'showNotebookDocument').rejects(new Error(errorMessage));
|
||||
sinon.stub(vscode.window, 'showErrorMessage').callsFake(async (message, ...items) => {
|
||||
if (outputProduced) {
|
||||
if (items?.length === 1) {
|
||||
message.should.equal(loc.backgroundExecutionFailed(taskName));
|
||||
return <any>loc.viewErrorDetail;
|
||||
} else {
|
||||
message.should.equal(loc.failedToOpenNotebook(errorMessage));
|
||||
deferred.resolve();
|
||||
}
|
||||
} else {
|
||||
message.should.equal(loc.taskFailedWithNoOutputNotebook(taskName));
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
notebookService.backgroundExecuteNotebook(taskName, <Notebook>{ cells: [] }, 'deploy'/*tempNotebookPrefix*/, mockPlatformService.object, process.env);
|
||||
verifyBackgroundExecuteNotebookKickoff(stub, taskName);
|
||||
await deferred.promise;
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
function verifyBackgroundExecuteNotebookKickoff(stub: sinon.SinonStub, taskName: string) {
|
||||
const operationInfo = <azdata.BackgroundOperationInfo>stub.getCall(0).args[0];
|
||||
stub.callCount.should.equal(1);
|
||||
operationInfo.displayName.should.equal(taskName);
|
||||
operationInfo.description.should.equal(taskName);
|
||||
should(operationInfo.operation).not.be.undefined();
|
||||
operationInfo.isCancelable.should.be.false();
|
||||
}
|
||||
|
||||
function executeNotebookSetup({ mockPlatformService, storagePath, deferred, errorMessage, sourceNotebookContent }: { mockPlatformService: TypeMoq.IMock<IPlatformService>; storagePath: string; deferred?: Deferred<void>, errorMessage?: string; sourceNotebookContent?: string; }) {
|
||||
mockPlatformService.setup(x => x.storagePath()).returns(() => storagePath);
|
||||
mockPlatformService.setup(x => x.saveTextFile(TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString()));
|
||||
if (errorMessage) {
|
||||
mockPlatformService.setup(x => x.runCommand(
|
||||
TypeMoq.It.is((s: string) => s.startsWith('azdata notebook run')),
|
||||
TypeMoq.It.isAny()
|
||||
)).throws(new Error(errorMessage));
|
||||
} else {
|
||||
mockPlatformService.setup(x => x.runCommand(
|
||||
TypeMoq.It.is((s: string) => s.startsWith('azdata notebook run')),
|
||||
TypeMoq.It.isAny()
|
||||
)).callback(async () => {
|
||||
if (deferred) {
|
||||
deferred.resolve();
|
||||
}
|
||||
return 'success';
|
||||
});
|
||||
}
|
||||
mockPlatformService.setup(x => x.deleteFile(TypeMoq.It.is((s: string) => path.dirname(s) === storagePath && path.basename(s).startsWith('nb-'))))
|
||||
.returns(async () => { }); // match deletion of executed notebookPath
|
||||
mockPlatformService.setup(x => x.deleteFile(TypeMoq.It.is((s: string) => path.dirname(s) === storagePath && path.basename(s).startsWith('output-nb-'))))
|
||||
.returns(async () => { }); // match deletion of output of executed notebookPath
|
||||
if (errorMessage) {
|
||||
mockPlatformService.setup(x => x.fileExists(TypeMoq.It.is((s: string) => path.dirname(s) === storagePath && path.basename(s).startsWith('output-nb-'))))
|
||||
.returns(async () => true);
|
||||
mockPlatformService.setup(x => x.readTextFile(TypeMoq.It.is((s: string) => path.dirname(s) === storagePath && path.basename(s).startsWith('output-nb-'))))
|
||||
.returns(async () => sourceNotebookContent!);
|
||||
}
|
||||
}
|
||||
|
||||
function showNotebookVerify(stub: sinon.SinonStub, expectedTargetFileName: string | undefined, sourceNotebookContent: string) {
|
||||
stub.callCount.should.equal(1);
|
||||
const untitledFileName = stub.getCall(0).args[0]!;
|
||||
untitledFileName.scheme.should.equal('untitled');
|
||||
if (expectedTargetFileName) {
|
||||
untitledFileName.path.should.equal(expectedTargetFileName);
|
||||
}
|
||||
const options = stub.getCall(0).args[1]!;
|
||||
options.initialContent!.should.equal(sourceNotebookContent);
|
||||
}
|
||||
|
||||
function showNotebookSetup(sourceNotebookContent: string, editorBuilder?: azdata.nb.NotebookEditorEdit) {
|
||||
sinon.stub(vscode.workspace, 'openTextDocument').resolves(<vscode.TextDocument>{ getText: () => sourceNotebookContent });
|
||||
const nbEditor = <azdata.nb.NotebookEditor>{
|
||||
edit(callback: (editBuilder: azdata.nb.NotebookEditorEdit) => void, options?: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable<boolean> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
};
|
||||
const notebookEditorStub = sinon.stub(nbEditor, 'edit').callsFake(async callback => {
|
||||
if (editorBuilder) {
|
||||
callback(editorBuilder);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const showNotebookStub = sinon.stub(azdata.nb, 'showNotebookDocument').resolves(nbEditor);
|
||||
return { showNotebookStub, notebookEditorStub };
|
||||
}
|
||||
|
||||
105
extensions/resource-deployment/src/test/stubs.ts
Normal file
105
extensions/resource-deployment/src/test/stubs.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as events from 'events';
|
||||
import * as cp from 'promisify-child-process';
|
||||
import { Readable } from 'stream';
|
||||
|
||||
export class TestChildProcessPromise<T> implements cp.ChildProcessPromise {
|
||||
private _promise: Promise<T>;
|
||||
private _event: events.EventEmitter = new events.EventEmitter();
|
||||
|
||||
constructor() {
|
||||
this._promise = new Promise<T>((resolve, reject) => {
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
});
|
||||
}
|
||||
resolve!: (value?: T | PromiseLike<T>) => void;
|
||||
reject!: (reason?: any) => void;
|
||||
then<TResult1 = T, TResult2 = never>(onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2> {
|
||||
return this._promise.then(onFulfilled, onRejected);
|
||||
}
|
||||
catch<TResult = never>(onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<T | TResult> {
|
||||
return this._promise.catch(onRejected);
|
||||
}
|
||||
[Symbol.toStringTag]: string;
|
||||
finally(onFinally?: (() => void) | null): Promise<T> {
|
||||
return this._promise.finally(onFinally);
|
||||
}
|
||||
stdin: any = this._event;
|
||||
stdout: Readable | null = <Readable>this._event;
|
||||
stderr: Readable | null = <Readable>this._event;
|
||||
channel?: any;
|
||||
stdio: [any, Readable | null, Readable | null, any, any] = [this.stdin, this.stdout, this.stderr, undefined, undefined];
|
||||
killed: boolean = false;
|
||||
pid: number = -1;
|
||||
connected: boolean = false;
|
||||
kill(signal?: number | 'SIGABRT' | 'SIGALRM' | 'SIGBUS' | 'SIGCHLD' | 'SIGCONT' | 'SIGFPE' | 'SIGHUP' | 'SIGILL' | 'SIGINT' | 'SIGIO' | 'SIGIOT' | 'SIGKILL' | 'SIGPIPE' | 'SIGPOLL' | 'SIGPROF' | 'SIGPWR' | 'SIGQUIT' | 'SIGSEGV' | 'SIGSTKFLT' | 'SIGSTOP' | 'SIGSYS' | 'SIGTERM' | 'SIGTRAP' | 'SIGTSTP' | 'SIGTTIN' | 'SIGTTOU' | 'SIGUNUSED' | 'SIGURG' | 'SIGUSR1' | 'SIGUSR2' | 'SIGVTALRM' | 'SIGWINCH' | 'SIGXCPU' | 'SIGXFSZ' | 'SIGBREAK' | 'SIGLOST' | 'SIGINFO'): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
send(message: any, callback?: (error: Error | null) => void): boolean;
|
||||
send(message: any, sendHandle?: any, callback?: (error: Error | null) => void): boolean;
|
||||
send(message: any, sendHandle?: any, options?: any, callback?: (error: Error | null) => void): boolean;
|
||||
send(message: any, sendHandle?: any, options?: any, callback?: any): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
disconnect(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
unref(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
ref(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
addListener(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
on(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
this._event.on(event, listener);
|
||||
return this;
|
||||
}
|
||||
once(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
prependListener(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
removeListener(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
off(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
removeAllListeners(event?: string | symbol): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
setMaxListeners(n: number): this {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getMaxListeners(): number {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
listeners(event: string | symbol): Function[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
rawListeners(event: string | symbol): Function[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
emit(event: string | symbol, ...args: any[]): boolean {
|
||||
return this._event.emit(event, args);
|
||||
}
|
||||
eventNames(): (string | symbol)[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
listenerCount(type: string | symbol): number {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
13
extensions/resource-deployment/src/test/utils.ts
Normal file
13
extensions/resource-deployment/src/test/utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export class Deferred<T> {
|
||||
promise: Promise<T> = new Promise<T>((resolve, reject) => {
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
});;
|
||||
resolve!: (value?: T | PromiseLike<T>) => void;
|
||||
reject!: (reason?: any) => void;
|
||||
}
|
||||
Reference in New Issue
Block a user