Skip to content

Commit c23b0f7

Browse files
authored
fix(wdio): don't scale browser in headless mode (#8033)
1 parent cefd4ba commit c23b0f7

File tree

15 files changed

+126
-17
lines changed

15 files changed

+126
-17
lines changed

packages/browser/src/client/orchestrator.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,13 @@ async function setIframeViewport(
306306
await ui.setIframeViewport(width, height)
307307
}
308308
else if (getBrowserState().provider === 'webdriverio') {
309-
iframe.style.width = `${width}px`
310-
iframe.style.height = `${height}px`
311309
iframe.parentElement?.setAttribute('data-scale', '1')
310+
await client.rpc.triggerCommand(
311+
getBrowserState().sessionId,
312+
'__vitest_viewport',
313+
undefined,
314+
[{ width, height }],
315+
)
312316
}
313317
else {
314318
const scale = Math.min(

packages/browser/src/node/commands/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { selectOptions } from './select'
1515
import { tab } from './tab'
1616
import { type } from './type'
1717
import { upload } from './upload'
18+
import { viewport } from './viewport'
1819

1920
export default {
2021
readFile: readFile as typeof readFile,
@@ -35,4 +36,5 @@ export default {
3536
__vitest_dragAndDrop: dragAndDrop as typeof dragAndDrop,
3637
__vitest_hover: hover as typeof hover,
3738
__vitest_cleanup: keyboardCleanup as typeof keyboardCleanup,
39+
__vitest_viewport: viewport as typeof viewport,
3840
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { UserEventCommand } from './utils'
2+
import { WebdriverBrowserProvider } from '../providers/webdriver'
3+
4+
export const viewport: UserEventCommand<(options: {
5+
width: number
6+
height: number
7+
}) => void> = async (context, options) => {
8+
if (context.provider instanceof WebdriverBrowserProvider) {
9+
await context.provider.setViewport(options)
10+
}
11+
else {
12+
throw new TypeError(`Provider ${context.provider.name} doesn't support "viewport" command`)
13+
}
14+
}

packages/browser/src/node/pool.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ export function createBrowserPool(vitest: Vitest): ProcessPool {
6969
isCancelled = true
7070
})
7171

72-
const groupedSpecifications = [...groupedFiles.entries()]
73-
const initialisedPools = (await Promise.all(groupedSpecifications.map(async ([project, files]) => {
72+
const initialisedPools = await Promise.all([...groupedFiles.entries()].map(async ([project, files]) => {
7473
await project._initBrowserProvider()
7574

7675
if (!project.browser) {
@@ -92,7 +91,7 @@ export function createBrowserPool(vitest: Vitest): ProcessPool {
9291
provider: project.browser!.provider,
9392
runTests: () => pool.runTests(method, files),
9493
}
95-
})))
94+
}))
9695

9796
if (isCancelled) {
9897
return

packages/browser/src/node/providers/webdriver.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export class WebdriverBrowserProvider implements BrowserProvider {
2828
private options?: Capabilities.WebdriverIOConfig
2929

3030
private closing = false
31+
private iframeSwitched = false
32+
private topLevelContext: string | undefined
3133

3234
getSupportedBrowsers(): readonly string[] {
3335
return webdriverBrowsers
@@ -43,6 +45,10 @@ export class WebdriverBrowserProvider implements BrowserProvider {
4345
this.options = options as Capabilities.WebdriverIOConfig
4446
}
4547

48+
isIframeSwitched(): boolean {
49+
return this.iframeSwitched
50+
}
51+
4652
async switchToTestFrame(): Promise<void> {
4753
const page = this.browser!
4854
// support wdio@9
@@ -56,6 +62,7 @@ export class WebdriverBrowserProvider implements BrowserProvider {
5662
)
5763
await page.switchToFrame(iframe)
5864
}
65+
this.iframeSwitched = true
5966
}
6067

6168
async switchToMainFrame(): Promise<void> {
@@ -66,6 +73,21 @@ export class WebdriverBrowserProvider implements BrowserProvider {
6673
else {
6774
await page.switchToParentFrame()
6875
}
76+
this.iframeSwitched = false
77+
}
78+
79+
async setViewport(options: { width: number; height: number }): Promise<void> {
80+
if (this.topLevelContext == null || !this.browser) {
81+
throw new Error(`The browser has no open pages.`)
82+
}
83+
await this.browser.send({
84+
method: 'browsingContext.setViewport',
85+
params: {
86+
context: this.topLevelContext,
87+
devicePixelRatio: 1,
88+
viewport: options,
89+
},
90+
})
6991
}
7092

7193
getCommandsContext(): {
@@ -153,6 +175,7 @@ export class WebdriverBrowserProvider implements BrowserProvider {
153175
const browserInstance = await this.openBrowser()
154176
debug?.('[%s][%s] browser page is created, opening %s', sessionId, this.browserName, url)
155177
await browserInstance.url(url)
178+
this.topLevelContext = await browserInstance.getWindowHandle()
156179
await this._throwIfClosing('opening the url')
157180
}
158181

packages/ui/client/auto-imports.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ declare global {
155155
const unref: typeof import('vue')['unref']
156156
const unrefElement: typeof import('@vueuse/core')['unrefElement']
157157
const until: typeof import('@vueuse/core')['until']
158+
const updateBrowserPanel: typeof import('./composables/navigation')['updateBrowserPanel']
158159
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
159160
const useAnimate: typeof import('@vueuse/core')['useAnimate']
160161
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']

packages/ui/client/components/BrowserIframe.vue

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<script setup lang="ts">
22
import type { ViewportSize } from '~/composables/browser'
33
import { viewport } from '~/composables/browser'
4+
import { browserState } from '~/composables/client'
45
import {
56
hideRightPanel,
67
panels,
78
showNavigationPanel,
89
showRightPanel,
10+
updateBrowserPanel,
911
} from '~/composables/navigation'
1012
1113
const sizes: Record<ViewportSize, [width: number, height: number]> = {
@@ -19,16 +21,24 @@ function isViewport(name: ViewportSize) {
1921
return viewport.value[0] === preset[0] && viewport.value[1] === preset[1]
2022
}
2123
24+
const { width: windowWidth, height: windowHeight } = useWindowSize()
25+
2226
async function changeViewport(name: ViewportSize) {
2327
viewport.value = sizes[name]
28+
if (browserState?.provider === 'webdriverio') {
29+
updateBrowserPanel()
30+
}
2431
}
2532
26-
const { width: windowWidth, height: windowHeight } = useWindowSize()
27-
2833
const PADDING_SIDES = 20
2934
const PADDING_TOP = 100
3035
3136
const containerSize = computed(() => {
37+
if (browserState?.provider === 'webdriverio') {
38+
const [width, height] = viewport.value
39+
return { width, height }
40+
}
41+
3242
const parentContainerWidth = windowWidth.value * (panels.details.size / 100)
3343
const parentOffsetWidth = parentContainerWidth * (panels.details.browser / 100)
3444
const containerWidth = parentOffsetWidth - PADDING_SIDES
@@ -40,6 +50,10 @@ const containerSize = computed(() => {
4050
})
4151
4252
const scale = computed(() => {
53+
if (browserState?.provider === 'webdriverio') {
54+
return 1
55+
}
56+
4357
const [iframeWidth, iframeHeight] = viewport.value
4458
const { width: containerWidth, height: containerHeight } = containerSize.value
4559
const widthScale = containerWidth > iframeWidth ? 1 : containerWidth / iframeWidth

packages/ui/client/components/views/ViewConsoleOutput.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ function getTaskName(id?: string) {
3535
/>
3636
</div>
3737
</div>
38-
<p v-else p6>
38+
<div v-else p6>
3939
Log something in your test and it would print here. (e.g. <pre inline>console.log(foo)</pre>)
40-
</p>
40+
</div>
4141
</template>

packages/ui/client/composables/api.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { BrowserUI } from 'vitest'
22
import { viewport } from './browser'
3-
import { findById } from './client'
3+
import { browserState, findById } from './client'
4+
import { updateBrowserPanel } from './navigation'
45

56
export const ui: BrowserUI = {
67
setCurrentFileId(fileId: string) {
@@ -11,6 +12,9 @@ export const ui: BrowserUI = {
1112
async setIframeViewport(width: number, height: number) {
1213
// reset the button before setting a custom viewport
1314
viewport.value = [width, height]
15+
if (browserState?.provider === 'webdriverio') {
16+
updateBrowserPanel()
17+
}
1418
await new Promise(r => requestAnimationFrame(r))
1519
},
1620
}

packages/ui/client/composables/client/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,13 @@ export function runCurrent() {
137137
// for testing during dev
138138
// export const browserState: BrowserRunnerState = {
139139
// files: [],
140-
// config: {},
140+
// config: {
141+
// browser: {
142+
// name: 'chrome',
143+
// }
144+
// } as any,
141145
// type: 'orchestrator',
146+
// provider: 'webdriverio',
142147
// wrapModule: () => {},
143148
// }
144149
// @ts-expect-error not typed global

0 commit comments

Comments
 (0)