Skip to content

Commit

Permalink
feat(browser): support actionTimeout as playwright provider options (
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa authored Dec 1, 2024
1 parent a485b32 commit e2c29ea
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 27 deletions.
4 changes: 4 additions & 0 deletions packages/browser/matchers.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ declare module 'vitest' {
type PromisifyDomAssertion<T> = Promisify<Assertion<T>>

interface ExpectStatic {
/**
* `expect.element(locator)` is a shorthand for `expect.poll(() => locator.element())`.
* You can set default timeout via `expect.poll.timeout` config.
*/
element: <T extends Element | Locator>(element: T, options?: ExpectPollOptions) => PromisifyDomAssertion<Awaited<Element | null>>
}
}
Expand Down
8 changes: 7 additions & 1 deletion packages/browser/providers/playwright.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ declare module 'vitest/node' {
context?: Omit<
BrowserContextOptions,
'ignoreHTTPSErrors' | 'serviceWorkers'
>
> & {
/**
* The maximum time in milliseconds to wait for `userEvent` action to complete.
* @default 0 (no timeout)
*/
actionTimeout?: number
}
}

export interface BrowserCommandContext {
Expand Down
4 changes: 1 addition & 3 deletions packages/browser/src/node/commands/clear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ export const clear: UserEventCommand<UserEvent['clear']> = async (
if (context.provider instanceof PlaywrightBrowserProvider) {
const { iframe } = context
const element = iframe.locator(selector)
await element.clear({
timeout: 1000,
})
await element.clear()
}
else if (context.provider instanceof WebdriverBrowserProvider) {
const browser = context.browser
Expand Down
6 changes: 1 addition & 5 deletions packages/browser/src/node/commands/click.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ export const click: UserEventCommand<UserEvent['click']> = async (
const provider = context.provider
if (provider instanceof PlaywrightBrowserProvider) {
const tester = context.iframe
await tester.locator(selector).click({
timeout: 1000,
...options,
})
await tester.locator(selector).click(options)
}
else if (provider instanceof WebdriverBrowserProvider) {
const browser = context.browser
Expand Down Expand Up @@ -53,7 +50,6 @@ export const tripleClick: UserEventCommand<UserEvent['tripleClick']> = async (
if (provider instanceof PlaywrightBrowserProvider) {
const tester = context.iframe
await tester.locator(selector).click({
timeout: 1000,
...options,
clickCount: 3,
})
Expand Down
5 changes: 1 addition & 4 deletions packages/browser/src/node/commands/dragAndDrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ export const dragAndDrop: UserEventCommand<UserEvent['dragAndDrop']> = async (
await frame.dragAndDrop(
source,
target,
{
timeout: 1000,
...options_,
},
options_,
)
}
else if (context.provider instanceof WebdriverBrowserProvider) {
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/src/node/commands/fill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const fill: UserEventCommand<UserEvent['fill']> = async (
if (context.provider instanceof PlaywrightBrowserProvider) {
const { iframe } = context
const element = iframe.locator(selector)
await element.fill(text, { timeout: 1000, ...options })
await element.fill(text, options)
}
else if (context.provider instanceof WebdriverBrowserProvider) {
const browser = context.browser
Expand Down
5 changes: 1 addition & 4 deletions packages/browser/src/node/commands/hover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ export const hover: UserEventCommand<UserEvent['hover']> = async (
options = {},
) => {
if (context.provider instanceof PlaywrightBrowserProvider) {
await context.iframe.locator(selector).hover({
timeout: 1000,
...options,
})
await context.iframe.locator(selector).hover(options)
}
else if (context.provider instanceof WebdriverBrowserProvider) {
const browser = context.browser
Expand Down
1 change: 0 additions & 1 deletion packages/browser/src/node/commands/screenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export const screenshot: BrowserCommand<[string, ScreenshotOptions]> = async (
const { element: selector, ...config } = options
const element = context.iframe.locator(`${selector}`)
const buffer = await element.screenshot({
timeout: 1000,
...config,
path: savePath,
})
Expand Down
5 changes: 1 addition & 4 deletions packages/browser/src/node/commands/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ export const selectOptions: UserEventCommand<UserEvent['selectOptions']> = async
return elementHandler
})) as (readonly string[]) | (readonly ElementHandle[])

await selectElement.selectOption(values, {
timeout: 1000,
...options,
})
await selectElement.selectOption(values, options)
}
else if (context.provider instanceof WebdriverBrowserProvider) {
const values = userValues as any as [({ index: number })]
Expand Down
10 changes: 7 additions & 3 deletions packages/browser/src/node/providers/playwright.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class PlaywrightBrowserProvider implements BrowserProvider {

private options?: {
launch?: LaunchOptions
context?: BrowserContextOptions
context?: BrowserContextOptions & { actionTimeout?: number }
}

public contexts = new Map<string, BrowserContext>()
Expand Down Expand Up @@ -108,15 +108,19 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
}

const browser = await this.openBrowser()
const { actionTimeout, ...contextOptions } = this.options?.context ?? {}
const options = {
...this.options?.context,
...contextOptions,
ignoreHTTPSErrors: true,
serviceWorkers: 'allow',
} satisfies BrowserContextOptions
if (this.project.config.browser.ui) {
options.viewport = null
}
const context = await browser.newContext(options)
if (actionTimeout) {
context.setDefaultTimeout(actionTimeout)
}
this.contexts.set(contextId, context)
return context
}
Expand Down Expand Up @@ -187,7 +191,7 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
async openPage(contextId: string, url: string, beforeNavigate?: () => Promise<void>) {
const browserPage = await this.openBrowserPage(contextId)
await beforeNavigate?.()
await browserPage.goto(url)
await browserPage.goto(url, { timeout: 0 })
}

async getCDPSession(contextId: string) {
Expand Down
21 changes: 21 additions & 0 deletions test/browser/fixtures/timeout/timeout.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { page } from '@vitest/browser/context';
import { afterEach, expect, test } from 'vitest';

afterEach(() => {
document.body.innerHTML = ''
})

test('click default', async () => {
document.body.innerHTML = '<div><span>hello</span></div>'
await page.getByText('world').click()
})

test('click override', async () => {
document.body.innerHTML = '<div><span>hello</span></div>'
await page.getByText('world').click({ timeout: 345 })
})

test('element', async () => {
document.body.innerHTML = '<div><span>hello</span></div>'
await expect.element(page.getByText('world')).toBeVisible()
})
27 changes: 27 additions & 0 deletions test/browser/fixtures/timeout/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vitest/config'

const provider = process.env.PROVIDER || 'playwright'
const name =
process.env.BROWSER || (provider === 'playwright' ? 'chromium' : 'chrome')

export default defineConfig({
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
test: {
browser: {
enabled: true,
provider,
name,
providerOptions: {
context: {
actionTimeout: 500
}
}
},
expect: {
poll: {
timeout: 500
}
}
},
})
16 changes: 15 additions & 1 deletion test/browser/specs/runner.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readFile } from 'node:fs/promises'
import { beforeAll, describe, expect, onTestFailed, test } from 'vitest'
import { browser, runBrowserTests } from './utils'
import { browser, provider, runBrowserTests } from './utils'

describe('running browser tests', async () => {
let stderr: string
Expand Down Expand Up @@ -153,3 +153,17 @@ test('user-event', async () => {
}
`)
})

test('timeout', async () => {
const { stderr } = await runBrowserTests({
root: './fixtures/timeout',
})
expect(stderr).toContain('Matcher did not succeed in 500ms')
if (provider === 'playwright') {
expect(stderr).toContain('locator.click: Timeout 500ms exceeded.')
expect(stderr).toContain('locator.click: Timeout 345ms exceeded.')
}
if (provider === 'webdriverio') {
expect(stderr).toContain('Cannot find element with locator')
}
})

0 comments on commit e2c29ea

Please sign in to comment.