@@ -7,8 +7,14 @@ const puppeteer = require('puppeteer');
77
88// export function connect(outPath: string, handle: string): Promise<{ client: IDisposable, driver: IDriver }>
99
10- const width = 800 ;
11- const height = 600 ;
10+ const width = 1200 ;
11+ const height = 800 ;
12+
13+ const vscodeToPuppeteerKey = {
14+ cmd : 'Meta' ,
15+ ctrl : 'Control' ,
16+ enter : 'Enter'
17+ } ;
1218
1319function buildDriver ( browser , page ) {
1420 return {
@@ -20,21 +26,147 @@ function buildDriver(browser, page) {
2026 reloadWindow : ( windowId ) => Promise . resolve ( ) ,
2127 exitApplication : ( ) => browser . close ( ) ,
2228 dispatchKeybinding : async ( windowId , keybinding ) => {
23- console . log ( 'ctrl+p' ) ;
24- await page . keyboard . down ( 'Control' ) ;
25- await page . keyboard . press ( 'p' ) ;
26- await page . keyboard . up ( 'Control' ) ;
27- await page . waitForSelector ( '.jkasndknjadsf' ) ;
29+ const keys = keybinding . split ( '+' ) ;
30+ const keysDown = [ ] ;
31+ for ( let i = 0 ; i < keys . length ; i ++ ) {
32+ if ( keys [ i ] in vscodeToPuppeteerKey ) {
33+ keys [ i ] = vscodeToPuppeteerKey [ keys [ i ] ] ;
34+ }
35+ await page . keyboard . down ( keys [ i ] ) ;
36+ keysDown . push ( keys [ i ] ) ;
37+ }
38+ while ( keysDown . length > 0 ) {
39+ await page . keyboard . up ( keysDown . pop ( ) ) ;
40+ }
41+ } ,
42+ click : async ( windowId , selector , xoffset , yoffset ) => {
43+ console . log ( 'click' ) ;
44+ const { x, y } = await page . evaluate ( `
45+ (function() {
46+ function convertToPixels(element, value) {
47+ return parseFloat(value) || 0;
48+ }
49+ function getDimension(element, cssPropertyName, jsPropertyName) {
50+ let computedStyle = getComputedStyle(element);
51+ let value = '0';
52+ if (computedStyle) {
53+ if (computedStyle.getPropertyValue) {
54+ value = computedStyle.getPropertyValue(cssPropertyName);
55+ } else {
56+ // IE8
57+ value = (computedStyle).getAttribute(jsPropertyName);
58+ }
59+ }
60+ return convertToPixels(element, value);
61+ }
62+ function getBorderLeftWidth(element) {
63+ return getDimension(element, 'border-left-width', 'borderLeftWidth');
64+ }
65+ function getBorderRightWidth(element) {
66+ return getDimension(element, 'border-right-width', 'borderRightWidth');
67+ }
68+ function getBorderTopWidth(element) {
69+ return getDimension(element, 'border-top-width', 'borderTopWidth');
70+ }
71+ function getBorderBottomWidth(element) {
72+ return getDimension(element, 'border-bottom-width', 'borderBottomWidth');
73+ }
74+ function getClientArea(element) {
75+ // Try with DOM clientWidth / clientHeight
76+ if (element !== document.body) {
77+ return { width: element.clientWidth, height: element.clientHeight };
78+ }
79+
80+ // Try innerWidth / innerHeight
81+ if (window.innerWidth && window.innerHeight) {
82+ return { width: window.innerWidth, height: window.innerHeight };
83+ }
84+
85+ // Try with document.body.clientWidth / document.body.clientHeight
86+ if (document.body && document.body.clientWidth && document.body.clientHeight) {
87+ return { width: document.body.clientWidth, height: document.body.clientHeight };
88+ }
89+
90+ // Try with document.documentElement.clientWidth / document.documentElement.clientHeight
91+ if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientHeight) {
92+ return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight };
93+ }
94+
95+ throw new Error('Unable to figure out browser width and height');
96+ }
97+ function getTopLeftOffset(element) {
98+ // Adapted from WinJS.Utilities.getPosition
99+ // and added borders to the mix
100+
101+ let offsetParent = element.offsetParent, top = element.offsetTop, left = element.offsetLeft;
102+
103+ while ((element = element.parentNode) !== null && element !== document.body && element !== document.documentElement) {
104+ top -= element.scrollTop;
105+ let c = getComputedStyle(element);
106+ if (c) {
107+ left -= c.direction !== 'rtl' ? element.scrollLeft : -element.scrollLeft;
108+ }
109+
110+ if (element === offsetParent) {
111+ left += getBorderLeftWidth(element);
112+ top += getBorderTopWidth(element);
113+ top += element.offsetTop;
114+ left += element.offsetLeft;
115+ offsetParent = element.offsetParent;
116+ }
117+ }
118+
119+ return {
120+ left: left,
121+ top: top
122+ };
123+ }
124+ const element = document.querySelector('${ selector } ');
125+
126+ if (!element) {
127+ throw new Error('Element not found: ${ selector } ');
128+ }
129+
130+ const { left, top } = getTopLeftOffset(element);
131+ const { width, height } = getClientArea(element);
132+ let x, y;
133+
134+ x = left + (width / 2);
135+ y = top + (height / 2);
136+
137+ x = Math.round(x);
138+ y = Math.round(y);
139+
140+ return { x, y };
141+ })();
142+ ` ) ;
143+ await page . mouse . click ( x + ( xoffset ? xoffset : 0 ) , y + ( yoffset ? yoffset : 0 ) ) ;
28144 } ,
29- click : ( windowId , selector , xoffset , yoffset ) => Promise . resolve ( ) ,
30145 doubleClick : ( windowId , selector ) => Promise . resolve ( ) ,
31- setValue : ( windowId , selector , text ) => Promise . resolve ( ) ,
146+ setValue : async ( windowId , selector , text ) => {
147+ return page . evaluate ( `
148+ (function() {
149+ const element = document.querySelector('${ selector } ');
150+
151+ if (!element) {
152+ throw new Error('Element not found: ${ selector } ');
153+ }
154+
155+ const inputElement = element;
156+ inputElement.value = '${ text } ';
157+
158+ const event = new Event('input', { bubbles: true, cancelable: true });
159+ inputElement.dispatchEvent(event);
160+ return true;
161+ })();
162+ ` ) ;
163+ } ,
32164 getTitle : ( windowId ) => page . title ( ) ,
33165 isActiveElement : ( windowId , selector ) => {
34- page . evaluate ( `document.querySelector('${ selector } ') === document.activeElement` ) ;
166+ return page . evaluate ( `document.querySelector('${ selector } ') === document.activeElement` ) ;
35167 } ,
36- getElements : async ( windowId , selector , recursive ) => {
37- return await page . evaluate ( `
168+ getElements : ( windowId , selector , recursive ) => {
169+ return page . evaluate ( `
38170 (function() {
39171 function convertToPixels(element, value) {
40172 return parseFloat(value) || 0;
@@ -138,22 +270,22 @@ function buildDriver(browser, page) {
138270 ` ) ;
139271 } ,
140272 typeInEditor : ( windowId , selector , text ) => Promise . resolve ( ) ,
141- getTerminalBuffer : async ( windowId , selector ) => {
142- return await page . evaluate ( `
273+ getTerminalBuffer : ( windowId , selector ) => {
274+ return page . evaluate ( `
143275 (function () {
144- const element = document.querySelector(selector);
276+ const element = document.querySelector(' ${ selector } ' );
145277
146278 if (!element) {
147- throw new Error('Terminal not found: ${ selector } '' );
279+ throw new Error('Terminal not found: ${ selector } ');
148280 }
149281
150- const xterm: Terminal = element.xterm;
282+ const xterm = element.xterm;
151283
152284 if (!xterm) {
153285 throw new Error('Xterm not found: ${ selector } ');
154286 }
155287
156- const lines: string[] = [];
288+ const lines = [];
157289
158290 for (let i = 0; i < xterm.buffer.length; i++) {
159291 lines.push(xterm.buffer.getLine(i).translateToString(true));
@@ -163,21 +295,23 @@ function buildDriver(browser, page) {
163295 })();
164296 ` ) ;
165297 } ,
166- writeInTerminal : async ( windowId , selector , text ) => {
167- page . evaluate ( `
168- const element = document.querySelector(selector);
298+ writeInTerminal : ( windowId , selector , text ) => {
299+ return page . evaluate ( `
300+ (function () {
301+ const element = document.querySelector('${ selector } ');
169302
170- if (!element) {
171- throw new Error('Element not found: ${ selector } ');
172- }
303+ if (!element) {
304+ throw new Error('Element not found: ${ selector } ');
305+ }
173306
174- const xterm: Terminal = element.xterm;
307+ const xterm = element.xterm;
175308
176- if (!xterm) {
177- throw new Error('Xterm not found: ${ selector } ');
178- }
309+ if (!xterm) {
310+ throw new Error('Xterm not found: ${ selector } ');
311+ }
179312
180- xterm._core.handler(text);
313+ xterm._core._coreService.triggerDataEvent('${ text } ');
314+ })();
181315 ` ) ;
182316 }
183317 }
@@ -186,13 +320,15 @@ function buildDriver(browser, page) {
186320exports . connect = function ( outPath , handle ) {
187321 return new Promise ( async ( c ) => {
188322 const browser = await puppeteer . launch ( {
323+ // Run in Edge dev on macOS
324+ // executablePath: '/Applications/Microsoft\ Edge\ Dev.app/Contents/MacOS/Microsoft\ Edge\ Dev',
189325 headless : false ,
190326 slowMo : 80 ,
191327 args : [ `--window-size=${ width } ,${ height } ` ]
192328 } ) ;
193329 const page = ( await browser . pages ( ) ) [ 0 ] ;
194330 await page . setViewport ( { width, height } ) ;
195- await page . goto ( 'http://127.0.0.1:8000 ' ) ;
331+ await page . goto ( 'http://127.0.0.1:9888 ' ) ;
196332 const result = {
197333 client : { dispose : ( ) => { } } ,
198334 driver : buildDriver ( browser , page )
0 commit comments