mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
First tests for notebook markdown transformer (#10072)
* First tests for markdown toolbar * Fix loader issues * PR Feedback
This commit is contained in:
@@ -46,8 +46,11 @@ export class TransformMarkdownAction extends Action {
|
|||||||
|
|
||||||
export class MarkdownTextTransformer {
|
export class MarkdownTextTransformer {
|
||||||
|
|
||||||
private _notebookEditor: INotebookEditor;
|
constructor(private _notebookService: INotebookService, private _cellModel: ICellModel, private _notebookEditor?: INotebookEditor) { }
|
||||||
constructor(private _notebookService: INotebookService, private _cellModel: ICellModel) { }
|
|
||||||
|
public get notebookEditor(): INotebookEditor {
|
||||||
|
return this._notebookEditor;
|
||||||
|
}
|
||||||
|
|
||||||
public transformText(type: MarkdownButtonType): void {
|
public transformText(type: MarkdownButtonType): void {
|
||||||
let editorControl = this.getEditorControl();
|
let editorControl = this.getEditorControl();
|
||||||
|
|||||||
@@ -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`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 { RenderMimeRegistry } from 'sql/workbench/services/notebook/browser/outputs/registry';
|
||||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor';
|
||||||
|
|
||||||
export class NotebookModelStub implements INotebookModel {
|
export class NotebookModelStub implements INotebookModel {
|
||||||
constructor(private _languageInfo?: nb.ILanguageInfo) {
|
constructor(private _languageInfo?: nb.ILanguageInfo) {
|
||||||
@@ -636,3 +637,63 @@ export class NodeStub implements Node {
|
|||||||
throw new Error('Method not implemented.');
|
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.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user