{"record":{"id":"2db04f534818f1f1","repo":"microsoft/playwright","slug":"mouse-wheel-is-not-supported-in-mobile-webkit","errorCode":null,"errorMessage":"Mouse wheel is not supported in mobile WebKit","messagePattern":"Mouse wheel is not supported in mobile WebKit","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/webkit/wkInput.ts","lineNumber":157,"sourceCode":"      clickCount\n    }));\n  }\n\n  async up(progress: Progress, x: number, y: number, button: types.MouseButton, buttons: Set<types.MouseButton>, modifiers: Set<types.KeyboardModifier>, clickCount: number): Promise<void> {\n    await progress.race(this._pageProxySession.send('Input.dispatchMouseEvent', {\n      type: 'up',\n      button,\n      buttons: toButtonsMask(buttons),\n      x,\n      y,\n      modifiers: toModifiersMask(modifiers),\n      clickCount\n    }));\n  }\n\n  async wheel(progress: Progress, x: number, y: number, buttons: Set<types.MouseButton>, modifiers: Set<types.KeyboardModifier>, deltaX: number, deltaY: number): Promise<void> {\n    if (this._page?.browserContext._options.isMobile)\n      throw new Error('Mouse wheel is not supported in mobile WebKit');\n    await progress.race(this._session!.send('Page.updateScrollingState'));\n    // Wheel events hit the compositor first, so wait one frame for it to be synced.\n    await this._page!.mainFrame().evaluateExpression(progress, `new Promise(requestAnimationFrame)`, { world: 'utility' });\n    await progress.race(this._pageProxySession.send('Input.dispatchWheelEvent', {\n      x,\n      y,\n      deltaX,\n      deltaY,\n      modifiers: toModifiersMask(modifiers),\n    }));\n  }\n\n  setPage(page: Page) {\n    this._page = page;\n  }\n}\n\nexport class RawTouchscreenImpl implements input.RawTouchscreen {","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/webkit/wkInput.ts#L139-L175","documentation":"WK mouse input does not support wheel events when the context is emulated as mobile (hasTouch/isMobile => isMobile option). The wheel() method short-circuits before dispatching because mobile WebKit touch scrolling semantics conflict with synthetic wheel dispatch.","triggerScenarios":"Calling page.mouse.wheel(...) (or locator/keyboard-driven scroll-by-wheel) on a context launched with isMobile:true or a device descriptor setting isMobile. Also via tools that synthesize wheel for scrolling.","commonSituations":"Using a mobile device descriptor (iPhone/Pixel presets set isMobile) and then attempting page.mouse.wheel. Mixing desktop scroll idioms into mobile emulation tests.","solutions":["Drop isMobile from context options (or use a non-mobile device descriptor) if you need wheel events.","For mobile emulation, scroll via touch-based APIs (e.g. page.touchscreen.tap/swipe patterns or evaluate window.scrollBy) instead of mouse.wheel.","Branch test logic on the emulation mode: wheel for desktop, touch-scroll for mobile."],"exampleFix":"// before\nconst ctx = await browser.newContext({ ...devices['iPhone 13'] });\nawait page.mouse.wheel(0, 500); // throws\n\n// after\nawait page.evaluate(y => window.scrollBy(0, y), 500);","handlingStrategy":"validation","validationCode":"function supportsWheel(contextOptions) { return !contextOptions.isMobile; }\nif (supportsWheel(ctxOptions)) await page.mouse.wheel(0, 500);\nelse await page.evaluate(y => window.scrollBy(0, y), 500);","typeGuard":"function isMobileContext(opts: { isMobile?: boolean }): boolean { return !!opts.isMobile; }","tryCatchPattern":"try { await page.mouse.wheel(0, 500); }\ncatch (e) {\n  if (/mobile WebKit/.test(e.message)) await page.evaluate(y => window.scrollBy(0, y), 500);\n  else throw e;\n}","preventionTips":["Don't combine mobile device descriptors with mouse.wheel.","Branch scroll strategy on emulation mode."],"tags":["webkit","input","mouse","mobile","emulation"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}