driver.ts 5.2 KB
Newer Older
J
Joao Moreno 已提交
1 2 3 4 5 6 7 8 9 10 11
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IWindowDriver, IElement, WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/common/driver';
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
J
Joao Moreno 已提交
12
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Joao Moreno 已提交
13 14
import { getTopLeftOffset, getClientArea } from 'vs/base/browser/dom';
import * as electron from 'electron';
J
Joao Moreno 已提交
15

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
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
	};
}

J
Joao Moreno 已提交
41 42
class WindowDriver implements IWindowDriver {

J
Joao Moreno 已提交
43
	constructor() { }
J
Joao Moreno 已提交
44

J
Joao Moreno 已提交
45
	async click(selector: string, xoffset?: number, yoffset?: number): TPromise<void> {
J
Joao Moreno 已提交
46 47 48 49 50 51 52 53
		return this._click(selector, 1, xoffset, yoffset);
	}

	doubleClick(selector: string): TPromise<void> {
		return this._click(selector, 2);
	}

	private async _click(selector: string, clickCount: number, xoffset?: number, yoffset?: number): TPromise<void> {
J
Joao Moreno 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
		const element = document.querySelector(selector);

		if (!element) {
			throw new Error('Element not found');
		}

		const { left, top } = getTopLeftOffset(element as HTMLElement);
		const { width, height } = getClientArea(element as HTMLElement);
		let x: number, y: number;

		if ((typeof xoffset === 'number') || (typeof yoffset === 'number')) {
			x = left + xoffset;
			y = top + yoffset;
		} else {
			x = left + (width / 2);
			y = top + (height / 2);
		}

J
Joao Moreno 已提交
72 73 74
		x = Math.round(x);
		y = Math.round(y);

J
Joao Moreno 已提交
75
		const webContents = electron.remote.getCurrentWebContents();
J
Joao Moreno 已提交
76 77
		webContents.sendInputEvent({ type: 'mouseDown', x, y, button: 'left', clickCount } as any);
		webContents.sendInputEvent({ type: 'mouseUp', x, y, button: 'left', clickCount } as any);
J
Joao Moreno 已提交
78 79

		await TPromise.timeout(100);
J
Joao Moreno 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92
	}

	move(selector: string): TPromise<void> {
		throw new Error('Method not implemented.');
	}

	async setValue(selector: string, text: string): TPromise<void> {
		const element = document.querySelector(selector);

		if (!element) {
			throw new Error('Element not found');
		}

J
Joao Moreno 已提交
93 94 95 96 97
		const inputElement = element as HTMLInputElement;
		inputElement.value = text;

		const event = new Event('input', { bubbles: true, cancelable: true });
		inputElement.dispatchEvent(event);
J
Joao Moreno 已提交
98 99 100 101 102 103 104 105 106 107 108
	}

	async getTitle(): TPromise<string> {
		return document.title;
	}

	async isActiveElement(selector: string): TPromise<boolean> {
		const element = document.querySelector(selector);
		return element === document.activeElement;
	}

109
	async getElements(selector: string, recursive: boolean): TPromise<IElement[]> {
J
Joao Moreno 已提交
110 111 112 113 114
		const query = document.querySelectorAll(selector);
		const result: IElement[] = [];

		for (let i = 0; i < query.length; i++) {
			const element = query.item(i);
115
			result.push(serializeElement(element, recursive));
J
Joao Moreno 已提交
116 117 118 119
		}

		return result;
	}
J
Joao Moreno 已提交
120

J
Joao Moreno 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
	async typeInEditor(selector: string, text: string): TPromise<void> {
		const element = document.querySelector(selector);

		if (!element) {
			throw new Error('Editor not found: ' + selector);
		}

		const textarea = element 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);
	}

J
Joao Moreno 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
	async getTerminalBuffer(selector: string): TPromise<string[]> {
		const element = document.querySelector(selector);

		if (!element) {
			throw new Error('Terminal not found: ' + selector);
		}

		const buffer = (element as any).xterm.buffer;

		const lines: string[] = [];

		for (let i = 0; i < buffer.lines.length; i++) {
			lines.push(buffer.translateBufferLineToString(i, true));
		}

		return lines;
J
Joao Moreno 已提交
157
	}
J
Joao Moreno 已提交
158 159
}

J
Joao Moreno 已提交
160 161 162 163 164 165
export async function registerWindowDriver(
	client: IPCClient,
	windowId: number,
	instantiationService: IInstantiationService
): TPromise<IDisposable> {
	const windowDriver = instantiationService.createInstance(WindowDriver);
J
Joao Moreno 已提交
166 167 168 169 170 171 172 173 174 175
	const windowDriverChannel = new WindowDriverChannel(windowDriver);
	client.registerChannel('windowDriver', windowDriverChannel);

	const windowDriverRegistryChannel = client.getChannel('windowDriverRegistry');
	const windowDriverRegistry = new WindowDriverRegistryChannelClient(windowDriverRegistryChannel);

	await windowDriverRegistry.registerWindowDriver(windowId);

	return client;
}