From fc0774e44ff7cd9a7568bcd2d7e3124c227483ba Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 10 Apr 2018 16:26:45 +0200 Subject: [PATCH] typeInEditor API --- src/vs/platform/driver/common/driver.ts | 14 ++++++++++ .../driver/electron-browser/driver.ts | 23 ++++++++++++++++ .../platform/driver/electron-main/driver.ts | 5 ++++ test/smoke/src/api.ts | 4 +++ test/smoke/src/areas/editor/editor.ts | 26 +++---------------- test/smoke/src/driver.ts | 14 ++++++++++ test/smoke/test/mocha.opts | 2 +- 7 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/vs/platform/driver/common/driver.ts b/src/vs/platform/driver/common/driver.ts index 0fdcc5d46c5..8a64621227b 100644 --- a/src/vs/platform/driver/common/driver.ts +++ b/src/vs/platform/driver/common/driver.ts @@ -33,6 +33,7 @@ export interface IDriver { getTitle(windowId: number): TPromise; isActiveElement(windowId: number, selector: string): TPromise; getElements(windowId: number, selector: string, recursive: boolean): TPromise; + typeInEditor(windowId: number, selector: string, text: string): TPromise; selectorExecute

(windowId: number, selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise

; } //*END @@ -47,6 +48,7 @@ export interface IDriverChannel extends IChannel { call(command: 'getTitle', arg: [number]): TPromise; call(command: 'isActiveElement', arg: [number, string]): TPromise; call(command: 'getElements', arg: [number, string, boolean]): TPromise; + call(command: 'typeInEditor', arg: [number, string, string]): TPromise; call(command: 'selectorExecute', arg: [number, string, string, any[]]): TPromise; call(command: string, arg: any): TPromise; } @@ -66,6 +68,7 @@ export class DriverChannel implements IDriverChannel { case 'getTitle': return this.driver.getTitle(arg[0]); case 'isActiveElement': return this.driver.isActiveElement(arg[0], arg[1]); case 'getElements': return this.driver.getElements(arg[0], arg[1], arg[2]); + case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1], arg[2]); // TODO@joao case 'selectorExecute': return this.driver.selectorExecute(arg[0], arg[1], arg[1], ...arg[2]); @@ -117,6 +120,10 @@ export class DriverChannelClient implements IDriver { return this.channel.call('getElements', [windowId, selector, recursive]); } + typeInEditor(windowId: number, selector: string, text: string): TPromise { + return this.channel.call('typeInEditor', [windowId, selector, text]); + } + selectorExecute

(windowId: number, selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise

{ // TODO@joao return this.channel.call('selectorExecute', [windowId, selector, script.toString(), args]); @@ -164,6 +171,7 @@ export interface IWindowDriver { getTitle(): TPromise; isActiveElement(selector: string): TPromise; getElements(selector: string, recursive: boolean): TPromise; + typeInEditor(selector: string, text: string): TPromise; selectorExecute

(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise

; } @@ -175,6 +183,7 @@ export interface IWindowDriverChannel extends IChannel { call(command: 'getTitle'): TPromise; call(command: 'isActiveElement', arg: string): TPromise; call(command: 'getElements', arg: [string, boolean]): TPromise; + call(command: 'typeInEditor', arg: [string, string]): TPromise; call(command: 'selectorExecute', arg: [string, string, any[]]): TPromise; call(command: string, arg: any): TPromise; } @@ -192,6 +201,7 @@ export class WindowDriverChannel implements IWindowDriverChannel { case 'getTitle': return this.driver.getTitle(); case 'isActiveElement': return this.driver.isActiveElement(arg); case 'getElements': return this.driver.getElements(arg[0], arg[1]); + case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1]); // TODO@joao case 'selectorExecute': return this.driver.selectorExecute(arg[0], arg[1], ...arg[2]); } @@ -234,6 +244,10 @@ export class WindowDriverChannelClient implements IWindowDriver { return this.channel.call('getElements', [selector, recursive]); } + typeInEditor(selector: string, text: string): TPromise { + return this.channel.call('typeInEditor', [selector, text]); + } + selectorExecute

(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise

{ // TODO@joao return this.channel.call('selectorExecute', [selector, script.toString(), args]); diff --git a/src/vs/platform/driver/electron-browser/driver.ts b/src/vs/platform/driver/electron-browser/driver.ts index 44100426f4f..7fb3fb6133b 100644 --- a/src/vs/platform/driver/electron-browser/driver.ts +++ b/src/vs/platform/driver/electron-browser/driver.ts @@ -87,6 +87,29 @@ class WindowDriver implements IWindowDriver { return result; } + async typeInEditor(selector: string, text: string): TPromise { + const element = document.querySelector(selector); + + if (!element) { + throw new Error('Editor not found: ' + selector); + } + + const textarea = element as HTMLTextAreaElement; + + console.log(textarea); + + const start = textarea.selectionStart; + const newStart = start + text.length; + const value = textarea.value; + const newValue = value.substr(0, start) + text + value.substr(start); + + textarea.value = newValue; + textarea.setSelectionRange(newStart, newStart); + + const event = new Event('input', { 'bubbles': true, 'cancelable': true }); + textarea.dispatchEvent(event); + } + selectorExecute

(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise

{ return TPromise.wrapError(new Error('not implemented')); } diff --git a/src/vs/platform/driver/electron-main/driver.ts b/src/vs/platform/driver/electron-main/driver.ts index 1676316a3a5..ad32690ab27 100644 --- a/src/vs/platform/driver/electron-main/driver.ts +++ b/src/vs/platform/driver/electron-main/driver.ts @@ -137,6 +137,11 @@ export class Driver implements IDriver, IWindowDriverRegistry { return windowDriver.selectorExecute(selector, script, ...args); } + typeInEditor(windowId: number, selector: string, text: string): TPromise { + const windowDriver = this.getWindowDriver(windowId); + return windowDriver.typeInEditor(selector, text); + } + private getWindowDriver(windowId: number): IWindowDriver { const router = new WindowRouter(windowId); const windowDriverChannel = this.windowServer.getChannel('windowDriver', router); diff --git a/test/smoke/src/api.ts b/test/smoke/src/api.ts index d93d19ff05f..356583997fb 100644 --- a/test/smoke/src/api.ts +++ b/test/smoke/src/api.ts @@ -80,6 +80,10 @@ export class API { return this.driver.selectorExecute(selector, script, ...args); } + typeInEditor(selector: string, text: string): Promise { + return this.driver.typeInEditor(selector, text); + } + private running = false; async waitFor(func: () => T | Promise, accept?: (result: T) => boolean | Promise, timeoutMessage?: string, retryCount?: number): Promise; async waitFor(func: () => T | Promise, accept: (result: T) => boolean | Promise = result => !!result, timeoutMessage?: string, retryCount?: number): Promise { diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index 552a4fc743b..fdb5f4ca9c2 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -9,6 +9,7 @@ import { API } from '../../api'; const RENAME_BOX = '.monaco-editor .monaco-editor.rename-box'; const RENAME_INPUT = `${RENAME_BOX} .rename-input`; +const EDITOR = filename => `.monaco-editor[data-uri$="${filename}"]`; export class Editor { @@ -87,39 +88,20 @@ export class Editor { } async waitForTypeInEditor(filename: string, text: string, selectorPrefix = ''): Promise { - const editor = [ - selectorPrefix || '', - `.monaco-editor[data-uri$="${filename}"]` - ].join(' '); + const editor = [selectorPrefix || '', EDITOR(filename)].join(' '); await this.api.waitForElement(editor); const textarea = `${editor} textarea`; await this.api.waitForActiveElement(textarea); - // https://github.com/Microsoft/vscode/issues/34203#issuecomment-334441786 - await this.api.selectorExecute(textarea, (elements, text) => { - const textarea = (Array.isArray(elements) ? elements : [elements])[0] as HTMLTextAreaElement; - const start = textarea.selectionStart; - const newStart = start + text.length; - const value = textarea.value; - const newValue = value.substr(0, start) + text + value.substr(start); - - textarea.value = newValue; - textarea.setSelectionRange(newStart, newStart); - - const event = new Event('input', { 'bubbles': true, 'cancelable': true }); - textarea.dispatchEvent(event); - }, text); + await this.api.typeInEditor(textarea, text); await this.waitForEditorContents(filename, c => c.indexOf(text) > -1, selectorPrefix); } async waitForEditorContents(filename: string, accept: (contents: string) => boolean, selectorPrefix = ''): Promise { - const selector = [ - selectorPrefix || '', - `.monaco-editor[data-uri$="${filename}"] .view-lines` - ].join(' '); + const selector = [selectorPrefix || '', `${EDITOR(filename)} .view-lines`].join(' '); return this.api.waitForTextContent(selector, undefined, c => accept(c.replace(/\u00a0/g, ' '))); } diff --git a/test/smoke/src/driver.ts b/test/smoke/src/driver.ts index bc7d4edb503..fa661be932e 100644 --- a/test/smoke/src/driver.ts +++ b/test/smoke/src/driver.ts @@ -23,6 +23,7 @@ export interface Driver { isActiveElement(selector: string): Promise; getElements(selector: string, recursive?: boolean): Promise; + typeInEditor(selector: string, text: string): Promise; selectorExecute

(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): Promise

; } @@ -116,6 +117,10 @@ export class SpectronDriver implements Driver { return result.value; } + typeInEditor(selector: string, text: string): Promise { + throw new Error('Method not implemented.'); + } + async selectorExecute

(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): Promise

{ if (this.verbose) { console.log('- selectorExecute:', selector); @@ -217,6 +222,15 @@ export class CodeDriver implements Driver { return await this.driver.selectorExecute(windowId, selector, script, ...args); } + async typeInEditor(selector: string, text: string): Promise { + if (this.verbose) { + console.log('- typeInEditor:', selector, text); + } + + const windowId = await this.getWindowId(); + return await this.driver.typeInEditor(windowId, selector, text); + } + private async getWindowId(): Promise { if (typeof this._activeWindowId !== 'number') { const windows = await this.driver.getWindowIds(); diff --git a/test/smoke/test/mocha.opts b/test/smoke/test/mocha.opts index a4520575eb6..ce88473e86b 100644 --- a/test/smoke/test/mocha.opts +++ b/test/smoke/test/mocha.opts @@ -1,3 +1,3 @@ ---timeout 10000 +--timeout 20000 --slow 2000 out/main.js \ No newline at end of file