Allow WebKit clients to specify a minimum effective width for layout.
[WebKit-https.git] / LayoutTests / resources / ui-helper.js
1
2 window.UIHelper = class UIHelper {
3     static isIOS()
4     {
5         return navigator.userAgent.includes('iPhone') || navigator.userAgent.includes('iPad');
6     }
7
8     static isWebKit2()
9     {
10         return window.testRunner.isWebKit2;
11     }
12
13     static tapAt(x, y)
14     {
15         console.assert(this.isIOS());
16
17         if (!this.isWebKit2()) {
18             eventSender.addTouchPoint(x, y);
19             eventSender.touchStart();
20             eventSender.releaseTouchPoint(0);
21             eventSender.touchEnd();
22             return Promise.resolve();
23         }
24
25         return new Promise((resolve) => {
26             testRunner.runUIScript(`
27                 uiController.singleTapAtPoint(${x}, ${y}, function() {
28                     uiController.uiScriptComplete('Done');
29                 });`, resolve);
30         });
31     }
32
33     static activateAt(x, y)
34     {
35         if (!this.isWebKit2() || !this.isIOS()) {
36             eventSender.mouseMoveTo(x, y);
37             eventSender.mouseDown();
38             eventSender.mouseUp();
39             return Promise.resolve();
40         }
41
42         return new Promise((resolve) => {
43             testRunner.runUIScript(`
44                 uiController.singleTapAtPoint(${x}, ${y}, function() {
45                     uiController.uiScriptComplete('Done');
46                 });`, resolve);
47         });
48     }
49
50     static activateElement(element)
51     {
52         const x = element.offsetLeft + element.offsetWidth / 2;
53         const y = element.offsetTop + element.offsetHeight / 2;
54         return UIHelper.activateAt(x, y);
55     }
56
57     static keyDown(key, modifiers=[])
58     {
59         if (!this.isWebKit2() || !this.isIOS()) {
60             eventSender.keyDown(key, modifiers);
61             return Promise.resolve();
62         }
63
64         return new Promise((resolve) => {
65             testRunner.runUIScript(`uiController.keyDown("${key}", ${JSON.stringify(modifiers)});`, resolve);
66         });
67     }
68
69     static toggleCapsLock()
70     {
71         return new Promise((resolve) => {
72             testRunner.runUIScript(`uiController.toggleCapsLock(() => uiController.uiScriptComplete('Done'));`, resolve);
73         });
74     }
75
76     static ensurePresentationUpdate()
77     {
78         if (!this.isWebKit2()) {
79             testRunner.display();
80             return Promise.resolve();
81         }
82
83         return new Promise(resolve => {
84             testRunner.runUIScript(`
85                 uiController.doAfterPresentationUpdate(function() {
86                     uiController.uiScriptComplete('Done');
87                 });`, resolve);
88         });
89     }
90
91     static ensureVisibleContentRectUpdate()
92     {
93         if (!this.isWebKit2())
94             return Promise.resolve();
95
96         return new Promise(resolve => {
97             const visibleContentRectUpdateScript = "uiController.doAfterVisibleContentRectUpdate(() => uiController.uiScriptComplete())";
98             testRunner.runUIScript(visibleContentRectUpdateScript, resolve);
99         });
100     }
101
102     static activateAndWaitForInputSessionAt(x, y)
103     {
104         if (!this.isWebKit2() || !this.isIOS())
105             return this.activateAt(x, y);
106
107         return new Promise(resolve => {
108             testRunner.runUIScript(`
109                 (function() {
110                     uiController.didShowKeyboardCallback = function() {
111                         uiController.uiScriptComplete("Done");
112                     };
113                     uiController.singleTapAtPoint(${x}, ${y}, function() { });
114                 })()`, resolve);
115         });
116     }
117
118     static activateFormControl(element)
119     {
120         if (!this.isWebKit2() || !this.isIOS())
121             return this.activateElement(element);
122
123         const x = element.offsetLeft + element.offsetWidth / 2;
124         const y = element.offsetTop + element.offsetHeight / 2;
125
126         return new Promise(resolve => {
127             testRunner.runUIScript(`
128                 (function() {
129                     uiController.didStartFormControlInteractionCallback = function() {
130                         uiController.uiScriptComplete("Done");
131                     };
132                     uiController.singleTapAtPoint(${x}, ${y}, function() { });
133                 })()`, resolve);
134         });
135     }
136
137     static waitForKeyboardToHide()
138     {
139         if (!this.isWebKit2() || !this.isIOS())
140             return Promise.resolve();
141
142         return new Promise(resolve => {
143             testRunner.runUIScript(`
144                 (function() {
145                     if (uiController.isShowingKeyboard)
146                         uiController.didHideKeyboardCallback = () => uiController.uiScriptComplete();
147                     else
148                         uiController.uiScriptComplete();
149                 })()`, resolve);
150         });
151     }
152
153     static getUICaretRect()
154     {
155         if (!this.isWebKit2() || !this.isIOS())
156             return Promise.resolve();
157
158         return new Promise(resolve => {
159             testRunner.runUIScript(`(function() {
160                 uiController.doAfterNextStablePresentationUpdate(function() {
161                     uiController.uiScriptComplete(JSON.stringify(uiController.textSelectionCaretRect));
162                 });
163             })()`, jsonString => {
164                 resolve(JSON.parse(jsonString));
165             });
166         });
167     }
168
169     static getUISelectionRects()
170     {
171         if (!this.isWebKit2() || !this.isIOS())
172             return Promise.resolve();
173
174         return new Promise(resolve => {
175             testRunner.runUIScript(`(function() {
176                 uiController.doAfterNextStablePresentationUpdate(function() {
177                     uiController.uiScriptComplete(JSON.stringify(uiController.textSelectionRangeRects));
178                 });
179             })()`, jsonString => {
180                 resolve(JSON.parse(jsonString));
181             });
182         });
183     }
184
185     static getUICaretViewRect()
186     {
187         if (!this.isWebKit2() || !this.isIOS())
188             return Promise.resolve();
189
190         return new Promise(resolve => {
191             testRunner.runUIScript(`(function() {
192                 uiController.doAfterNextStablePresentationUpdate(function() {
193                     uiController.uiScriptComplete(JSON.stringify(uiController.selectionCaretViewRect));
194                 });
195             })()`, jsonString => {
196                 resolve(JSON.parse(jsonString));
197             });
198         });
199     }
200
201     static getUISelectionViewRects()
202     {
203         if (!this.isWebKit2() || !this.isIOS())
204             return Promise.resolve();
205
206         return new Promise(resolve => {
207             testRunner.runUIScript(`(function() {
208                 uiController.doAfterNextStablePresentationUpdate(function() {
209                     uiController.uiScriptComplete(JSON.stringify(uiController.selectionRangeViewRects));
210                 });
211             })()`, jsonString => {
212                 resolve(JSON.parse(jsonString));
213             });
214         });
215     }
216
217     static getSelectionStartGrabberViewRect()
218     {
219         if (!this.isWebKit2() || !this.isIOS())
220             return Promise.resolve();
221
222         return new Promise(resolve => {
223             testRunner.runUIScript(`(function() {
224                 uiController.doAfterNextStablePresentationUpdate(function() {
225                     uiController.uiScriptComplete(JSON.stringify(uiController.selectionStartGrabberViewRect));
226                 });
227             })()`, jsonString => {
228                 resolve(JSON.parse(jsonString));
229             });
230         });
231     }
232
233     static getSelectionEndGrabberViewRect()
234     {
235         if (!this.isWebKit2() || !this.isIOS())
236             return Promise.resolve();
237
238         return new Promise(resolve => {
239             testRunner.runUIScript(`(function() {
240                 uiController.doAfterNextStablePresentationUpdate(function() {
241                     uiController.uiScriptComplete(JSON.stringify(uiController.selectionEndGrabberViewRect));
242                 });
243             })()`, jsonString => {
244                 resolve(JSON.parse(jsonString));
245             });
246         });
247     }
248
249     static replaceTextAtRange(text, location, length) {
250         return new Promise(resolve => {
251             testRunner.runUIScript(`(() => {
252                 uiController.replaceTextAtRange("${text}", ${location}, ${length});
253                 uiController.uiScriptComplete('Done');
254             })()`, resolve);
255         });
256     }
257
258     static wait(promise)
259     {
260         testRunner.waitUntilDone();
261         if (window.finishJSTest)
262             window.jsTestIsAsync = true;
263
264         let finish = () => {
265             if (window.finishJSTest)
266                 finishJSTest();
267             else
268                 testRunner.notifyDone();
269         }
270
271         return promise.then(finish, finish);
272     }
273
274     static withUserGesture(callback)
275     {
276         internals.withUserGesture(callback);
277     }
278
279     static selectFormAccessoryPickerRow(rowIndex)
280     {
281         const selectRowScript = `(() => uiController.selectFormAccessoryPickerRow(${rowIndex}))()`;
282         return new Promise(resolve => testRunner.runUIScript(selectRowScript, resolve));
283     }
284
285     static selectFormPopoverTitle()
286     {
287         return new Promise(resolve => {
288             testRunner.runUIScript(`(() => {
289                 uiController.uiScriptComplete(uiController.selectFormPopoverTitle);
290             })()`, resolve);
291         });
292     }
293
294     static enterText(text)
295     {
296         const escapedText = text.replace(/`/g, "\\`");
297         const enterTextScript = `(() => uiController.enterText(\`${escapedText}\`))()`;
298         return new Promise(resolve => testRunner.runUIScript(enterTextScript, resolve));
299     }
300
301     static setTimePickerValue(hours, minutes)
302     {
303         const setValueScript = `(() => uiController.setTimePickerValue(${hours}, ${minutes}))()`;
304         return new Promise(resolve => testRunner.runUIScript(setValueScript, resolve));
305     }
306
307     static setShareSheetCompletesImmediatelyWithResolution(resolved)
308     {
309         const resolveShareSheet = `(() => uiController.setShareSheetCompletesImmediatelyWithResolution(${resolved}))()`;
310         return new Promise(resolve => testRunner.runUIScript(resolveShareSheet, resolve));
311     }
312
313     static textContentType()
314     {
315         return new Promise(resolve => {
316             testRunner.runUIScript(`(() => {
317                 uiController.uiScriptComplete(uiController.textContentType);
318             })()`, resolve);
319         });
320     }
321
322     static formInputLabel()
323     {
324         return new Promise(resolve => {
325             testRunner.runUIScript(`(() => {
326                 uiController.uiScriptComplete(uiController.formInputLabel);
327             })()`, resolve);
328         });
329     }
330
331     static isShowingDataListSuggestions()
332     {
333         return new Promise(resolve => {
334             testRunner.runUIScript(`(() => {
335                 uiController.uiScriptComplete(uiController.isShowingDataListSuggestions);
336             })()`, result => resolve(result === "true" ? true : false));
337         });
338     }
339
340     static zoomScale()
341     {
342         return new Promise(resolve => {
343             testRunner.runUIScript(`(() => {
344                 uiController.uiScriptComplete(uiController.zoomScale);
345             })()`, scaleAsString => resolve(parseFloat(scaleAsString)));
346         });
347     }
348
349     static typeCharacter(characterString)
350     {
351         if (!this.isWebKit2() || !this.isIOS()) {
352             eventSender.keyDown(characterString);
353             return;
354         }
355
356         const escapedString = characterString.replace(/\\/g, "\\\\").replace(/`/g, "\\`");
357         const uiScript = `uiController.typeCharacterUsingHardwareKeyboard(\`${escapedString}\`, () => uiController.uiScriptComplete())`;
358         return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
359     }
360
361     static applyAutocorrection(newText, oldText)
362     {
363         if (!this.isWebKit2())
364             return;
365
366         const [escapedNewText, escapedOldText] = [newText.replace(/`/g, "\\`"), oldText.replace(/`/g, "\\`")];
367         const uiScript = `uiController.applyAutocorrection(\`${escapedNewText}\`, \`${escapedOldText}\`, () => uiController.uiScriptComplete())`;
368         return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
369     }
370
371     static inputViewBounds()
372     {
373         if (!this.isWebKit2() || !this.isIOS())
374             return Promise.resolve();
375
376         return new Promise(resolve => {
377             testRunner.runUIScript(`(() => {
378                 uiController.uiScriptComplete(JSON.stringify(uiController.inputViewBounds));
379             })()`, jsonString => {
380                 resolve(JSON.parse(jsonString));
381             });
382         });
383     }
384
385     static calendarType()
386     {
387         if (!this.isWebKit2())
388             return Promise.resolve();
389
390         return new Promise(resolve => {
391             testRunner.runUIScript(`(() => {
392                 uiController.doAfterNextStablePresentationUpdate(() => {
393                     uiController.uiScriptComplete(JSON.stringify(uiController.calendarType));
394                 })
395             })()`, jsonString => {
396                 resolve(JSON.parse(jsonString));
397             });
398         });
399     }
400
401     static setDefaultCalendarType(calendarIdentifier)
402     {
403         if (!this.isWebKit2())
404             return Promise.resolve();
405
406         return new Promise(resolve => testRunner.runUIScript(`uiController.setDefaultCalendarType('${calendarIdentifier}')`, resolve));
407
408     }
409
410     static setViewScale(scale)
411     {
412         if (!this.isWebKit2())
413             return Promise.resolve();
414
415         return new Promise(resolve => testRunner.runUIScript(`uiController.setViewScale(${scale})`, resolve));
416     }
417
418     static resignFirstResponder()
419     {
420         if (!this.isWebKit2())
421             return Promise.resolve();
422
423         return new Promise(resolve => testRunner.runUIScript(`uiController.resignFirstResponder()`, resolve));
424     }
425
426     static minimumZoomScale()
427     {
428         if (!this.isWebKit2())
429             return Promise.resolve();
430
431         return new Promise(resolve => {
432             testRunner.runUIScript(`(() => {
433                 uiController.uiScriptComplete(uiController.minimumZoomScale);
434             })()`, scaleAsString => resolve(parseFloat(scaleAsString)))
435         });
436     }
437
438     static drawSquareInEditableImage()
439     {
440         if (!this.isWebKit2())
441             return Promise.resolve();
442
443         return new Promise(resolve => testRunner.runUIScript(`uiController.drawSquareInEditableImage()`, resolve));
444     }
445
446     static numberOfStrokesInEditableImage()
447     {
448         if (!this.isWebKit2())
449             return Promise.resolve();
450
451         return new Promise(resolve => {
452             testRunner.runUIScript(`(() => {
453                 uiController.uiScriptComplete(uiController.numberOfStrokesInEditableImage);
454             })()`, numberAsString => resolve(parseInt(numberAsString, 10)))
455         });
456     }
457
458     static attachmentInfo(attachmentIdentifier)
459     {
460         if (!this.isWebKit2())
461             return Promise.resolve();
462
463         return new Promise(resolve => {
464             testRunner.runUIScript(`(() => {
465                 uiController.uiScriptComplete(JSON.stringify(uiController.attachmentInfo('${attachmentIdentifier}')));
466             })()`, jsonString => {
467                 resolve(JSON.parse(jsonString));
468             })
469         });
470     }
471
472     static setMinimumEffectiveWidth(effectiveWidth)
473     {
474         if (!this.isWebKit2())
475             return Promise.resolve();
476
477         return new Promise(resolve => testRunner.runUIScript(`uiController.setMinimumEffectiveWidth(${effectiveWidth})`, resolve));
478     }
479 }