From d9b889ff6de60c1213a674d0a15f6eff708ba414 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 6 Sep 2017 23:18:55 +0200 Subject: [PATCH] smoke test: adopt editor tests --- test/smoke/src/areas/common.ts | 211 -------------------- test/smoke/src/areas/css/css.test.ts | 16 +- test/smoke/src/areas/editor/editor.test.ts | 80 ++++++++ test/smoke/src/areas/editor/editor.ts | 109 +++++++++- test/smoke/src/areas/editor/peek.ts | 40 ++++ test/smoke/src/areas/editor/quickoutline.ts | 11 +- test/smoke/src/areas/editor/rename.ts | 25 +++ test/smoke/src/areas/first-experience.ts | 21 -- test/smoke/src/areas/javascript.ts | 186 ----------------- test/smoke/src/main.ts | 1 + test/smoke/src/spectron/client.ts | 6 + test/smoke/src/tests/data-migration.ts | 105 ---------- test/smoke/src/tests/javascript.ts | 87 -------- 13 files changed, 264 insertions(+), 634 deletions(-) delete mode 100644 test/smoke/src/areas/common.ts create mode 100644 test/smoke/src/areas/editor/editor.test.ts create mode 100644 test/smoke/src/areas/editor/peek.ts create mode 100644 test/smoke/src/areas/editor/rename.ts delete mode 100644 test/smoke/src/areas/first-experience.ts delete mode 100644 test/smoke/src/areas/javascript.ts delete mode 100644 test/smoke/src/tests/data-migration.ts delete mode 100644 test/smoke/src/tests/javascript.ts diff --git a/test/smoke/src/areas/common.ts b/test/smoke/src/areas/common.ts deleted file mode 100644 index 1a1f8bc0fc2..00000000000 --- a/test/smoke/src/areas/common.ts +++ /dev/null @@ -1,211 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { SpectronApplication } from '../spectron/application'; -import { Util } from '../helpers/utilities'; - -/** - * Contains methods that are commonly used across test areas. - */ -export class CommonActions { - private util: Util; - - constructor(private spectron: SpectronApplication) { - this.util = new Util(); - } - - public async getWindowTitle(): Promise { - return this.spectron.client.getTitle(); - } - - public enter(): Promise { - return this.spectron.client.keys(['Enter', 'NULL']); - } - - public async addSetting(setting: string, value: string): Promise { - await this.openUserSettings(); - await this.spectron.client.keys(['ArrowDown', 'NULL'], false); - await this.spectron.client.waitForElement(`.editable-preferences-editor-container .monaco-editor.focused`); - await this.spectron.client.keys(['ArrowRight', 'NULL'], false); - await this.spectron.client.keys(`"${setting}": "${value}"`); - await this.saveOpenedFile(); - } - - public async openUserSettings(): Promise { - await this.spectron.command('workbench.action.openGlobalSettings'); - await this.spectron.client.waitForElement('.settings-search-input .synthetic-focus'); - } - - public async openKeybindings(): Promise { - await this.spectron.command('workbench.action.openGlobalKeybindings'); - await this.spectron.client.waitForElement('.settings-search-input .synthetic-focus'); - } - - public async newUntitledFile(): Promise { - await this.spectron.command('workbench.action.files.newUntitledFile'); - return this.spectron.wait(); - } - - public closeTab(): Promise { - return this.spectron.client.keys(['Control', 'w', 'NULL']); - } - - public async getTab(tabName: string, active?: boolean): Promise { - await this.closeCurrentNotification(); // close any notification messages that could overlap tabs - - let tabSelector = active ? '.tab.active' : 'div'; - let el = await this.spectron.client.waitForElement(`.tabs-container ${tabSelector}[aria-label="${tabName}, tab"]`); - if (el) { - return el; - } - - return undefined; - } - - public async selectTab(tabName: string): Promise { - await this.closeCurrentNotification(); // close any notification messages that could overlap tabs - await this.spectron.client.waitAndClick(`.tabs-container div[aria-selected="false"][aria-label="${tabName}, tab"]`); - await this.spectron.client.waitForElement(`.tabs-container div[aria-selected="true"][aria-label="${tabName}, tab"]`); - return this.waitForEditorFocus(); - } - - private async waitForEditorFocus(): Promise { - this.spectron.client.waitForElement(`.monaco-editor.focused`); - } - - public async openFirstMatchFile(fileName: string): Promise { - await this.openQuickOpen(); - await this.type(fileName); - await this.spectron.wait(); - await this.enter(); - return this.spectron.wait(); - } - - public async saveOpenedFile(): Promise { - try { - await this.spectron.client.waitForElement('.tabs-container .tab.active.dirty'); - } catch (e) { - // ignore if there is no dirty file - return Promise.resolve(); - } - await this.spectron.command('workbench.action.files.save'); - return this.spectron.client.waitForElement('.tabs-container .tab.active.dirty', element => !element); - } - - public type(text: string): Promise { - let spectron = this.spectron; - - return new Promise(function (res) { - let textSplit = text.split(' '); - - async function type(i: number) { - if (!textSplit[i] || textSplit[i].length <= 0) { - return res(); - } - - const toType = textSplit[i + 1] ? `${textSplit[i]} ` : textSplit[i]; - await spectron.client.keys(toType, false); - await spectron.client.keys(['NULL']); - await type(i + 1); - } - - return type(0); - }); - } - - public showCommands(): Promise { - return this.spectron.command('workbench.action.showCommands'); - } - - public openQuickOpen(): Promise { - return this.spectron.command('workbench.action.quickOpen'); - } - - public closeQuickOpen(): Promise { - return this.spectron.command('workbench.action.closeQuickOpen'); - } - - public selectNextQuickOpenElement(): Promise { - return this.spectron.client.keys(['ArrowDown', 'NULL']); - } - - public async getQuickOpenElements(): Promise { - const elements = await this.spectron.client.waitForElements('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties .monaco-tree-row'); - return elements.length; - } - - public async openFile(fileName: string, explorer?: boolean): Promise { - let selector = `div[class="monaco-icon-label file-icon ${fileName}-name-file-icon ${this.getExtensionSelector(fileName)}`; - if (explorer) { - selector += ' explorer-item'; - } - selector += '"]'; - - try { - await this.spectron.client.doubleClickAndWait(selector); - await this.spectron.client.waitForElement(`.tabs-container div[aria-label="${fileName}, tab"]`); - await this.spectron.client.waitForElement(`.monaco-editor.focused`); - } catch (e) { - return Promise.reject(`Cannot fine ${fileName} in a viewlet.`); - } - } - - public getExtensionSelector(fileName: string): string { - const extension = fileName.split('.')[1]; - if (extension === 'js') { - return 'js-ext-file-icon javascript-lang-file-icon'; - } else if (extension === 'json') { - return 'json-ext-file-icon json-lang-file-icon'; - } else if (extension === 'md') { - return 'md-ext-file-icon markdown-lang-file-icon'; - } - - throw new Error('No class defined for this file extension'); - } - - public async getEditorFirstLinePlainText(): Promise { - const trials = 3; - let retry = 0; - let error; - - while (retry < trials) { - try { - const span = await this.spectron.client.getText('.view-lines span span'); - if (Array.isArray(span)) { - return span[0]; - } - - return span; - } catch (e) { - error = e; - retry++; - - if (retry < trials) { - await this.spectron.wait(); - } else { - error = e; - } - } - } - - return Promise.reject('Could not obtain text on the first line of an editor: ' + error); - } - - public removeFile(filePath: string): void { - this.util.removeFile(filePath); - } - - public removeDirectory(directory: string): Promise { - try { - return this.util.rimraf(directory); - } catch (e) { - throw new Error(`Failed to remove ${directory} with an error: ${e}`); - } - } - - private closeCurrentNotification(): Promise { - return this.spectron.command('workbench.action.closeMessages'); - } -} \ No newline at end of file diff --git a/test/smoke/src/areas/css/css.test.ts b/test/smoke/src/areas/css/css.test.ts index e72958dae9b..96d5150319b 100644 --- a/test/smoke/src/areas/css/css.test.ts +++ b/test/smoke/src/areas/css/css.test.ts @@ -6,8 +6,6 @@ import * as assert from 'assert'; import { SpectronApplication } from '../../spectron/application'; import { ProblemSeverity, Problems } from '../problems/problems'; -import { QuickOutline } from '../editor/quickoutline'; -import { SettingsEditor } from '../preferences/settings'; describe('CSS', () => { let app: SpectronApplication; @@ -16,10 +14,9 @@ describe('CSS', () => { it('verifies quick outline', async () => { await app.workbench.quickopen.openFile('style.css'); - const outline = new QuickOutline(app); - await outline.openSymbols(); - const elements = await app.client.waitForElements(QuickOutline.QUICK_OPEN_ENTRY_SELECTOR, elements => elements.length === 2); - assert.ok(elements, `Did not find two outline elements`); + const outline = await app.workbench.editor.openOutline(); + const elements = await outline.getQuickOpenElements(); + assert.equal(elements.length, 2, `Did not find two outline elements`); }); it('verifies warnings for the empty rule', async () => { @@ -30,15 +27,14 @@ describe('CSS', () => { let warning = await app.client.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.WARNING)); assert.ok(warning, `Warning squiggle is not shown in 'style.css'.`); - const problems = new Problems(app); - await problems.showProblemsView(); + await app.workbench.problems.showProblemsView(); warning = await app.client.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.WARNING)); assert.ok(warning, 'Warning does not appear in Problems view.'); - await problems.hideProblemsView(); + await app.workbench.problems.hideProblemsView(); }); it('verifies that warning becomes an error once setting changed', async () => { - await new SettingsEditor(app).addUserSetting('css.lint.emptyRules', '"error"'); + await app.workbench.settingsEditor.addUserSetting('css.lint.emptyRules', '"error"'); await app.workbench.quickopen.openFile('style.css'); await app.client.type('.foo{}'); diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts new file mode 100644 index 00000000000..b6be8548c73 --- /dev/null +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; + +import { SpectronApplication } from '../../spectron/application'; + +describe('Editor', () => { + let app: SpectronApplication; + before(() => { app = new SpectronApplication(); return app.start(); }); + after(() => app.stop()); + + it('shows correct quick outline', async function () { + await app.workbench.quickopen.openFile('www'); + + const outline = await app.workbench.editor.openOutline(); + + const symbols = await outline.getQuickOpenElements(); + assert.equal(symbols.length, 12, 'Quick outline elements count does not match to expected.'); + }); + + it(`finds 'All References' to 'app'`, async function () { + await app.workbench.quickopen.openFile('www'); + + const references = await app.workbench.editor.findReferences('app', 7); + + const countInTitle = await references.getCountFromTitle(); + assert.equal(countInTitle, 3, 'References count in widget title is not as expected.'); + const referencesCount = await references.getCount(); + assert.equal(referencesCount, 3, 'References count in tree is not as expected.'); + + await references.close(); + }); + + it(`renames local 'app' variable`, async function () { + await app.workbench.quickopen.openFile('www'); + + const selector = await app.workbench.editor.getSelector('app', 7); + const rename = await app.workbench.editor.rename('app', 7); + rename.rename('newApp'); + + const actual = await app.client.waitForText(selector, 'newApp'); + assert.equal(actual, 'newApp'); + }); + + it('folds/unfolds the code correctly', async function () { + await app.workbench.quickopen.openFile('www'); + + // Fold + await app.workbench.editor.foldAtLine(3); + await app.workbench.editor.waitUntilShown(3); + await app.workbench.editor.waitUntilHidden(4); + await app.workbench.editor.waitUntilHidden(5); + + // Unfold + await app.workbench.editor.unfoldAtLine(3); + await app.workbench.editor.waitUntilShown(3); + await app.workbench.editor.waitUntilShown(4); + await app.workbench.editor.waitUntilShown(5); + }); + + it(`verifies that 'Go To Definition' works`, async function () { + await app.workbench.quickopen.openFile('app.js'); + + await app.workbench.editor.gotoDefinition('express', 11); + + assert.ok(await app.workbench.waitForActiveOpen('index.d.ts'), 'Tab opened when navigating to definition is not as expected.'); + }); + + it(`verifies that 'Peek Definition' works`, async function () { + await app.workbench.quickopen.openFile('app.js'); + + const peek = await app.workbench.editor.peekDefinition('express', 11); + + const definitionFilename = await peek.getFileNameFromTitle(); + assert.equal(definitionFilename, 'index.d.ts', 'Peek result is not as expected.'); + }); +}); \ No newline at end of file diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index 532cf9ddabb..1980ef9d2d9 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -4,9 +4,16 @@ *--------------------------------------------------------------------------------------------*/ import { SpectronApplication } from '../../spectron/application'; +import { QuickOutline } from './quickoutline'; +import { References } from './peek'; +import { Rename } from './rename'; export class Editor { + private static VIEW_LINES = '.monaco-editor .view-lines'; + private static FOLDING_EXPANDED = '.monaco-editor .margin .margin-view-overlays>:nth-child(${INDEX}) .folding'; + private static FOLDING_COLLAPSED = `${Editor.FOLDING_EXPANDED}.collapsed`; + constructor(private spectron: SpectronApplication) { } @@ -19,17 +26,99 @@ export class Editor { return await this.spectron.client.getText('.view-lines'); } + public async openOutline(): Promise { + const outline = new QuickOutline(this.spectron); + await outline.open(); + return outline; + } + + public async findReferences(term: string, line: number): Promise { + await this.clickOnTerm(term, line); + await this.spectron.workbench.commandPallette.runCommand('Find All References'); + const references = new References(this.spectron); + await references.waitUntilOpen(); + return references; + } + + public async rename(term: string, line: number): Promise { + await this.clickOnTerm(term, line); + await this.spectron.workbench.commandPallette.runCommand('Rename Symbol'); + const rename = new Rename(term, this.spectron); + await rename.waitUntilOpen(); + return rename; + } + + public async gotoDefinition(term: string, line: number): Promise { + await this.clickOnTerm(term, line); + await this.spectron.workbench.commandPallette.runCommand('Go to Definition'); + } + + public async peekDefinition(term: string, line: number): Promise { + await this.clickOnTerm(term, line); + await this.spectron.workbench.commandPallette.runCommand('Peek Definition'); + const peek = new References(this.spectron); + await peek.waitUntilOpen(); + return peek; + } + public async waitForHighlightingLine(line: number): Promise { - const currentLineIndex = await this.spectron.client.waitFor(async () => { - const lineNumbers = await this.spectron.webclient.selectorExecute(`.monaco-editor .line-numbers`, - elements => (Array.isArray(elements) ? elements : [elements]).map(element => element.textContent)); - for (let index = 0; index < lineNumbers.length; index++) { - if (lineNumbers[index] === `${line}`) { - return index + 1; - } + const currentLineIndex = await this.getViewLineIndex(line); + if (currentLineIndex) { + await this.spectron.client.waitForElement(`.monaco-editor .view-overlays>:nth-child(${currentLineIndex}) .current-line`); + } + throw new Error('Cannot find line ' + line); + } + + public async getSelector(term: string, line: number): Promise { + const lineIndex = await this.getViewLineIndex(line); + const classNames = await this.spectron.client.waitFor(() => this.getClassSelectors(term, lineIndex), classNames => classNames && !!classNames.length); + return `${Editor.VIEW_LINES}>:nth-child(${lineIndex}) span span.${classNames[0]}`; + } + + public async foldAtLine(line: number): Promise { + const lineIndex = await this.getViewLineIndex(line); + await this.spectron.client.waitAndClick(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); + await this.spectron.client.waitForElement(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); + } + + public async unfoldAtLine(line: number): Promise { + const lineIndex = await this.getViewLineIndex(line); + await this.spectron.client.waitAndClick(Editor.FOLDING_COLLAPSED.replace('${INDEX}', '' + lineIndex)); + await this.spectron.client.waitForElement(Editor.FOLDING_EXPANDED.replace('${INDEX}', '' + lineIndex)); + } + + public async waitUntilHidden(line: number): Promise { + await this.spectron.client.waitFor(() => this.getViewLineIndexWithoutWait(line), lineNumber => lineNumber === undefined); + } + + public async waitUntilShown(line: number): Promise { + await this.getViewLineIndex(line); + } + + public async clickOnTerm(term: string, line: number): Promise { + const selector = await this.getSelector(term, line); + await this.spectron.client.waitAndClick(selector); + } + + private async getClassSelectors(term: string, viewline: number): Promise { + const result: { text: string, className: string }[] = await this.spectron.webclient.selectorExecute(`${Editor.VIEW_LINES}>:nth-child(${viewline}) span span`, + elements => (Array.isArray(elements) ? elements : [elements]) + .map(element => ({ text: element.textContent, className: element.className }))); + return result.filter(r => r.text === term).map(({ className }) => className); + } + + private async getViewLineIndex(line: number): Promise { + return await this.spectron.client.waitFor(() => this.getViewLineIndexWithoutWait(line)); + } + + private async getViewLineIndexWithoutWait(line: number): Promise { + const lineNumbers = await this.spectron.webclient.selectorExecute(`.monaco-editor .line-numbers`, + elements => (Array.isArray(elements) ? elements : [elements]).map(element => element.textContent)); + for (let index = 0; index < lineNumbers.length; index++) { + if (lineNumbers[index] === `${line}`) { + return index + 1; } - return undefined; - }); - await this.spectron.client.waitForElement(`.monaco-editor .view-overlays>:nth-child(${currentLineIndex}) .current-line`); + } + return undefined; } } \ No newline at end of file diff --git a/test/smoke/src/areas/editor/peek.ts b/test/smoke/src/areas/editor/peek.ts new file mode 100644 index 00000000000..ab7ba6558d1 --- /dev/null +++ b/test/smoke/src/areas/editor/peek.ts @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { SpectronApplication } from '../../spectron/application'; + +export class References { + + private static REFERENCES_WIDGET = '.monaco-editor .zone-widget .zone-widget-container.peekview-widget.reference-zone-widget.results-loaded'; + private static REFERENCES_TITLE_FILE_NAME = `${References.REFERENCES_WIDGET} .head .peekview-title .filename`; + private static REFERENCES_TITLE_COUNT = `${References.REFERENCES_WIDGET} .head .peekview-title .meta`; + private static REFERENCES = `${References.REFERENCES_WIDGET} .body .ref-tree.inline .monaco-tree-row .reference`; + + constructor(private spectron: SpectronApplication) { + } + + public async waitUntilOpen(): Promise { + await this.spectron.client.waitForElement(References.REFERENCES_WIDGET); + } + + public async getCountFromTitle(): Promise { + const titleCount = await this.spectron.client.waitForText(References.REFERENCES_TITLE_COUNT); + const matches = titleCount.match(/\d+/); + return matches ? parseInt(matches[0]) : 0; + } + + public async getFileNameFromTitle(): Promise { + return await this.spectron.client.waitForText(References.REFERENCES_TITLE_FILE_NAME); + } + + public async getCount(): Promise { + return (await this.spectron.client.waitForElements(References.REFERENCES)).length; + } + + public async close(): Promise { + await this.spectron.client.keys(['Escape', 'NULL']); + await this.spectron.client.waitForElement(References.REFERENCES_WIDGET, element => !element); + } +} \ No newline at end of file diff --git a/test/smoke/src/areas/editor/quickoutline.ts b/test/smoke/src/areas/editor/quickoutline.ts index a766072a543..c44d5a605f1 100644 --- a/test/smoke/src/areas/editor/quickoutline.ts +++ b/test/smoke/src/areas/editor/quickoutline.ts @@ -12,12 +12,15 @@ export class QuickOutline extends QuickOpen { super(spectron); } - public async openSymbols(): Promise { + public async open(): Promise { await this.spectron.client.waitFor(async () => { await this.spectron.command('workbench.action.gotoSymbol'); - const element = await this.spectron.client.element('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row[aria-label="body, symbols, picker"] .quick-open-entry'); - if (element) { - return element; + const entry = await this.spectron.client.element('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry'); + if (entry) { + const text = await this.spectron.client.getText('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry .monaco-icon-label .label-name .monaco-highlighted-label span'); + if (text !== 'No symbol information for the file') { + return entry; + } } await this.closeQuickOpen(); }); diff --git a/test/smoke/src/areas/editor/rename.ts b/test/smoke/src/areas/editor/rename.ts new file mode 100644 index 00000000000..caabc37ea23 --- /dev/null +++ b/test/smoke/src/areas/editor/rename.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { SpectronApplication } from '../../spectron/application'; + +export class Rename { + + private static RENAME_WIDGET = '.monaco-editor .rename-box .rename-input'; + + constructor(private term: string, private spectron: SpectronApplication) { + } + + public async waitUntilOpen(): Promise { + await this.spectron.client.waitForElement(Rename.RENAME_WIDGET); + await this.spectron.client.waitForValue(Rename.RENAME_WIDGET, this.term); + } + + public async rename(newTerm: string): Promise { + await this.spectron.client.type(newTerm); + await this.spectron.client.keys(['Enter', 'NULL']); + await this.spectron.client.waitForElement(Rename.RENAME_WIDGET, element => !element); + } +} \ No newline at end of file diff --git a/test/smoke/src/areas/first-experience.ts b/test/smoke/src/areas/first-experience.ts deleted file mode 100644 index 11df1a44f80..00000000000 --- a/test/smoke/src/areas/first-experience.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { SpectronApplication } from '../spectron/application'; - -export class FirstExperience { - constructor(private spectron: SpectronApplication) { - // noop - } - - public async getWelcomeTab(): Promise { - let el = await this.spectron.client.waitForElement('.vs_code_welcome_page-name-file-icon'); - if (el) { - return el; - } - - return undefined; - } -} \ No newline at end of file diff --git a/test/smoke/src/areas/javascript.ts b/test/smoke/src/areas/javascript.ts deleted file mode 100644 index 18e9b386997..00000000000 --- a/test/smoke/src/areas/javascript.ts +++ /dev/null @@ -1,186 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { SpectronApplication } from '../spectron/application'; - -var htmlparser = require('htmlparser2'); - -export class JavaScript { - private appVarSelector: string; - private expressVarSelector: string; - - private foldSelector: string; - private foldLine: number; - - constructor(private spectron: SpectronApplication) { - // noop - } - - public openQuickOutline(): Promise { - return this.spectron.command('workbench.action.gotoSymbol'); - } - - public async findAppReferences(): Promise { - await this.setAppVarSelector(); - try { - await this.spectron.client.waitAndClick(this.appVarSelector); - } catch (e) { - return Promise.reject(`Failed to select 'app' variable.`); - } - - return this.spectron.command('editor.action.referenceSearch.trigger'); - } - - public async getTitleReferencesCount(): Promise { - const meta = await this.spectron.client.getText('.reference-zone-widget.results-loaded .peekview-title .meta'); - - return meta.match(/\d+/)[0]; - } - - public async getTreeReferencesCount(): Promise { - const treeElems = await this.spectron.client.waitForElements('.reference-zone-widget.results-loaded .ref-tree.inline .show-twisties .monaco-tree-row'); - - return treeElems.length; - } - - public async renameApp(newValue: string): Promise { - await this.setAppVarSelector(); - - try { - await this.spectron.client.waitAndClick(this.appVarSelector); - } catch (e) { - return Promise.reject(`Failed to select 'app' variable.`); - } - await this.spectron.command('editor.action.rename'); - await this.spectron.wait(); - return this.spectron.client.keys(newValue, false); - } - - public async getNewAppName(): Promise { - return this.spectron.client.getText(this.appVarSelector); - } - - public async toggleFirstCommentFold(): Promise { - this.foldLine = await this.getLineIndexOfFirstFoldableElement(`.margin-view-overlays`); - this.foldSelector = `.margin-view-overlays>:nth-child(${this.foldLine})`; - - try { - return this.spectron.client.waitAndClick(`${this.foldSelector} .cldr.folding`); - } catch (e) { - return Promise.reject('Clicking on fold element failed ' + e); - } - } - - public async getFirstCommentFoldedIcon(): Promise { - if (!this.foldSelector) { - return Promise.reject('No code folding happened to be able to check for a folded icon.'); - } - - return this.spectron.client.waitForHTML(`${this.foldSelector} .cldr.folding.collapsed`); - } - - public async getNextLineNumberAfterFold(): Promise { - if (!this.foldLine) { - return Promise.reject('Folded line was not set, most likely because fold was not toggled initially.'); - } - - return this.spectron.client.getText(`.margin-view-overlays>:nth-child(${this.foldLine + 1}) .line-numbers`); - } - - public async goToExpressDefinition(): Promise { - await this.setExpressVarSelector(); - try { - await this.spectron.client.waitAndClick(this.expressVarSelector); - } catch (e) { - return Promise.reject(`Clicking on express variable failed: ` + e); - } - - return this.spectron.command('editor.action.goToDeclaration'); - } - - public async peekExpressDefinition(): Promise { - await this.setExpressVarSelector(); - try { - await this.spectron.client.waitAndClick(this.expressVarSelector); - } catch (e) { - return Promise.reject('Clicking on express variable failed: ' + e); - } - - return this.spectron.command('editor.action.previewDeclaration'); - } - - public async getPeekExpressResultName(): Promise { - return this.spectron.client.getText('.reference-zone-widget.results-loaded .filename'); - } - - private async setAppVarSelector(): Promise { - if (!this.appVarSelector) { - const lineIndex = await this.getLineIndexOfFirst('app', '.view-lines'); - this.appVarSelector = `.view-lines>:nth-child(${lineIndex}) .mtk11`; - } - } - - private async setExpressVarSelector(): Promise { - if (!this.expressVarSelector) { - const lineIndex = await this.getLineIndexOfFirst('express', '.view-lines'); - this.expressVarSelector = `.view-lines>:nth-child(${lineIndex}) .mtk10`; - } - } - - private getLineIndexOfFirst(string: string, selector: string): Promise { - return this.spectron.client.waitForHTML(selector).then(html => { - return new Promise((res, rej) => { - let lineIndex: number = 0; - let stringFound: boolean; - let parser = new htmlparser.Parser({ - onopentag: function (name: string, attribs: any) { - if (name === 'div' && attribs.class === 'view-line') { - lineIndex++; - } - }, - ontext: function (text) { - if (!stringFound && text === string) { - stringFound = true; - parser.end(); - } - }, - onend: function () { - if (!stringFound) { - return rej(`No ${string} in editor found.`); - } - return res(lineIndex); - } - }); - parser.write(html); - }); - }); - } - - private getLineIndexOfFirstFoldableElement(selector: string): Promise { - return this.spectron.client.waitForHTML(selector).then(html => { - return new Promise((res, rej) => { - let lineIndex: number = 0; - let foldFound: boolean; - let parser = new htmlparser.Parser({ - onopentag: function (name: string, attribs: any) { - if (name === 'div' && !attribs.class) { - lineIndex++; - } else if (name === 'div' && attribs.class.indexOf('cldr folding') !== -1) { - foldFound = true; - parser.end(); - } - }, - onend: function () { - if (!foldFound) { - return rej(`No foldable elements found.`); - } - return res(lineIndex); - } - }); - parser.write(html); - }); - }); - } -} \ No newline at end of file diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index 27930e2b276..eed70c1d47a 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -182,4 +182,5 @@ import './areas/statusbar/statusbar.test'; import './areas/debug/debug.test'; import './areas/workbench/localization.test'; import './areas/terminal/terminal.test'; +import './areas/editor/editor.test'; // import './areas/workbench/data-migration.test'; \ No newline at end of file diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts index 168cc3fbcbc..0751d1b9c4c 100644 --- a/test/smoke/src/spectron/client.ts +++ b/test/smoke/src/spectron/client.ts @@ -38,6 +38,12 @@ export class SpectronClient { return this.waitFor(() => this.spectron.client.getText(selector), accept, `getText with selector ${selector}`); } + public async waitForValue(selector: string, value?: string, accept?: (result: string) => boolean): Promise { + await this.screenshot(); + accept = accept ? accept : result => value !== void 0 ? value === result : !!result; + return this.waitFor(() => this.spectron.client.getValue(selector), accept, `getValue with selector ${selector}`); + } + public async waitForHTML(selector: string, accept: (result: string) => boolean = (result: string) => !!result): Promise { await this.screenshot(); return this.waitFor(() => this.spectron.client.getHTML(selector), accept, `getHTML with selector ${selector}`); diff --git a/test/smoke/src/tests/data-migration.ts b/test/smoke/src/tests/data-migration.ts deleted file mode 100644 index 36cf1b9992d..00000000000 --- a/test/smoke/src/tests/data-migration.ts +++ /dev/null @@ -1,105 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; - -import { SpectronApplication, USER_DIR, STABLE_PATH, LATEST_PATH, WORKSPACE_PATH, EXTENSIONS_DIR } from '../spectron/application'; -import { CommonActions } from '../areas/common'; - -let app: SpectronApplication; -let common: CommonActions; - -export function testDataMigration() { - if (!STABLE_PATH) { - return; - } - - describe('Data Migration', () => { - - afterEach(async function () { - await app.stop(); - await common.removeDirectory(USER_DIR); - return await common.removeDirectory(EXTENSIONS_DIR); - }); - - function setupSpectron(context: Mocha.ITestCallbackContext, appPath: string, args?: string[]): void { - if (!args) { - args = []; - } - args.push(`--extensions-dir=${EXTENSIONS_DIR}`); - - // app = new SpectronApplication(appPath, context.test.fullTitle(), context.test.currentRetry(), args, [`--user-data-dir=${USER_DIR}`]); - common = new CommonActions(app); - } - - it('checks if the Untitled file is restored migrating from stable to latest', async function () { - const textToType = 'Very dirty file'; - - // Setting up stable version - setupSpectron(this, STABLE_PATH); - await app.start(); - - await common.newUntitledFile(); - await common.type(textToType); - await app.stop(); - - await app.wait(); // wait until all resources are released (e.g. locked local storage) - - // Checking latest version for the restored state - setupSpectron(this, LATEST_PATH); - await app.start(); - - assert.ok(await common.getTab('Untitled-1'), 'Untitled-1 tab was not restored after migration.'); - await common.selectTab('Untitled-1'); - const editorText = await common.getEditorFirstLinePlainText(); - assert.equal(editorText, textToType, 'Typed editor text does not match to the one after migration.'); - }); - - it('checks if the newly created dirty file is restored migrating from stable to latest', async function () { - const fileName = 'test_data/plainFile', - firstTextPart = 'This is going to be an unsaved file', secondTextPart = '_that is dirty.'; - - // Setting up stable version - setupSpectron(this, STABLE_PATH, [fileName]); - await common.removeFile(`${fileName}`); - await app.start(); - - await common.type(firstTextPart); - await common.saveOpenedFile(); - await app.wait(); - await common.type(secondTextPart); - - await app.stop(); - await app.wait(); // wait until all resources are released (e.g. locked local storage) - - // Checking latest version for the restored state - setupSpectron(this, LATEST_PATH); - await app.start(); - assert.ok(await common.getTab(fileName.split('/')[1]), `${fileName} was not restored after migration.`); - await common.selectTab(fileName.split('/')[1]); - const editorText = await common.getEditorFirstLinePlainText(); - assert.equal(editorText, firstTextPart.concat(secondTextPart), 'Entered text was not correctly restored after migration.'); - - // Cleanup - await common.removeFile(`${fileName}`); - }); - - it('cheks if opened tabs are restored migrating from stable to latest', async function () { - const fileName1 = 'app.js', fileName2 = 'jsconfig.json', fileName3 = 'readme.md'; - setupSpectron(this, STABLE_PATH, [WORKSPACE_PATH]); - await app.start(); - await common.openFile(fileName1, true); - await common.openFile(fileName2, true); - await common.openFile(fileName3, true); - await app.stop(); - - setupSpectron(this, LATEST_PATH, [WORKSPACE_PATH]); - await app.start(); - assert.ok(await common.getTab(fileName1), `${fileName1} tab was not restored after migration.`); - assert.ok(await common.getTab(fileName2), `${fileName2} tab was not restored after migration.`); - assert.ok(await common.getTab(fileName3), `${fileName3} tab was not restored after migration.`); - }); - }); -} \ No newline at end of file diff --git a/test/smoke/src/tests/javascript.ts b/test/smoke/src/tests/javascript.ts deleted file mode 100644 index 5bb9f011980..00000000000 --- a/test/smoke/src/tests/javascript.ts +++ /dev/null @@ -1,87 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; - -import { SpectronApplication } from '../spectron/application'; -import { CommonActions } from '../areas/common'; -import { JavaScript } from '../areas/javascript'; - -let app: SpectronApplication; -let common: CommonActions; - -export function testJavaScript() { - describe('JavaScript', () => { - let js: JavaScript; - - beforeEach(async function () { - // app = new SpectronApplication(LATEST_PATH, this.currentTest.fullTitle(), (this.currentTest as any).currentRetry(), [WORKSPACE_PATH]); - common = new CommonActions(app); - js = new JavaScript(app); - - return await app.start(); - }); - afterEach(async function () { - return await app.stop(); - }); - - it('shows correct quick outline', async function () { - await common.openFirstMatchFile('bin/www'); - await js.openQuickOutline(); - await app.wait(); - const symbols = await common.getQuickOpenElements(); - assert.equal(symbols, 12, 'Quick outline elements count does not match to expected.'); - }); - - it(`finds 'All References' to 'app'`, async function () { - await common.openFirstMatchFile('bin/www'); - await js.findAppReferences(); - await app.wait(); - const titleCount = await js.getTitleReferencesCount(); - assert.equal(titleCount, 3, 'References count in widget title is not as expected.'); - const treeCount = await js.getTreeReferencesCount(); - assert.equal(treeCount, 3, 'References count in tree is not as expected.'); - }); - - it(`renames local 'app' variable`, async function () { - await common.openFirstMatchFile('bin/www'); - - const newVarName = 'newApp'; - await js.renameApp(newVarName); - await common.enter(); - const newName = await js.getNewAppName(); - assert.equal(newName, newVarName); - }); - - it('folds/unfolds the code correctly', async function () { - await common.openFirstMatchFile('bin/www'); - // Fold - await js.toggleFirstCommentFold(); - const foldedIcon = await js.getFirstCommentFoldedIcon(); - assert.ok(foldedIcon, 'Folded icon was not found in the margin.'); - let nextLineNumber = await js.getNextLineNumberAfterFold(); - assert.equal(nextLineNumber, 7, 'Line number after folded code is wrong.'); - // Unfold - await js.toggleFirstCommentFold(); - nextLineNumber = await js.getNextLineNumberAfterFold(); - assert.equal(nextLineNumber, 4, 'Line number with unfolded code is wrong.'); - }); - - it(`verifies that 'Go To Definition' works`, async function () { - await common.openFirstMatchFile('app.js'); - await js.goToExpressDefinition(); - await app.wait(); - assert.ok(await common.getTab('index.d.ts'), 'Tab opened when navigating to definition is not as expected.'); - }); - - it(`verifies that 'Peek Definition' works`, async function () { - await common.openFirstMatchFile('app.js'); - await js.peekExpressDefinition(); - await app.wait(); - const definitionFilename = await js.getPeekExpressResultName(); - assert.equal(definitionFilename, 'index.d.ts', 'Peek result is not as expected.'); - }); - }); -} \ No newline at end of file -- GitLab