First tests for notebook markdown transformer (#10072)

* First tests for markdown toolbar

* Fix loader issues

* PR Feedback
This commit is contained in:
Chris LaFreniere
2020-04-23 21:24:15 -07:00
committed by GitHub
parent 6a02287dc6
commit 7633c810aa
4 changed files with 282 additions and 2 deletions

View File

@@ -46,8 +46,11 @@ export class TransformMarkdownAction extends Action {
export class MarkdownTextTransformer {
private _notebookEditor: INotebookEditor;
constructor(private _notebookService: INotebookService, private _cellModel: ICellModel) { }
constructor(private _notebookService: INotebookService, private _cellModel: ICellModel, private _notebookEditor?: INotebookEditor) { }
public get notebookEditor(): INotebookEditor {
return this._notebookEditor;
}
public transformText(type: MarkdownButtonType): void {
let editorControl = this.getEditorControl();

View File

@@ -0,0 +1,166 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as TypeMoq from 'typemoq';
import * as assert from 'assert';
import { MarkdownTextTransformer, MarkdownButtonType } from 'sql/workbench/contrib/notebook/browser/markdownToolbarActions';
import { NotebookService } from 'sql/workbench/services/notebook/browser/notebookServiceImpl';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { TestLifecycleService, TestEnvironmentService, TestAccessibilityService } from 'vs/workbench/test/browser/workbenchTestServices';
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { TextModel } from 'vs/editor/common/model/textModel';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { DefaultEndOfLine } from 'vs/editor/common/model';
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IEditor } from 'vs/editor/common/editorCommon';
import { TestNotebookEditor } from 'sql/workbench/contrib/notebook/test/browser/testEditorsAndProviders.test';
suite('MarkdownTextTransformer', () => {
let markdownTextTransformer: MarkdownTextTransformer;
let widget: IEditor;
let textModel: TextModel;
setup(() => {
let mockNotebookService: TypeMoq.Mock<INotebookService>;
const dialogService = new TestDialogService();
const notificationService = new TestNotificationService();
const undoRedoService = new UndoRedoService(dialogService, notificationService);
const instantiationService = new TestInstantiationService();
instantiationService.stub(IAccessibilityService, new TestAccessibilityService());
instantiationService.stub(IContextKeyService, new MockContextKeyService());
instantiationService.stub(ICodeEditorService, new TestCodeEditorService());
instantiationService.stub(IThemeService, new TestThemeService());
instantiationService.stub(IEnvironmentService, TestEnvironmentService);
instantiationService.stub(IStorageService, new TestStorageService());
mockNotebookService = TypeMoq.Mock.ofType(NotebookService, undefined, new TestLifecycleService(), undefined, undefined, undefined, instantiationService, new MockContextKeyService(),
undefined, undefined, undefined, undefined, undefined, undefined, TestEnvironmentService);
let cellModel = new CellModel(undefined, undefined, mockNotebookService.object);
let notebookEditor = new TestNotebookEditor(cellModel.cellGuid, instantiationService);
markdownTextTransformer = new MarkdownTextTransformer(mockNotebookService.object, cellModel, notebookEditor);
mockNotebookService.setup(s => s.findNotebookEditor(TypeMoq.It.isAny())).returns(() => notebookEditor);
let editor = notebookEditor.cellEditors[0].getEditor();
assert(!isUndefinedOrNull(editor), 'editor is undefined');
widget = editor.getControl();
assert(!isUndefinedOrNull(widget), 'widget is undefined');
// Create new text model
textModel = new TextModel('', { isForSimpleWidget: true, defaultEOL: DefaultEndOfLine.LF, detectIndentation: true, indentSize: 0, insertSpaces: false, largeFileOptimizations: false, tabSize: 4, trimAutoWhitespace: false }, null, undefined, undoRedoService);
// Couple widget with newly created text model
widget.setModel(textModel);
// let textModel = widget.getModel() as TextModel;
assert(!isUndefinedOrNull(widget.getModel()), 'Text model is undefined');
});
test('Transform text with no previous selection', () => {
testWithNoSelection(MarkdownButtonType.BOLD, '****', true);
testWithNoSelection(MarkdownButtonType.BOLD, '');
testWithNoSelection(MarkdownButtonType.ITALIC, '__', true);
testWithNoSelection(MarkdownButtonType.ITALIC, '');
// testWithNoSelection(MarkdownButtonType.CODE, '```\n\n```', true);
// testWithNoSelection(MarkdownButtonType.CODE, '\n');
testWithNoSelection(MarkdownButtonType.HIGHLIGHT, '<mark></mark>', true);
testWithNoSelection(MarkdownButtonType.HIGHLIGHT, '');
testWithNoSelection(MarkdownButtonType.LINK, '[]()', true);
testWithNoSelection(MarkdownButtonType.LINK, '');
testWithNoSelection(MarkdownButtonType.UNORDERED_LIST, '- ', true);
testWithNoSelection(MarkdownButtonType.UNORDERED_LIST, '- ');
testWithNoSelection(MarkdownButtonType.ORDERED_LIST, '1. ', true);
testWithNoSelection(MarkdownButtonType.ORDERED_LIST, '1. ');
testWithNoSelection(MarkdownButtonType.IMAGE, '![]()', true);
testWithNoSelection(MarkdownButtonType.IMAGE, '');
});
test('Transform text with one word selected', () => {
testWithSingleWordSelected(MarkdownButtonType.BOLD, '**WORD**');
testWithSingleWordSelected(MarkdownButtonType.ITALIC, '_WORD_');
testWithSingleWordSelected(MarkdownButtonType.CODE, '```\nWORD\n```');
testWithSingleWordSelected(MarkdownButtonType.HIGHLIGHT, '<mark>WORD</mark>');
testWithSingleWordSelected(MarkdownButtonType.LINK, '[WORD]()');
testWithSingleWordSelected(MarkdownButtonType.UNORDERED_LIST, '- WORD');
testWithSingleWordSelected(MarkdownButtonType.ORDERED_LIST, '1. WORD');
testWithSingleWordSelected(MarkdownButtonType.IMAGE, '![WORD]()');
});
test('Transform text with multiple words selected', () => {
testWithMultipleWordsSelected(MarkdownButtonType.BOLD, '**Multi Words**');
testWithMultipleWordsSelected(MarkdownButtonType.ITALIC, '_Multi Words_');
testWithMultipleWordsSelected(MarkdownButtonType.CODE, '```\nMulti Words\n```');
testWithMultipleWordsSelected(MarkdownButtonType.HIGHLIGHT, '<mark>Multi Words</mark>');
testWithMultipleWordsSelected(MarkdownButtonType.LINK, '[Multi Words]()');
testWithMultipleWordsSelected(MarkdownButtonType.UNORDERED_LIST, '- Multi Words');
testWithMultipleWordsSelected(MarkdownButtonType.ORDERED_LIST, '1. Multi Words');
testWithMultipleWordsSelected(MarkdownButtonType.IMAGE, '![Multi Words]()');
});
test('Transform text with multiple lines selected', () => {
testWithMultipleLinesSelected(MarkdownButtonType.BOLD, '**Multi\nLines\nSelected**');
testWithMultipleLinesSelected(MarkdownButtonType.ITALIC, '_Multi\nLines\nSelected_');
testWithMultipleLinesSelected(MarkdownButtonType.CODE, '```\nMulti\nLines\nSelected\n```');
testWithMultipleLinesSelected(MarkdownButtonType.HIGHLIGHT, '<mark>Multi\nLines\nSelected</mark>');
testWithMultipleLinesSelected(MarkdownButtonType.LINK, '[Multi\nLines\nSelected]()');
testWithMultipleLinesSelected(MarkdownButtonType.UNORDERED_LIST, '- Multi\n- Lines\n- Selected');
testWithMultipleLinesSelected(MarkdownButtonType.ORDERED_LIST, '1. Multi\n1. Lines\n1. Selected');
testWithMultipleLinesSelected(MarkdownButtonType.IMAGE, '![Multi\nLines\nSelected]()');
});
function testWithNoSelection(type: MarkdownButtonType, expectedValue: string, setValue = false): void {
if (setValue) {
textModel.setValue('');
}
markdownTextTransformer.transformText(type);
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with no selection failed`);
}
function testWithSingleWordSelected(type: MarkdownButtonType, expectedValue: string): void {
let value = 'WORD';
textModel.setValue(value);
widget.setSelection({ startColumn: 1, startLineNumber: 1, endColumn: 5, endLineNumber: 1 });
assert.equal(textModel.getValueInRange(widget.getSelection()), value, 'Expected selection is not found');
markdownTextTransformer.transformText(type);
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with single word selection failed`);
}
function testWithMultipleWordsSelected(type: MarkdownButtonType, expectedValue: string): void {
let value = 'Multi Words';
textModel.setValue(value);
widget.setSelection({ startColumn: 1, startLineNumber: 1, endColumn: 12, endLineNumber: 1 });
assert.equal(textModel.getValueInRange(widget.getSelection()), value, 'Expected multi-word selection is not found');
markdownTextTransformer.transformText(type);
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with multiple word selection failed`);
}
function testWithMultipleLinesSelected(type: MarkdownButtonType, expectedValue: string): void {
let value = 'Multi\nLines\nSelected';
textModel.setValue(value);
widget.setSelection({ startColumn: 1, startLineNumber: 1, endColumn: 9, endLineNumber: 3 });
assert.equal(textModel.getValueInRange(widget.getSelection()), value, 'Expected multi-line selection is not found');
markdownTextTransformer.transformText(type);
assert.equal(textModel.getValue(), expectedValue, `${MarkdownButtonType[type]} with multiple line selection failed`);
}
});

View File

@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NotebookEditorStub, CellEditorProviderStub } from 'sql/workbench/contrib/notebook/test/stubs';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestTextResourceConfigurationService, TestEditorGroupsService, TestEditorService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import * as dom from 'vs/base/browser/dom';
export class TestNotebookEditor extends NotebookEditorStub {
constructor(private _cellGuid?: string, private _instantiationService?: IInstantiationService) {
super();
}
cellEditors: CellEditorProviderStub[] = [new TestCellEditorProvider(this._cellGuid, this._instantiationService)];
}
class TestCellEditorProvider extends CellEditorProviderStub {
private _editor: QueryTextEditor;
private _cellGuid: string;
constructor(cellGuid: string, instantiationService?: IInstantiationService) {
super();
let div = dom.$('div', undefined, dom.$('span', { id: 'demospan' }));
let firstChild = div.firstChild as HTMLElement;
this._editor = new QueryTextEditor(
NullTelemetryService,
instantiationService,
new TestStorageService(),
new TestTextResourceConfigurationService(),
new TestThemeService(),
new TestEditorGroupsService(),
new TestEditorService(),
new TestConfigurationService()
);
this._editor.create(firstChild);
this._cellGuid = cellGuid;
}
cellGuid(): string {
return this._cellGuid;
}
getEditor(): QueryTextEditor {
return this._editor;
}
}

View File

@@ -16,6 +16,7 @@ import { NotebookFindMatch } from 'sql/workbench/contrib/notebook/browser/find/n
import { RenderMimeRegistry } from 'sql/workbench/services/notebook/browser/outputs/registry';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { URI } from 'vs/base/common/uri';
import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor';
export class NotebookModelStub implements INotebookModel {
constructor(private _languageInfo?: nb.ILanguageInfo) {
@@ -636,3 +637,63 @@ export class NodeStub implements Node {
throw new Error('Method not implemented.');
}
}
export class NotebookEditorStub implements INotebookEditor {
notebookParams: INotebookParams;
id: string;
cells?: ICellModel[];
cellEditors: CellEditorProviderStub[];
modelReady: Promise<INotebookModel>;
model: INotebookModel;
isDirty(): boolean {
throw new Error('Method not implemented.');
}
isActive(): boolean {
throw new Error('Method not implemented.');
}
isVisible(): boolean {
throw new Error('Method not implemented.');
}
executeEdits(edits: ISingleNotebookEditOperation[]): boolean {
throw new Error('Method not implemented.');
}
runCell(cell: ICellModel): Promise<boolean> {
throw new Error('Method not implemented.');
}
runAllCells(startCell?: ICellModel, endCell?: ICellModel): Promise<boolean> {
throw new Error('Method not implemented.');
}
clearOutput(cell: ICellModel): Promise<boolean> {
throw new Error('Method not implemented.');
}
clearAllOutputs(): Promise<boolean> {
throw new Error('Method not implemented.');
}
getSections(): INotebookSection[] {
throw new Error('Method not implemented.');
}
navigateToSection(sectionId: string): void {
throw new Error('Method not implemented.');
}
deltaDecorations(newDecorationRange: NotebookRange, oldDecorationRange: NotebookRange): void {
throw new Error('Method not implemented.');
}
addCell(cellType: CellType, index?: number, event?: UIEvent) {
throw new Error('Method not implemented.');
}
}
export class CellEditorProviderStub implements ICellEditorProvider {
hasEditor(): boolean {
throw new Error('Method not implemented.');
}
cellGuid(): string {
throw new Error('Method not implemented.');
}
getEditor(): QueryTextEditor {
throw new Error('Method not implemented.');
}
deltaDecorations(newDecorationRange: NotebookRange, oldDecorationRange: NotebookRange): void {
throw new Error('Method not implemented.');
}
}