diff --git a/packages/browser/src/client/orchestrator.ts b/packages/browser/src/client/orchestrator.ts index 76d56d3ee..6888d7dcb 100644 --- a/packages/browser/src/client/orchestrator.ts +++ b/packages/browser/src/client/orchestrator.ts @@ -306,9 +306,13 @@ async function setIframeViewport( await ui.setIframeViewport(width, height) } else if (getBrowserState().provider === 'webdriverio') { - iframe.style.width = `${width}px` - iframe.style.height = `${height}px` iframe.parentElement?.setAttribute('data-scale', '1') + await client.rpc.triggerCommand( + getBrowserState().sessionId, + '__vitest_viewport', + undefined, + [{ width, height }], + ) } else { const scale = Math.min( diff --git a/packages/browser/src/node/commands/index.ts b/packages/browser/src/node/commands/index.ts index 8adfd1aa5..d6dee10c3 100644 --- a/packages/browser/src/node/commands/index.ts +++ b/packages/browser/src/node/commands/index.ts @@ -15,6 +15,7 @@ import { selectOptions } from './select' import { tab } from './tab' import { type } from './type' import { upload } from './upload' +import { viewport } from './viewport' export default { readFile: readFile as typeof readFile, @@ -35,4 +36,5 @@ export default { __vitest_dragAndDrop: dragAndDrop as typeof dragAndDrop, __vitest_hover: hover as typeof hover, __vitest_cleanup: keyboardCleanup as typeof keyboardCleanup, + __vitest_viewport: viewport as typeof viewport, } diff --git a/packages/browser/src/node/commands/viewport.ts b/packages/browser/src/node/commands/viewport.ts new file mode 100644 index 000000000..502921c12 --- /dev/null +++ b/packages/browser/src/node/commands/viewport.ts @@ -0,0 +1,14 @@ +import type { UserEventCommand } from './utils' +import { WebdriverBrowserProvider } from '../providers/webdriver' + +export const viewport: UserEventCommand<(options: { + width: number + height: number +}) => void> = async (context, options) => { + if (context.provider instanceof WebdriverBrowserProvider) { + await context.provider.setViewport(options) + } + else { + throw new TypeError(`Provider ${context.provider.name} doesn't support "viewport" command`) + } +} diff --git a/packages/browser/src/node/pool.ts b/packages/browser/src/node/pool.ts index c268634ac..a7a08ad10 100644 --- a/packages/browser/src/node/pool.ts +++ b/packages/browser/src/node/pool.ts @@ -69,8 +69,7 @@ export function createBrowserPool(vitest: Vitest): ProcessPool { isCancelled = true }) - const groupedSpecifications = [...groupedFiles.entries()] - const initialisedPools = (await Promise.all(groupedSpecifications.map(async ([project, files]) => { + const initialisedPools = await Promise.all([...groupedFiles.entries()].map(async ([project, files]) => { await project._initBrowserProvider() if (!project.browser) { @@ -92,7 +91,7 @@ export function createBrowserPool(vitest: Vitest): ProcessPool { provider: project.browser!.provider, runTests: () => pool.runTests(method, files), } - }))) + })) if (isCancelled) { return diff --git a/packages/browser/src/node/providers/webdriver.ts b/packages/browser/src/node/providers/webdriver.ts index 6d8287dbd..a8ec41c65 100644 --- a/packages/browser/src/node/providers/webdriver.ts +++ b/packages/browser/src/node/providers/webdriver.ts @@ -28,6 +28,8 @@ export class WebdriverBrowserProvider implements BrowserProvider { private options?: Capabilities.WebdriverIOConfig private closing = false + private iframeSwitched = false + private topLevelContext: string | undefined getSupportedBrowsers(): readonly string[] { return webdriverBrowsers @@ -43,6 +45,10 @@ export class WebdriverBrowserProvider implements BrowserProvider { this.options = options as Capabilities.WebdriverIOConfig } + isIframeSwitched(): boolean { + return this.iframeSwitched + } + async switchToTestFrame(): Promise { const page = this.browser! // support wdio@9 @@ -56,6 +62,7 @@ export class WebdriverBrowserProvider implements BrowserProvider { ) await page.switchToFrame(iframe) } + this.iframeSwitched = true } async switchToMainFrame(): Promise { @@ -66,6 +73,21 @@ export class WebdriverBrowserProvider implements BrowserProvider { else { await page.switchToParentFrame() } + this.iframeSwitched = false + } + + async setViewport(options: { width: number; height: number }): Promise { + if (this.topLevelContext == null || !this.browser) { + throw new Error(`The browser has no open pages.`) + } + await this.browser.send({ + method: 'browsingContext.setViewport', + params: { + context: this.topLevelContext, + devicePixelRatio: 1, + viewport: options, + }, + }) } getCommandsContext(): { @@ -153,6 +175,7 @@ export class WebdriverBrowserProvider implements BrowserProvider { const browserInstance = await this.openBrowser() debug?.('[%s][%s] browser page is created, opening %s', sessionId, this.browserName, url) await browserInstance.url(url) + this.topLevelContext = await browserInstance.getWindowHandle() await this._throwIfClosing('opening the url') } diff --git a/packages/ui/client/auto-imports.d.ts b/packages/ui/client/auto-imports.d.ts index 8a28dee61..021bd219e 100644 --- a/packages/ui/client/auto-imports.d.ts +++ b/packages/ui/client/auto-imports.d.ts @@ -155,6 +155,7 @@ declare global { const unref: typeof import('vue')['unref'] const unrefElement: typeof import('@vueuse/core')['unrefElement'] const until: typeof import('@vueuse/core')['until'] + const updateBrowserPanel: typeof import('./composables/navigation')['updateBrowserPanel'] const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] const useAnimate: typeof import('@vueuse/core')['useAnimate'] const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference'] diff --git a/packages/ui/client/components/BrowserIframe.vue b/packages/ui/client/components/BrowserIframe.vue index 5a194b5a2..d93df9c19 100644 --- a/packages/ui/client/components/BrowserIframe.vue +++ b/packages/ui/client/components/BrowserIframe.vue @@ -1,11 +1,13 @@