| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright 2018 Google Inc. All rights reserved. | 
					
						
							|  |  |  |  * Modifications copyright (c) Microsoft Corporation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-19 21:32:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 07:08:22 -07:00
										 |  |  | import { test as it, expect } from './pageTest'; | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | function dimensions() { | 
					
						
							|  |  |  |   const rect = document.querySelector('textarea').getBoundingClientRect(); | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     x: rect.left, | 
					
						
							|  |  |  |     y: rect.top, | 
					
						
							|  |  |  |     width: rect.width, | 
					
						
							|  |  |  |     height: rect.height | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-10 19:42:52 +01:00
										 |  |  | it('should click the document @smoke', async ({ page, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.evaluate(() => { | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |     window['clickPromise'] = new Promise(resolve => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |       document.addEventListener('click', event => { | 
					
						
							|  |  |  |         resolve({ | 
					
						
							|  |  |  |           type: event.type, | 
					
						
							|  |  |  |           detail: event.detail, | 
					
						
							|  |  |  |           clientX: event.clientX, | 
					
						
							|  |  |  |           clientY: event.clientY, | 
					
						
							|  |  |  |           isTrusted: event.isTrusted, | 
					
						
							|  |  |  |           button: event.button | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.click(50, 60); | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |   const event = await page.evaluate(() => window['clickPromise']); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   expect(event.type).toBe('click'); | 
					
						
							|  |  |  |   expect(event.detail).toBe(1); | 
					
						
							|  |  |  |   expect(event.clientX).toBe(50); | 
					
						
							|  |  |  |   expect(event.clientY).toBe(60); | 
					
						
							|  |  |  |   expect(event.isTrusted).toBe(true); | 
					
						
							|  |  |  |   expect(event.button).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | it('should dblclick the div', async ({ page, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.setContent(`<div style='width: 100px; height: 100px;'>Click me</div>`); | 
					
						
							|  |  |  |   await page.evaluate(() => { | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |     window['dblclickPromise'] = new Promise(resolve => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |       document.querySelector('div').addEventListener('dblclick', event => { | 
					
						
							|  |  |  |         resolve({ | 
					
						
							|  |  |  |           type: event.type, | 
					
						
							|  |  |  |           detail: event.detail, | 
					
						
							|  |  |  |           clientX: event.clientX, | 
					
						
							|  |  |  |           clientY: event.clientY, | 
					
						
							|  |  |  |           isTrusted: event.isTrusted, | 
					
						
							|  |  |  |           button: event.button, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.dblclick(50, 60); | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |   const event = await page.evaluate(() => window['dblclickPromise']); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   expect(event.type).toBe('dblclick'); | 
					
						
							|  |  |  |   expect(event.detail).toBe(2); | 
					
						
							|  |  |  |   expect(event.clientX).toBe(50); | 
					
						
							|  |  |  |   expect(event.clientY).toBe(60); | 
					
						
							|  |  |  |   expect(event.isTrusted).toBe(true); | 
					
						
							|  |  |  |   expect(event.button).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-12 19:01:45 +01:00
										 |  |  | it('should pointerdown the div with a custom button', async ({ page, server, browserName }) => { | 
					
						
							|  |  |  |   await page.setContent(`<div style='width: 100px; height: 100px;'>Click me</div>`); | 
					
						
							|  |  |  |   await page.evaluate(() => { | 
					
						
							|  |  |  |     window['pointerdownPromise'] = new Promise(resolve => { | 
					
						
							|  |  |  |       document.querySelector('div').addEventListener('pointerdown', event => { | 
					
						
							|  |  |  |         resolve({ | 
					
						
							|  |  |  |           type: event.type, | 
					
						
							|  |  |  |           detail: event.detail, | 
					
						
							|  |  |  |           clientX: event.clientX, | 
					
						
							|  |  |  |           clientY: event.clientY, | 
					
						
							|  |  |  |           isTrusted: event.isTrusted, | 
					
						
							|  |  |  |           button: event.button, | 
					
						
							|  |  |  |           buttons: event.buttons, | 
					
						
							|  |  |  |           pointerId: event.pointerId, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.click(50, 60, { | 
					
						
							|  |  |  |     button: 'middle' | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   const event = await page.evaluate(() => window['pointerdownPromise']); | 
					
						
							|  |  |  |   expect(event.type).toBe('pointerdown'); | 
					
						
							|  |  |  |   expect(event.detail).toBe(browserName === 'webkit' ? 1 : 0); | 
					
						
							|  |  |  |   expect(event.clientX).toBe(50); | 
					
						
							|  |  |  |   expect(event.clientY).toBe(60); | 
					
						
							|  |  |  |   expect(event.isTrusted).toBe(true); | 
					
						
							|  |  |  |   expect(event.button).toBe(1); | 
					
						
							|  |  |  |   expect(event.buttons).toBe(4); | 
					
						
							|  |  |  |   expect(event.pointerId).toBe(browserName === 'firefox' ? 0 : 1); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-10 05:48:16 +01:00
										 |  |  | it('should report correct buttons property', async ({ page }) => { | 
					
						
							|  |  |  |   await page.evaluate(() => { | 
					
						
							|  |  |  |     (window as any).__EVENTS = []; | 
					
						
							|  |  |  |     const handler = event => { | 
					
						
							|  |  |  |       (window as any).__EVENTS.push({ | 
					
						
							|  |  |  |         type: event.type, | 
					
						
							|  |  |  |         button: event.button, | 
					
						
							|  |  |  |         buttons: event.buttons, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     window.addEventListener('mousedown', handler, false); | 
					
						
							|  |  |  |     window.addEventListener('mouseup', handler, false); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.move(50, 60); | 
					
						
							|  |  |  |   await page.mouse.down({ | 
					
						
							|  |  |  |     button: 'middle', | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.down({ | 
					
						
							|  |  |  |     button: 'left', | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.up({ | 
					
						
							|  |  |  |     button: 'middle', | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.up({ | 
					
						
							|  |  |  |     button: 'left', | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => (window as any).__EVENTS)).toEqual([ | 
					
						
							|  |  |  |     { type: 'mousedown', button: 1, buttons: 4 }, | 
					
						
							|  |  |  |     { type: 'mousedown', button: 0, buttons: 5 }, | 
					
						
							|  |  |  |     { type: 'mouseup', button: 1, buttons: 1 }, | 
					
						
							|  |  |  |     { type: 'mouseup', button: 0, buttons: 0 }, | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | it('should select the text with mouse', async ({ page, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.goto(server.PREFIX + '/input/textarea.html'); | 
					
						
							|  |  |  |   await page.focus('textarea'); | 
					
						
							|  |  |  |   const text = 'This is the text that we are going to try to select. Let\'s see how it goes.'; | 
					
						
							|  |  |  |   await page.keyboard.type(text); | 
					
						
							|  |  |  |   // Firefox needs an extra frame here after typing or it will fail to set the scrollTop
 | 
					
						
							|  |  |  |   await page.evaluate(() => new Promise(requestAnimationFrame)); | 
					
						
							|  |  |  |   await page.evaluate(() => document.querySelector('textarea').scrollTop = 0); | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   const { x, y } = await page.evaluate(dimensions); | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   await page.mouse.move(x + 2, y + 2); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.mouse.down(); | 
					
						
							| 
									
										
										
										
											2022-08-18 20:12:33 +02:00
										 |  |  |   await page.mouse.move(200, 200); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.mouse.up(); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => { | 
					
						
							|  |  |  |     const textarea = document.querySelector('textarea'); | 
					
						
							|  |  |  |     return textarea.value.substring(textarea.selectionStart, textarea.selectionEnd); | 
					
						
							|  |  |  |   })).toBe(text); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | it('should trigger hover state', async ({ page, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.goto(server.PREFIX + '/input/scrollable.html'); | 
					
						
							|  |  |  |   await page.hover('#button-6'); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6'); | 
					
						
							|  |  |  |   await page.hover('#button-2'); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-2'); | 
					
						
							|  |  |  |   await page.hover('#button-91'); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-91'); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | it('should trigger hover state on disabled button', async ({ page, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-14 13:18:32 -07:00
										 |  |  |   await page.goto(server.PREFIX + '/input/scrollable.html'); | 
					
						
							|  |  |  |   await page.$eval('#button-6', (button: HTMLButtonElement) => button.disabled = true); | 
					
						
							|  |  |  |   await page.hover('#button-6', { timeout: 5000 }); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6'); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | it('should trigger hover state with removed window.Node', async ({ page, server }) => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.goto(server.PREFIX + '/input/scrollable.html'); | 
					
						
							|  |  |  |   await page.evaluate(() => delete window.Node); | 
					
						
							|  |  |  |   await page.hover('#button-6'); | 
					
						
							|  |  |  |   expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6'); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | it('should set modifier keys on click', async ({ page, server, browserName, isMac }) => { | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   await page.goto(server.PREFIX + '/input/scrollable.html'); | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |   await page.evaluate(() => document.querySelector('#button-3').addEventListener('mousedown', e => window['lastEvent'] = e, true)); | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   const modifiers = { 'Shift': 'shiftKey', 'Control': 'ctrlKey', 'Alt': 'altKey', 'Meta': 'metaKey' }; | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   // In Firefox, the Meta modifier only exists on Mac
 | 
					
						
							| 
									
										
										
										
											2021-05-13 10:22:23 -07:00
										 |  |  |   if (browserName === 'firefox' && !isMac) | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |     delete modifiers['Meta']; | 
					
						
							|  |  |  |   for (const modifier in modifiers) { | 
					
						
							|  |  |  |     await page.keyboard.down(modifier); | 
					
						
							|  |  |  |     await page.click('#button-3'); | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |     if (!(await page.evaluate(mod => window['lastEvent'][mod], modifiers[modifier]))) | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |       throw new Error(modifiers[modifier] + ' should be true'); | 
					
						
							|  |  |  |     await page.keyboard.up(modifier); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   await page.click('#button-3'); | 
					
						
							|  |  |  |   for (const modifier in modifiers) { | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |     if ((await page.evaluate(mod => window['lastEvent'][mod], modifiers[modifier]))) | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |       throw new Error(modifiers[modifier] + ' should be false'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  | it('should tween mouse movement', async ({ page, browserName, isAndroid }) => { | 
					
						
							| 
									
										
										
										
											2021-04-09 07:59:09 -07:00
										 |  |  |   it.skip(isAndroid, 'Bad rounding'); | 
					
						
							| 
									
										
										
										
											2021-04-04 19:32:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   // The test becomes flaky on WebKit without next line.
 | 
					
						
							| 
									
										
										
										
											2021-05-13 10:22:23 -07:00
										 |  |  |   if (browserName === 'webkit') | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |     await page.evaluate(() => new Promise(requestAnimationFrame)); | 
					
						
							|  |  |  |   await page.mouse.move(100, 100); | 
					
						
							|  |  |  |   await page.evaluate(() => { | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |     window['result'] = []; | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |     document.addEventListener('mousemove', event => { | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |       window['result'].push([event.clientX, event.clientY]); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   await page.mouse.move(200, 300, { steps: 5 }); | 
					
						
							| 
									
										
										
										
											2020-08-03 15:23:53 -07:00
										 |  |  |   expect(await page.evaluate('result')).toEqual([ | 
					
						
							|  |  |  |     [120, 140], | 
					
						
							|  |  |  |     [140, 180], | 
					
						
							|  |  |  |     [160, 220], | 
					
						
							|  |  |  |     [180, 260], | 
					
						
							|  |  |  |     [200, 300] | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-11-23 02:55:32 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-02 22:51:10 +02:00
										 |  |  | it('should always round down', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2021-11-23 02:55:32 -05:00
										 |  |  |   await page.evaluate(() => { | 
					
						
							|  |  |  |     document.addEventListener('mousedown', event => { | 
					
						
							|  |  |  |       window['result'] = [event.clientX, event.clientY]; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.mouse.click(50.1, 50.9); | 
					
						
							|  |  |  |   expect(await page.evaluate('result')).toEqual([50, 50]); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-08-17 15:36:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 01:55:11 -07:00
										 |  |  | it('should not crash on mouse drag with any button', async ({ page }) => { | 
					
						
							| 
									
										
										
										
											2022-08-17 15:36:14 -07:00
										 |  |  |   it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/16609' }); | 
					
						
							|  |  |  |   for (const button of ['left', 'middle', 'right'] as const) { | 
					
						
							|  |  |  |     await page.mouse.move(50, 50); | 
					
						
							|  |  |  |     await page.mouse.down({ button }); | 
					
						
							|  |  |  |     await page.mouse.move(100, 100); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); |