diff --git a/package.json b/package.json index 3612562aaa..521bd4bfde 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "azuredatastudio", "version": "1.30.0", - "distro": "ab16639070613df1c9772fe028786f44ff9096f3", + "distro": "da9346f4dbf9e6069dd59f3d5b2ee4dcc1a19b2a", "author": { "name": "Microsoft Corporation" }, diff --git a/test/automation/src/sql/createBookDialog.ts b/test/automation/src/sql/createBookDialog.ts new file mode 100644 index 0000000000..9655c2cc7d --- /dev/null +++ b/test/automation/src/sql/createBookDialog.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * 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 CREATE_BOOK_DIALOG_TITLE = 'New Jupyter Book (Preview)'; + +const NAME_INPUT_SELECTOR = '.modal .modal-body input[aria-label="Name. Please fill out this field."]'; +const LOCATION_INPUT_SELECTOR = '.modal .modal-body input[title="Browse locations..."]'; +const CONTENT_FOLDER_INPUT_SELECTOR = '.modal .modal-body input[title="Select content folder"]'; +const CREATE_BUTTON_SELECTOR = '.modal .modal-footer a[aria-label="Create"]:not(.disabled)'; + +export class CreateBookDialog extends Dialog { + + constructor(code: Code) { + super(CREATE_BOOK_DIALOG_TITLE, code); + } + + async waitForDialog(): Promise { + await this.waitForNewDialog(); + } + + public async setName(name: string): Promise { + await this.code.waitForSetValue(NAME_INPUT_SELECTOR, name); + } + + public async setLocation(location: string): Promise { + await this.code.waitForSetValue(LOCATION_INPUT_SELECTOR, location); + } + + public async setContentFolder(contentFolder: string): Promise { + await this.code.waitForSetValue(CONTENT_FOLDER_INPUT_SELECTOR, contentFolder); + } + + async create(): Promise { + await this.code.waitAndClick(CREATE_BUTTON_SELECTOR); + + await this.waitForDialogGone(); + } +} diff --git a/test/automation/src/workbench.ts b/test/automation/src/workbench.ts index e05c44509c..8cdc77555a 100644 --- a/test/automation/src/workbench.ts +++ b/test/automation/src/workbench.ts @@ -28,6 +28,7 @@ import { QueryEditors } from './sql/queryEditors'; import { QueryEditor } from './sql/queryEditor'; import { Notebook as SqlNotebook } from './sql/notebook'; import { ConfigurePythonDialog } from './sql/configurePythonDialog'; +import { CreateBookDialog } from './sql/createBookDialog'; import { NotificationToast } from './sql/notificationToast'; // {{END}} @@ -60,6 +61,7 @@ export class Workbench { readonly queryEditors: QueryEditors; readonly queryEditor: QueryEditor; readonly sqlNotebook: SqlNotebook; + readonly createBookDialog: CreateBookDialog; readonly configurePythonDialog: ConfigurePythonDialog; readonly notificationToast: NotificationToast; // {{END}} @@ -87,6 +89,7 @@ export class Workbench { this.queryEditors = new QueryEditors(code, this.editors); this.queryEditor = new QueryEditor(code); this.sqlNotebook = new SqlNotebook(code, this.quickaccess, this.quickinput, this.editors); + this.createBookDialog = new CreateBookDialog(code); this.configurePythonDialog = new ConfigurePythonDialog(code); // {{END}} this.notebook = new Notebook(this.quickaccess, code); diff --git a/test/smoke/package.json b/test/smoke/package.json index cb37f8db32..ae235a0bac 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -17,6 +17,7 @@ "@types/ncp": "2.0.1", "@types/node": "^12.19.9", "@types/rimraf": "^2.0.4", + "@types/tmp": "0.0.33", "cpx": "^1.5.0", "htmlparser2": "^3.9.2", "mkdirp": "^0.5.1", diff --git a/test/smoke/src/sql/areas/notebook/createBook.test.ts b/test/smoke/src/sql/areas/notebook/createBook.test.ts new file mode 100644 index 0000000000..78b2ac91aa --- /dev/null +++ b/test/smoke/src/sql/areas/notebook/createBook.test.ts @@ -0,0 +1,45 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Application } from '../../../../../automation'; +import { promises as fs } from 'fs'; +import * as rimraf from 'rimraf'; +import * as path from 'path'; +import { assert } from 'console'; +import * as tmp from 'tmp'; + +export function setup() { + + const bookName = 'my-book'; + + describe('CreateBookDialog', () => { + + let tmpDir = ''; + it('can create new book with default content folder', async function () { + const app = this.app as Application; + // Add timeout for giving time for the SQL Tools Service to start (it'll error if it's not started yet) + // TODO @chgagnon - Figure out better way to have tests wait for STS + await new Promise(r => setTimeout(r, 10000)); + // eslint-disable-next-line no-sync + tmpDir = tmp.dirSync().name; + await app.workbench.quickaccess.runCommand('Jupyter Books: Create Jupyter Book'); + await app.workbench.createBookDialog.setName(bookName); + await app.workbench.createBookDialog.setLocation(tmpDir); + await app.workbench.createBookDialog.create(); + const bookExists = await fs.stat(path.join(tmpDir, 'my-book')); + assert(!!bookExists, 'Book was not created'); + }); + + afterEach(async function () { + if (tmpDir) { + try { + rimraf.sync(tmpDir); + } catch (err) { + // Try our best to clean up but don't fail the test if we can't + } + } + }); + }); +} diff --git a/test/smoke/src/sql/main.ts b/test/smoke/src/sql/main.ts index 51397cb6e6..3640e9ed4f 100644 --- a/test/smoke/src/sql/main.ts +++ b/test/smoke/src/sql/main.ts @@ -7,6 +7,7 @@ import { setup as setupQueryEditorTests, setupWeb as setupQueryEditorWebTests } import { setup as setupNotebookTests } from './areas/notebook/notebook.test'; import { setup as setupNotebookViewTests } from './areas/notebook/notebookView.test'; import { setup as setupImportTests } from './areas/import/import.test'; +import { setup as setupCreateBookDialogTests } from './areas/notebook/createBook.test'; import { ApplicationOptions } from '../../../automation'; import * as yazl from 'yauzl'; import * as fs from 'fs'; @@ -22,6 +23,7 @@ export function main(isWeb: boolean = false): void { } setupNotebookTests(); setupNotebookViewTests(); + setupCreateBookDialogTests(); setupImportTests(); } diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index aad5a2e729..3ab32f4b5b 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -63,6 +63,11 @@ "@types/glob" "*" "@types/node" "*" +"@types/tmp@0.0.33": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d" + integrity sha1-EHPEvIJHVK49EM+riKsCN7qWTk0= + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"