[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

feat(browser): add `tripleClick` to interactive api (#5987)

authored by

Joaquín Sánchez and committed by
GitHub
(Jun 28, 2024, 10:38 AM +0200) 200a4349 152891b3

+124 -1
+25
docs/guide/browser.md
··· 551 551 - [WebdriverIO `element.doubleClick` API](https://webdriver.io/docs/api/element/doubleClick/) 552 552 - [testing-library `dblClick` API](https://testing-library.com/docs/user-event/convenience/#dblClick) 553 553 554 + ### userEvent.tripleClick 555 + 556 + - **Type:** `(element: Element, options?: UserEventTripleClickOptions) => Promise<void>` 557 + 558 + Triggers a triple click event on an element 559 + 560 + Please refer to your provider's documentation for detailed explanation about how this method works. 561 + 562 + ```ts 563 + import { userEvent } from '@vitest/browser/context' 564 + import { screen } from '@testing-library/dom' 565 + 566 + test('triggers a triple click on an element', async () => { 567 + const logo = screen.getByRole('img', { name: /logo/ }) 568 + 569 + await userEvent.tripleClick(logo) 570 + }) 571 + ``` 572 + 573 + References: 574 + 575 + - [Playwright `locator.click` API](https://playwright.dev/docs/api/class-locator#locator-click) 576 + - [WebdriverIO `browser.action` API](https://webdriver.io/docs/api/browser/action/) 577 + - [testing-library `tripleClick` API](https://testing-library.com/docs/user-event/convenience/#tripleClick) 578 + 554 579 ### userEvent.fill 555 580 556 581 - **Type:** `(element: Element, text: string) => Promise<void>`
+8
packages/browser/context.d.ts
··· 61 61 */ 62 62 dblClick: (element: Element, options?: UserEventDoubleClickOptions) => Promise<void> 63 63 /** 64 + * Triggers a triple click event on an element. Uses provider's API under the hood. 65 + * @see {@link https://playwright.dev/docs/api/class-locator#locator-click} Playwright API: using `click` with `clickCount: 3` 66 + * @see {@link https://webdriver.io/docs/api/browser/actions/} WebdriverIO API: using actions with `move` and 3 `down + up + down` events in a row 67 + * @see {@link https://testing-library.com/docs/user-event/convenience/#tripleclick} testing-library API 68 + */ 69 + tripleClick: (element: Element, options?: UserEventTripleClickOptions) => Promise<void> 70 + /** 64 71 * Choose one or more values from a select element. Uses provider's API under the hood. 65 72 * If select doesn't have `multiple` attribute, only the first value will be selected. 66 73 * @example ··· 165 172 export interface UserEventSelectOptions {} 166 173 export interface UserEventClickOptions {} 167 174 export interface UserEventDoubleClickOptions {} 175 + export interface UserEventTripleClickOptions {} 168 176 export interface UserEventDragAndDropOptions {} 169 177 170 178 export interface UserEventTabOptions {
+46
test/browser/test/userEvent.test.ts
··· 75 75 }) 76 76 }) 77 77 78 + describe('userEvent.tripleClick', () => { 79 + test('correctly clicks a button', async () => { 80 + const button = document.createElement('button') 81 + button.textContent = 'Click me' 82 + document.body.appendChild(button) 83 + const onClick = vi.fn() 84 + const dblClick = vi.fn() 85 + const tripleClick = vi.fn() 86 + button.addEventListener('click', onClick) 87 + button.addEventListener('dblclick', dblClick) 88 + button.addEventListener('click', tripleClick) 89 + 90 + await userEvent.tripleClick(button) 91 + 92 + expect(onClick).toHaveBeenCalledTimes(3) 93 + expect(dblClick).toHaveBeenCalledTimes(1) 94 + expect(tripleClick).toHaveBeenCalledTimes(3) 95 + expect(tripleClick.mock.calls.length).toBe(3) 96 + expect(tripleClick.mock.calls 97 + .map(c => c[0] as MouseEvent) 98 + .filter(c => c.detail === 3)).toHaveLength(1) 99 + }) 100 + 101 + test('correctly doesn\'t click on a disabled button', async () => { 102 + const button = document.createElement('button') 103 + button.textContent = 'Click me' 104 + button.disabled = true 105 + document.body.appendChild(button) 106 + const onClick = vi.fn() 107 + const dblClick = vi.fn() 108 + const tripleClick = vi.fn() 109 + button.addEventListener('click', onClick) 110 + button.addEventListener('dblclick', dblClick) 111 + button.addEventListener('click', tripleClick) 112 + 113 + await userEvent.tripleClick(button, { 114 + // playwright requires force: true to click on a disabled button 115 + force: true, 116 + }) 117 + 118 + expect(onClick).not.toHaveBeenCalled() 119 + expect(dblClick).not.toHaveBeenCalled() 120 + expect(tripleClick).not.toHaveBeenCalled() 121 + }) 122 + }) 123 + 78 124 describe('userEvent.hover, userEvent.unhover', () => { 79 125 test('hover works correctly', async () => { 80 126 const target = document.createElement('div')
+4
packages/browser/src/client/tester/context.ts
··· 73 73 const xpath = convertElementToXPath(element) 74 74 return triggerCommand('__vitest_dblClick', xpath, options) 75 75 }, 76 + tripleClick(element: Element, options: UserEventClickOptions = {}) { 77 + const xpath = convertElementToXPath(element) 78 + return triggerCommand('__vitest_tripleClick', xpath, options) 79 + }, 76 80 selectOptions(element, value) { 77 81 const values = provider === 'webdriverio' 78 82 ? getWebdriverioSelectOptions(element, value)
+39
packages/browser/src/node/commands/click.ts
··· 45 45 throw new TypeError(`Provider "${provider.name}" doesn't support dblClick command`) 46 46 } 47 47 } 48 + 49 + export const tripleClick: UserEventCommand<UserEvent['tripleClick']> = async ( 50 + context, 51 + xpath, 52 + options = {}, 53 + ) => { 54 + const provider = context.provider 55 + if (provider instanceof PlaywrightBrowserProvider) { 56 + const tester = context.iframe 57 + await tester.locator(`xpath=${xpath}`).click({ 58 + timeout: 1000, 59 + ...options, 60 + clickCount: 3, 61 + }) 62 + } 63 + else if (provider instanceof WebdriverBrowserProvider) { 64 + const browser = context.browser 65 + const markedXpath = `//${xpath}` 66 + await browser 67 + .action('pointer', { parameters: { pointerType: 'mouse' } }) 68 + // move the pointer over the button 69 + .move({ origin: await browser.$(markedXpath) }) 70 + // simulate 3 clicks 71 + .down() 72 + .up() 73 + .pause(50) 74 + .down() 75 + .up() 76 + .pause(50) 77 + .down() 78 + .up() 79 + .pause(50) 80 + // run the sequence 81 + .perform() 82 + } 83 + else { 84 + throw new TypeError(`Provider "${provider.name}" doesn't support tripleClick command`) 85 + } 86 + }
+2 -1
packages/browser/src/node/commands/index.ts
··· 1 - import { click, dblClick } from './click' 1 + import { click, dblClick, tripleClick } from './click' 2 2 import { type } from './type' 3 3 import { clear } from './clear' 4 4 import { fill } from './fill' ··· 20 20 writeFile, 21 21 __vitest_click: click, 22 22 __vitest_dblClick: dblClick, 23 + __vitest_tripleClick: tripleClick, 23 24 __vitest_screenshot: screenshot, 24 25 __vitest_type: type, 25 26 __vitest_clear: clear,