提交 d9b889ff 编写于 作者: S Sandeep Somavarapu

smoke test: adopt editor tests

上级 bf84cbcc
/*---------------------------------------------------------------------------------------------
* 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<any> {
return this.spectron.client.getTitle();
}
public enter(): Promise<any> {
return this.spectron.client.keys(['Enter', 'NULL']);
}
public async addSetting(setting: string, value: string): Promise<any> {
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<void> {
await this.spectron.command('workbench.action.openGlobalSettings');
await this.spectron.client.waitForElement('.settings-search-input .synthetic-focus');
}
public async openKeybindings(): Promise<void> {
await this.spectron.command('workbench.action.openGlobalKeybindings');
await this.spectron.client.waitForElement('.settings-search-input .synthetic-focus');
}
public async newUntitledFile(): Promise<any> {
await this.spectron.command('workbench.action.files.newUntitledFile');
return this.spectron.wait();
}
public closeTab(): Promise<any> {
return this.spectron.client.keys(['Control', 'w', 'NULL']);
}
public async getTab(tabName: string, active?: boolean): Promise<any> {
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<any> {
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<void> {
this.spectron.client.waitForElement(`.monaco-editor.focused`);
}
public async openFirstMatchFile(fileName: string): Promise<any> {
await this.openQuickOpen();
await this.type(fileName);
await this.spectron.wait();
await this.enter();
return this.spectron.wait();
}
public async saveOpenedFile(): Promise<any> {
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<any> {
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<any> {
return this.spectron.command('workbench.action.showCommands');
}
public openQuickOpen(): Promise<any> {
return this.spectron.command('workbench.action.quickOpen');
}
public closeQuickOpen(): Promise<any> {
return this.spectron.command('workbench.action.closeQuickOpen');
}
public selectNextQuickOpenElement(): Promise<any> {
return this.spectron.client.keys(['ArrowDown', 'NULL']);
}
public async getQuickOpenElements(): Promise<number> {
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<any> {
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<any> {
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<any> {
try {
return this.util.rimraf(directory);
} catch (e) {
throw new Error(`Failed to remove ${directory} with an error: ${e}`);
}
}
private closeCurrentNotification(): Promise<any> {
return this.spectron.command('workbench.action.closeMessages');
}
}
\ No newline at end of file
......@@ -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{}');
......
/*---------------------------------------------------------------------------------------------
* 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
......@@ -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,8 +26,92 @@ export class Editor {
return await this.spectron.client.getText('.view-lines');
}
public async openOutline(): Promise<QuickOutline> {
const outline = new QuickOutline(this.spectron);
await outline.open();
return outline;
}
public async findReferences(term: string, line: number): Promise<References> {
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<Rename> {
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<void> {
await this.clickOnTerm(term, line);
await this.spectron.workbench.commandPallette.runCommand('Go to Definition');
}
public async peekDefinition(term: string, line: number): Promise<References> {
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<void> {
const currentLineIndex = await this.spectron.client.waitFor<number>(async () => {
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<string> {
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<any> {
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<any> {
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<void> {
await this.spectron.client.waitFor<number>(() => this.getViewLineIndexWithoutWait(line), lineNumber => lineNumber === undefined);
}
public async waitUntilShown(line: number): Promise<void> {
await this.getViewLineIndex(line);
}
public async clickOnTerm(term: string, line: number): Promise<void> {
const selector = await this.getSelector(term, line);
await this.spectron.client.waitAndClick(selector);
}
private async getClassSelectors(term: string, viewline: number): Promise<string[]> {
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<number> {
return await this.spectron.client.waitFor<number>(() => this.getViewLineIndexWithoutWait(line));
}
private async getViewLineIndexWithoutWait(line: number): Promise<number | undefined> {
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++) {
......@@ -29,7 +120,5 @@ export class Editor {
}
}
return undefined;
});
await this.spectron.client.waitForElement(`.monaco-editor .view-overlays>:nth-child(${currentLineIndex}) .current-line`);
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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<void> {
await this.spectron.client.waitForElement(References.REFERENCES_WIDGET);
}
public async getCountFromTitle(): Promise<number> {
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<string> {
return await this.spectron.client.waitForText(References.REFERENCES_TITLE_FILE_NAME);
}
public async getCount(): Promise<number> {
return (await this.spectron.client.waitForElements(References.REFERENCES)).length;
}
public async close(): Promise<void> {
await this.spectron.client.keys(['Escape', 'NULL']);
await this.spectron.client.waitForElement(References.REFERENCES_WIDGET, element => !element);
}
}
\ No newline at end of file
......@@ -12,12 +12,15 @@ export class QuickOutline extends QuickOpen {
super(spectron);
}
public async openSymbols(): Promise<void> {
public async open(): Promise<void> {
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();
});
......
......@@ -3,19 +3,23 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SpectronApplication } from '../spectron/application';
import { SpectronApplication } from '../../spectron/application';
export class FirstExperience {
constructor(private spectron: SpectronApplication) {
// noop
export class Rename {
private static RENAME_WIDGET = '.monaco-editor .rename-box .rename-input';
constructor(private term: string, private spectron: SpectronApplication) {
}
public async getWelcomeTab(): Promise<any> {
let el = await this.spectron.client.waitForElement('.vs_code_welcome_page-name-file-icon');
if (el) {
return el;
public async waitUntilOpen(): Promise<void> {
await this.spectron.client.waitForElement(Rename.RENAME_WIDGET);
await this.spectron.client.waitForValue(Rename.RENAME_WIDGET, this.term);
}
return undefined;
public async rename(newTerm: string): Promise<void> {
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
/*---------------------------------------------------------------------------------------------
* 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<any> {
return this.spectron.command('workbench.action.gotoSymbol');
}
public async findAppReferences(): Promise<any> {
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<any> {
const meta = await this.spectron.client.getText('.reference-zone-widget.results-loaded .peekview-title .meta');
return meta.match(/\d+/)[0];
}
public async getTreeReferencesCount(): Promise<any> {
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<any> {
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<any> {
return this.spectron.client.getText(this.appVarSelector);
}
public async toggleFirstCommentFold(): Promise<any> {
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<any> {
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<any> {
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<any> {
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<any> {
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<any> {
return this.spectron.client.getText('.reference-zone-widget.results-loaded .filename');
}
private async setAppVarSelector(): Promise<any> {
if (!this.appVarSelector) {
const lineIndex = await this.getLineIndexOfFirst('app', '.view-lines');
this.appVarSelector = `.view-lines>:nth-child(${lineIndex}) .mtk11`;
}
}
private async setExpressVarSelector(): Promise<any> {
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<number> {
return this.spectron.client.waitForHTML(selector).then(html => {
return new Promise<number>((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<number> {
return this.spectron.client.waitForHTML(selector).then(html => {
return new Promise<number>((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
......@@ -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
......@@ -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<any> {
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<any> {
await this.screenshot();
return this.waitFor(() => this.spectron.client.getHTML(selector), accept, `getHTML with selector ${selector}`);
......
/*---------------------------------------------------------------------------------------------
* 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
/*---------------------------------------------------------------------------------------------
* 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册