提交 7bd69c0c 编写于 作者: J Joao Moreno

attributes, children on IElement instances

上级 43207efb
......@@ -17,6 +17,8 @@ export interface IElement {
tagName: string;
className: string;
textContent: string;
attributes: { [name: string]: string; };
children: IElement[];
}
export interface IDriver {
......@@ -30,7 +32,7 @@ export interface IDriver {
setValue(windowId: number, selector: string, text: string): TPromise<void>;
getTitle(windowId: number): TPromise<string>;
isActiveElement(windowId: number, selector: string): TPromise<boolean>;
getElements(windowId: number, selector: string): TPromise<IElement[]>;
getElements(windowId: number, selector: string, recursive: boolean): TPromise<IElement[]>;
selectorExecute<P>(windowId: number, selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise<P>;
}
//*END
......@@ -44,7 +46,7 @@ export interface IDriverChannel extends IChannel {
call(command: 'setValue', arg: [number, string, string]): TPromise<void>;
call(command: 'getTitle', arg: [number]): TPromise<string>;
call(command: 'isActiveElement', arg: [number, string]): TPromise<boolean>;
call(command: 'getElements', arg: [number, string]): TPromise<IElement[]>;
call(command: 'getElements', arg: [number, string, boolean]): TPromise<IElement[]>;
call(command: 'selectorExecute', arg: [number, string, string, any[]]): TPromise<any>;
call(command: string, arg: any): TPromise<any>;
}
......@@ -63,7 +65,7 @@ export class DriverChannel implements IDriverChannel {
case 'setValue': return this.driver.setValue(arg[0], arg[1], arg[2]);
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]);
case 'getElements': return this.driver.getElements(arg[0], arg[1], arg[2]);
// TODO@joao
case 'selectorExecute': return this.driver.selectorExecute(arg[0], arg[1], arg[1], ...arg[2]);
......@@ -111,8 +113,8 @@ export class DriverChannelClient implements IDriver {
return this.channel.call('isActiveElement', [windowId, selector]);
}
getElements(windowId: number, selector: string): TPromise<IElement[]> {
return this.channel.call('getElements', [windowId, selector]);
getElements(windowId: number, selector: string, recursive: boolean): TPromise<IElement[]> {
return this.channel.call('getElements', [windowId, selector, recursive]);
}
selectorExecute<P>(windowId: number, selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise<P> {
......@@ -161,7 +163,7 @@ export interface IWindowDriver {
setValue(selector: string, text: string): TPromise<void>;
getTitle(): TPromise<string>;
isActiveElement(selector: string): TPromise<boolean>;
getElements(selector: string): TPromise<IElement[]>;
getElements(selector: string, recursive: boolean): TPromise<IElement[]>;
selectorExecute<P>(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise<P>;
}
......@@ -172,7 +174,7 @@ export interface IWindowDriverChannel extends IChannel {
call(command: 'setValue', arg: [string, string]): TPromise<void>;
call(command: 'getTitle'): TPromise<string>;
call(command: 'isActiveElement', arg: string): TPromise<boolean>;
call(command: 'getElements', arg: string): TPromise<IElement[]>;
call(command: 'getElements', arg: [string, boolean]): TPromise<IElement[]>;
call(command: 'selectorExecute', arg: [string, string, any[]]): TPromise<any>;
call(command: string, arg: any): TPromise<any>;
}
......@@ -189,7 +191,7 @@ export class WindowDriverChannel implements IWindowDriverChannel {
case 'setValue': return this.driver.setValue(arg[0], arg[1]);
case 'getTitle': return this.driver.getTitle();
case 'isActiveElement': return this.driver.isActiveElement(arg);
case 'getElements': return this.driver.getElements(arg);
case 'getElements': return this.driver.getElements(arg[0], arg[1]);
// TODO@joao
case 'selectorExecute': return this.driver.selectorExecute(arg[0], arg[1], ...arg[2]);
}
......@@ -228,8 +230,8 @@ export class WindowDriverChannelClient implements IWindowDriver {
return this.channel.call('isActiveElement', selector);
}
getElements(selector: string): TPromise<IElement[]> {
return this.channel.call('getElements', selector);
getElements(selector: string, recursive: boolean): TPromise<IElement[]> {
return this.channel.call('getElements', [selector, recursive]);
}
selectorExecute<P>(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise<P> {
......
......@@ -11,6 +11,31 @@ import { IWindowDriver, IElement, WindowDriverChannel, WindowDriverRegistryChann
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
function serializeElement(element: Element, recursive: boolean): IElement {
const attributes = Object.create(null);
for (let j = 0; j < element.attributes.length; j++) {
const attr = element.attributes.item(j);
attributes[attr.name] = attr.value;
}
const children = [];
if (recursive) {
for (let i = 0; i < element.children.length; i++) {
children.push(serializeElement(element.children.item(i), true));
}
}
return {
tagName: element.tagName,
className: element.className,
textContent: element.textContent || '',
attributes,
children
};
}
class WindowDriver implements IWindowDriver {
constructor() { }
......@@ -50,18 +75,13 @@ class WindowDriver implements IWindowDriver {
return element === document.activeElement;
}
async getElements(selector: string): TPromise<IElement[]> {
async getElements(selector: string, recursive: boolean): TPromise<IElement[]> {
const query = document.querySelectorAll(selector);
const result: IElement[] = [];
for (let i = 0; i < query.length; i++) {
const element = query.item(i);
result.push({
tagName: element.tagName,
className: element.className,
textContent: element.textContent || ''
});
result.push(serializeElement(element, recursive));
}
return result;
......
......@@ -127,9 +127,9 @@ export class Driver implements IDriver, IWindowDriverRegistry {
return windowDriver.isActiveElement(selector);
}
getElements(windowId: number, selector: string): TPromise<IElement[]> {
getElements(windowId: number, selector: string, recursive: boolean): TPromise<IElement[]> {
const windowDriver = this.getWindowDriver(windowId);
return windowDriver.getElements(selector);
return windowDriver.getElements(selector, recursive);
}
selectorExecute<P>(windowId: number, selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): TPromise<P> {
......
......@@ -60,8 +60,8 @@ export class API {
return elements.length;
}
waitForElements(selector: string, accept: (result: Element[]) => boolean = result => result.length > 0): Promise<Element[]> {
return this.waitFor(() => this.driver.getElements(selector), accept, `elements with selector ${selector}`) as Promise<any>;
waitForElements(selector: string, recursive: boolean, accept: (result: Element[]) => boolean = result => result.length > 0): Promise<Element[]> {
return this.waitFor(() => this.driver.getElements(selector, recursive), accept, `elements with selector ${selector}`) as Promise<any>;
}
waitForElement(selector: string, accept: (result: Element | undefined) => boolean = result => !!result): Promise<void> {
......
......@@ -105,7 +105,7 @@ export class Debug extends Viewlet {
}
async waitForStackFrameLength(length: number): Promise<any> {
await this.api.waitForElements(STACK_FRAME, result => result.length === length);
await this.api.waitForElements(STACK_FRAME, false, result => result.length === length);
}
async focusStackFrame(name: string, message: string): Promise<any> {
......
......@@ -125,13 +125,13 @@ export class Editor {
}
private async getClassSelectors(term: string, viewline: number): Promise<string[]> {
const elements = await this.api.waitForElements(`${Editor.VIEW_LINES}>:nth-child(${viewline}) span span`, els => els.some(el => el.textContent === term));
const elements = await this.api.waitForElements(`${Editor.VIEW_LINES}>:nth-child(${viewline}) span span`, false, els => els.some(el => el.textContent === term));
const { className } = elements.filter(r => r.textContent === term)[0];
return className.split(/\s/g);
}
private async getViewLineIndex(line: number): Promise<number> {
const elements = await this.api.waitForElements(Editor.LINE_NUMBERS, els => {
const elements = await this.api.waitForElements(Editor.LINE_NUMBERS, false, els => {
return els.some(el => el.textContent === `${line}`);
});
......
......@@ -26,7 +26,7 @@ export class References {
}
async waitForReferencesCount(count: number): Promise<void> {
await this.api.waitForElements(References.REFERENCES, result => result && result.length === count);
await this.api.waitForElements(References.REFERENCES, false, result => result && result.length === count);
}
async waitForFile(file: string): Promise<void> {
......
......@@ -18,12 +18,12 @@ export function setup() {
const app = this.app as SpectronApplication;
await app.workbench.explorer.openFile('app.js');
await app.api.waitForElements('.line-numbers', elements => !!elements.length);
await app.api.waitForElements('.line-numbers', false, elements => !!elements.length);
await app.screenCapturer.capture('app.js has line numbers');
await app.workbench.settingsEditor.addUserSetting('editor.lineNumbers', '"off"');
await app.workbench.editors.selectTab('app.js');
await app.api.waitForElements('.line-numbers', result => !result || result.length === 0);
await app.api.waitForElements('.line-numbers', false, result => !result || result.length === 0);
await app.screenCapturer.capture('line numbers hidden');
});
......
......@@ -65,7 +65,7 @@ export class QuickOpen {
}
async waitForQuickOpenElements(accept: (names: string[]) => boolean): Promise<void> {
await this.api.waitForElements(QuickOpen.QUICK_OPEN_ENTRY_LABEL_SELECTOR, els => accept(els.map(e => e.textContent)));
await this.api.waitForElements(QuickOpen.QUICK_OPEN_ENTRY_LABEL_SELECTOR, false, els => accept(els.map(e => e.textContent)));
}
async runCommand(command: string): Promise<void> {
......
......@@ -10,6 +10,7 @@ export interface Element {
tagName: string;
className: string;
textContent: string;
attributes: { [name: string]: string };
}
export interface Driver {
......@@ -21,7 +22,7 @@ export interface Driver {
getTitle(): Promise<string>;
isActiveElement(selector: string): Promise<boolean>;
getElements(selector: string): Promise<Element[]>;
getElements(selector: string, recursive?: boolean): Promise<Element[]>;
selectorExecute<P>(selector: string, script: (elements: HTMLElement[], ...args: any[]) => P, ...args: any[]): Promise<P>;
}
......@@ -104,7 +105,8 @@ export class SpectronDriver implements Driver {
result.push({
tagName: element.tagName,
className: element.className,
textContent: element.textContent || ''
textContent: element.textContent || '',
attributes: {}
});
}
......@@ -196,13 +198,13 @@ export class CodeDriver implements Driver {
return await this.driver.isActiveElement(windowId, selector);
}
async getElements(selector: string): Promise<Element[]> {
async getElements(selector: string, recursive = false): Promise<Element[]> {
if (this.verbose) {
console.log('- getElements:', selector);
}
const windowId = await this.getWindowId();
const result = await this.driver.getElements(windowId, selector);
const result = await this.driver.getElements(windowId, selector, recursive);
return result;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册