mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Add simple notebook smoke test (#12898)
* add simple notebook smoke test * add id for notebook dropdown elements
This commit is contained in:
@@ -350,6 +350,7 @@ export class SelectBox extends vsSelectBox {
|
||||
|
||||
super.render(selectContainer);
|
||||
this.selectElement.classList.add('action-item-label');
|
||||
this.selectElement.id = selectOptions.id;
|
||||
}
|
||||
else {
|
||||
super.render(container);
|
||||
@@ -364,4 +365,5 @@ export class SelectBox extends vsSelectBox {
|
||||
export interface ISelectBoxOptionsWithLabel extends ISelectBoxOptions {
|
||||
labelText?: string;
|
||||
labelOnTop?: boolean;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
@@ -275,12 +275,13 @@ export class CollapseCellsAction extends ToggleableAction {
|
||||
const showAllKernelsConfigName = 'notebook.showAllKernels';
|
||||
const workbenchPreviewConfigName = 'workbench.enablePreviewFeatures';
|
||||
export const noKernelName = localize('noKernel', "No Kernel");
|
||||
const kernelDropdownElementId = 'kernel-dropdown';
|
||||
|
||||
export class KernelsDropdown extends SelectBox {
|
||||
private model: NotebookModel;
|
||||
private _showAllKernels: boolean = false;
|
||||
constructor(container: HTMLElement, contextViewProvider: IContextViewProvider, modelReady: Promise<INotebookModel>, @IConfigurationService private _configurationService: IConfigurationService) {
|
||||
super([msgLoading], msgLoading, contextViewProvider, container, { labelText: kernelLabel, labelOnTop: false, ariaLabel: kernelLabel } as ISelectBoxOptionsWithLabel);
|
||||
super([msgLoading], msgLoading, contextViewProvider, container, { labelText: kernelLabel, labelOnTop: false, ariaLabel: kernelLabel, id: kernelDropdownElementId } as ISelectBoxOptionsWithLabel);
|
||||
|
||||
if (modelReady) {
|
||||
modelReady
|
||||
@@ -353,6 +354,8 @@ export class KernelsDropdown extends SelectBox {
|
||||
}
|
||||
}
|
||||
|
||||
const attachToDropdownElementId = 'attach-to-dropdown';
|
||||
|
||||
export class AttachToDropdown extends SelectBox {
|
||||
private model: NotebookModel;
|
||||
|
||||
@@ -363,7 +366,7 @@ export class AttachToDropdown extends SelectBox {
|
||||
@INotificationService private _notificationService: INotificationService,
|
||||
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
|
||||
) {
|
||||
super([msgLoadingContexts], msgLoadingContexts, contextViewProvider, container, { labelText: attachToLabel, labelOnTop: false, ariaLabel: attachToLabel } as ISelectBoxOptionsWithLabel);
|
||||
super([msgLoadingContexts], msgLoadingContexts, contextViewProvider, container, { labelText: attachToLabel, labelOnTop: false, ariaLabel: attachToLabel, id: attachToDropdownElementId } as ISelectBoxOptionsWithLabel);
|
||||
if (modelReady) {
|
||||
modelReady
|
||||
.then(model => {
|
||||
|
||||
39
test/automation/src/sql/configurePythonDialog.ts
Normal file
39
test/automation/src/sql/configurePythonDialog.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Code } from '../code';
|
||||
import { Dialog } from './dialog';
|
||||
|
||||
const CONFIGURE_PYTHON_DIALOG_TITLE = 'Configure Python to run Python 3 kernel';
|
||||
|
||||
export class ConfigurePythonDialog extends Dialog {
|
||||
|
||||
constructor(code: Code) {
|
||||
super(CONFIGURE_PYTHON_DIALOG_TITLE, code);
|
||||
}
|
||||
|
||||
async waitForConfigurePythonDialog(): Promise<void> {
|
||||
await this.waitForNewDialog();
|
||||
}
|
||||
|
||||
async installPython(): Promise<void> {
|
||||
const dialog = '.modal .modal-dialog';
|
||||
await this.code.waitAndClick(dialog);
|
||||
|
||||
const newPythonInstallation = '.modal .modal-body input[aria-label="New Python installation"]';
|
||||
await this.code.waitAndClick(newPythonInstallation);
|
||||
|
||||
const nextButton = '.modal-dialog .modal-content .modal-footer .right-footer .footer-button a[aria-label="Next"][aria-disabled="false"]';
|
||||
await this.code.waitForElement(nextButton);
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
|
||||
const installButton = '.modal-dialog .modal-content .modal-footer .right-footer .footer-button a[aria-label="Install"][aria-disabled="false"]';
|
||||
await this.code.waitForElement(installButton);
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
|
||||
return this.waitForDialogGone();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,17 +8,82 @@ import { QuickAccess } from '../quickaccess';
|
||||
import { QuickInput } from '../quickinput';
|
||||
import { Editors } from '../editors';
|
||||
|
||||
const winOrCtrl = process.platform === 'darwin' ? 'ctrl' : 'win';
|
||||
|
||||
export class Notebook {
|
||||
|
||||
public readonly toolbar: NotebookToolbar;
|
||||
|
||||
constructor(private code: Code, private quickAccess: QuickAccess, private quickInput: QuickInput, private editors: Editors) {
|
||||
this.toolbar = new NotebookToolbar(code);
|
||||
}
|
||||
|
||||
async openFile(fileName: string): Promise<void> {
|
||||
await this.quickAccess.openQuickAccess(fileName);
|
||||
|
||||
await this.quickInput.waitForQuickInputElements(names => names[0] === fileName);
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
await this.editors.waitForActiveTab(fileName);
|
||||
await this.code.waitForElement('.notebookEditor');
|
||||
}
|
||||
|
||||
async newUntitledNotebook(): Promise<void> {
|
||||
await this.code.dispatchKeybinding(winOrCtrl + '+alt+n');
|
||||
await this.editors.waitForActiveTab('Notebook-0');
|
||||
await this.code.waitForElement('.notebookEditor');
|
||||
}
|
||||
|
||||
async addCell(cellType: 'markdown' | 'code'): Promise<void> {
|
||||
if (cellType === 'markdown') {
|
||||
await this.code.dispatchKeybinding(winOrCtrl + '+shift+t');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding(winOrCtrl + '+shift+c');
|
||||
}
|
||||
|
||||
await this.code.waitForElement('.notebook-cell.active');
|
||||
}
|
||||
|
||||
async changeKernel(kernel: string): Promise<void> {
|
||||
await this.toolbar.changeKernel(kernel);
|
||||
}
|
||||
|
||||
async runActiveCell(): Promise<void> {
|
||||
await this.code.dispatchKeybinding('F5');
|
||||
}
|
||||
|
||||
async runAllCells(): Promise<void> {
|
||||
await this.code.dispatchKeybinding(winOrCtrl + '+shift+F5');
|
||||
}
|
||||
|
||||
async waitForTypeInEditor(text: string) {
|
||||
const editor = '.notebook-cell.active .monaco-editor';
|
||||
await this.code.waitAndClick(editor);
|
||||
|
||||
const textarea = `${editor} textarea`;
|
||||
await this.code.waitForActiveElement(textarea);
|
||||
|
||||
await this.code.waitForTypeInEditor(textarea, text);
|
||||
await this._waitForActiveCellEditorContents(c => c.indexOf(text) > -1);
|
||||
}
|
||||
|
||||
private async _waitForActiveCellEditorContents(accept: (contents: string) => boolean): Promise<any> {
|
||||
const selector = '.notebook-cell.active .monaco-editor .view-lines';
|
||||
return this.code.waitForTextContent(selector, undefined, c => accept(c.replace(/\u00a0/g, ' ')));
|
||||
}
|
||||
|
||||
async waitForResults(): Promise<void> {
|
||||
const outputComponent = '.notebook-cell.active .notebook-output';
|
||||
await this.code.waitForElement(outputComponent);
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookToolbar {
|
||||
|
||||
private static readonly toolbarSelector = '.notebookEditor .editor-toolbar .actions-container';
|
||||
constructor(private code: Code) { }
|
||||
|
||||
async changeKernel(kernel: string): Promise<void> {
|
||||
const kernelDropdown = `${NotebookToolbar.toolbarSelector} select[id="kernel-dropdown"]`;
|
||||
await this.code.waitForSetValue(kernelDropdown, kernel);
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import { Profiler } from './sql/profiler';
|
||||
import { QueryEditors } from './sql/queryEditors';
|
||||
import { QueryEditor } from './sql/queryEditor';
|
||||
import { Notebook as SqlNotebook } from './sql/notebook';
|
||||
import { ConfigurePythonDialog } from './sql/configurePythonDialog';
|
||||
// {{END}}
|
||||
|
||||
export interface Commands {
|
||||
@@ -57,7 +58,8 @@ export class Workbench {
|
||||
readonly profiler: Profiler;
|
||||
readonly queryEditors: QueryEditors;
|
||||
readonly queryEditor: QueryEditor;
|
||||
readonly sqlNotebbok: SqlNotebook;
|
||||
readonly sqlNotebook: SqlNotebook;
|
||||
readonly configurePythonDialog: ConfigurePythonDialog;
|
||||
// {{END}}
|
||||
|
||||
constructor(code: Code, userDataPath: string) {
|
||||
@@ -81,7 +83,8 @@ export class Workbench {
|
||||
this.profiler = new Profiler(code, this.quickaccess);
|
||||
this.queryEditors = new QueryEditors(code, this.editors);
|
||||
this.queryEditor = new QueryEditor(code);
|
||||
this.sqlNotebbok = new SqlNotebook(code, this.quickaccess, this.quickinput, this.editors);
|
||||
this.sqlNotebook = new SqlNotebook(code, this.quickaccess, this.quickinput, this.editors);
|
||||
this.configurePythonDialog = new ConfigurePythonDialog(code);
|
||||
// {{END}}
|
||||
this.notebook = new Notebook(this.quickaccess, code);
|
||||
}
|
||||
|
||||
@@ -7,9 +7,21 @@ import { Application } from '../../../../../automation';
|
||||
|
||||
export function setup() {
|
||||
describe('Notebook', () => {
|
||||
it('open ', async function () {
|
||||
|
||||
|
||||
it('can open new notebook, configure Python, and execute one cell', async function () {
|
||||
const app = this.app as Application;
|
||||
await app.workbench.sqlNotebbok.openFile('hello.ipynb');
|
||||
await app.workbench.sqlNotebook.newUntitledNotebook();
|
||||
await app.workbench.sqlNotebook.addCell('code');
|
||||
await app.workbench.sqlNotebook.waitForTypeInEditor('print("Hello world!")');
|
||||
|
||||
await app.workbench.sqlNotebook.changeKernel('Python 3');
|
||||
await app.workbench.configurePythonDialog.waitForConfigurePythonDialog();
|
||||
await app.workbench.configurePythonDialog.installPython();
|
||||
|
||||
await app.workbench.sqlNotebook.runActiveCell();
|
||||
await app.workbench.sqlNotebook.waitForResults();
|
||||
await app.workbench.quickaccess.runCommand('workbench.action.closeActiveEditor');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user