feat(browser): add userEvent.wheel API#9188
Conversation
7d5bc4b to
6d66ee5
Compare
|
Looks like there's a huge difference in running times between Firefox and Chrome in WebdriverIO: In Playwright all timings are roughly aligned, but all are ~4x slower than Firefox in WebdriverIO: |
6a8e51f to
14530f8
Compare
✅ Deploy Preview for vitest-dev ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
d786dca to
64aed3e
Compare
|
|
||
| const DEFAULT_WHEEL_DELTA = 100 | ||
|
|
||
| export function resolveUserEventWheelOptions(options: UserEventWheelOptions): UserEventWheelOptionsWithDelta { |
There was a problem hiding this comment.
Not entirely sure whether this is the best place for this function.
| if (browser === 'chromium' || browser === 'chrome') { | ||
| return new Promise((resolve) => { | ||
| requestAnimationFrame(() => { | ||
| resolve() | ||
| }) | ||
| }) | ||
| } |
There was a problem hiding this comment.
As said in another comment, I'm not sure if this branching is worth it or if we should just resolve the promise after a frame on all browsers.
The tricky part is that sometimes, on resource-constrained machines (~CI), one frame might not be enough. From my testing this happens rarely tho, maybe a couple of times in 50 runs (with repeats). A "proper" solution would be waiting for the event to fire with a listener, but we risk not resolving the promise if user-code intercepts and stops the propagation of the event.
packages/browser/context.d.ts
Outdated
| export type UserEventWheelOptions = ExactlyOneOf< | ||
| { | ||
| /** | ||
| * Precise scroll delta values in pixels. At least one axis must be specified. | ||
| * | ||
| * - Positive `y` scrolls down, negative `y` scrolls up. | ||
| * - Positive `x` scrolls right, negative `x` scrolls left. | ||
| */ | ||
| delta: AtLeastOneOf<{ x: number, y: number }>, | ||
| /** | ||
| * Semantic scroll direction. Use this for readable tests when exact pixel values don't matter. | ||
| */ | ||
| direction: 'up' | 'down' | 'left' | 'right', | ||
| /** | ||
| * Number of wheel events to fire. Defaults to `1`. | ||
| * | ||
| * Useful for simulating multiple scroll steps in a single call. | ||
| */ | ||
| times?: number, | ||
| }, | ||
| 'delta' | 'direction' | ||
| > |
There was a problem hiding this comment.
I can rewrite this type without using any helpers, but thought they might be useful for other types too.
There was a problem hiding this comment.
Honestly, to me this just looks like overengineering, there are just two unions, it might be easier (for readability) to just define them
docs/api/browser/interactivity.md
Outdated
| - [WebdriverIO `browser.action` API](https://webdriver.io/docs/api/browser/action/): implemented via actions api with `move` plus three `down + up + pause` events in a row | ||
| - [testing-library `tripleClick` API](https://testing-library.com/docs/user-event/convenience/#tripleClick) | ||
|
|
||
| ## userEvent.wheel |
There was a problem hiding this comment.
| ## userEvent.wheel | |
| ## userEvent.wheel <Version>4.1.0</Version> {#userevent-wheel} |
docs/api/browser/interactivity.md
Outdated
| ): Promise<void> | ||
| ``` | ||
|
|
||
| Triggers a wheel event on an element. This is useful for testing any UI that responds to wheel events. |
There was a problem hiding this comment.
| Triggers a wheel event on an element. This is useful for testing any UI that responds to wheel events. | |
| Triggers a [wheel event](https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event) on an element. This is useful for testing any UI that responds to wheel events. |
There was a problem hiding this comment.
Good suggestion, I'll add the link in the JSDocs too.
I think I should also add to not use this for general scrolling but rely on automatic scrolling other userEvent methods have built-in.
docs/api/browser/interactivity.md
Outdated
|
|
||
| Triggers a wheel event on an element. This is useful for testing any UI that responds to wheel events. | ||
|
|
||
| You can specify the scroll amount using either `delta` for precise pixel-based control, or `direction` for simpler directional scrolling (`up`, `down`, `left`, `right`). When you need to trigger multiple wheel events, use the `times` option rather than calling the method multiple times. |
There was a problem hiding this comment.
| You can specify the scroll amount using either `delta` for precise pixel-based control, or `direction` for simpler directional scrolling (`up`, `down`, `left`, `right`). When you need to trigger multiple wheel events, use the `times` option rather than calling the method multiple times. | |
| You can specify the scroll amount using either `delta` for precise pixel-based control, or `direction` for simpler directional scrolling (`up`, `down`, `left`, `right`). When you need to trigger multiple wheel events, use the `times` option rather than calling the method multiple times for better performance. |
docs/api/browser/interactivity.md
Outdated
| }) | ||
| ``` | ||
|
|
||
| Wheel events can also be triggered directly from locators: |
There was a problem hiding this comment.
| Wheel events can also be triggered directly from locators: | |
| Wheel events can also be triggered directly from [locators](/api/browser/locator#wheel): |
docs/api/browser/locators.md
Outdated
|
|
||
| - [See more at `userEvent.tripleClick`](/api/browser/interactivity#userevent-tripleclick) | ||
|
|
||
| ### wheel |
There was a problem hiding this comment.
| ### wheel | |
| ### wheel <Version>4.1.0</Version> |
docs/api/browser/locators.md
Outdated
| function wheel(options: UserEventWheelOptions): Promise<void> | ||
| ``` | ||
|
|
||
| Triggers a wheel event on an element. You can use the options to choose a general scroll `direction` or a precise `delta` value. |
There was a problem hiding this comment.
| Triggers a wheel event on an element. You can use the options to choose a general scroll `direction` or a precise `delta` value. | |
| Triggers a [wheel event](https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event) on an element. You can use the options to choose a general scroll `direction` or a precise `delta` value. |
packages/browser/context.d.ts
Outdated
| export type UserEventWheelOptions = ExactlyOneOf< | ||
| { | ||
| /** | ||
| * Precise scroll delta values in pixels. At least one axis must be specified. | ||
| * | ||
| * - Positive `y` scrolls down, negative `y` scrolls up. | ||
| * - Positive `x` scrolls right, negative `x` scrolls left. | ||
| */ | ||
| delta: AtLeastOneOf<{ x: number, y: number }>, | ||
| /** | ||
| * Semantic scroll direction. Use this for readable tests when exact pixel values don't matter. | ||
| */ | ||
| direction: 'up' | 'down' | 'left' | 'right', | ||
| /** | ||
| * Number of wheel events to fire. Defaults to `1`. | ||
| * | ||
| * Useful for simulating multiple scroll steps in a single call. | ||
| */ | ||
| times?: number, | ||
| }, | ||
| 'delta' | 'direction' | ||
| > |
There was a problem hiding this comment.
Honestly, to me this just looks like overengineering, there are just two unions, it might be easier (for readability) to just define them
|
Applied the suggestions and split the type (used different interfaces as I was extracting a subtype anyway for the server function) |
f19937c to
4d3f4eb
Compare
This MR contains the following updates: | Package | Type | Update | Change | OpenSSF | |---|---|---|---|---| | [@openapitools/openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli) | devDependencies | minor | [`2.29.0` → `2.30.2`](https://renovatebot.com/diffs/npm/@openapitools%2fopenapi-generator-cli/2.29.0/2.30.2) | [](https://securityscorecards.dev/viewer/?uri=github.com/OpenAPITools/openapi-generator-cli) | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | devDependencies | minor | [`24.10.13` → `24.12.0`](https://renovatebot.com/diffs/npm/@types%2fnode/24.10.13/24.12.0) | [](https://securityscorecards.dev/viewer/?uri=github.com/DefinitelyTyped/DefinitelyTyped) | | [@typescript-eslint/eslint-plugin](https://typescript-eslint.io/packages/eslint-plugin) ([source](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin)) | devDependencies | minor | [`8.56.1` → `8.57.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/8.56.1/8.57.0) | [](https://securityscorecards.dev/viewer/?uri=github.com/typescript-eslint/typescript-eslint) | | [@typescript-eslint/parser](https://typescript-eslint.io/packages/parser) ([source](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)) | devDependencies | minor | [`8.56.1` → `8.57.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.56.1/8.57.0) | [](https://securityscorecards.dev/viewer/?uri=github.com/typescript-eslint/typescript-eslint) | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme) ([source](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react)) | devDependencies | minor | [`5.1.4` → `5.2.0`](https://renovatebot.com/diffs/npm/@vitejs%2fplugin-react/5.1.4/5.2.0) | [](https://securityscorecards.dev/viewer/?uri=github.com/vitejs/vite-plugin-react) | | [typescript-eslint](https://typescript-eslint.io/packages/typescript-eslint) ([source](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint)) | devDependencies | minor | [`8.56.1` → `8.57.0`](https://renovatebot.com/diffs/npm/typescript-eslint/8.56.1/8.57.0) | [](https://securityscorecards.dev/viewer/?uri=github.com/typescript-eslint/typescript-eslint) | | [vite-plugin-static-copy](https://github.com/sapphi-red/vite-plugin-static-copy) | devDependencies | minor | [`3.2.0` → `3.3.0`](https://renovatebot.com/diffs/npm/vite-plugin-static-copy/3.2.0/3.3.0) | [](https://securityscorecards.dev/viewer/?uri=github.com/sapphi-red/vite-plugin-static-copy) | | [vitest](https://vitest.dev) ([source](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest)) | devDependencies | minor | [`4.0.18` → `4.1.0`](https://renovatebot.com/diffs/npm/vitest/4.0.18/4.1.0) | [](https://securityscorecards.dev/viewer/?uri=github.com/vitest-dev/vitest) | --- ### Release Notes <details> <summary>OpenAPITools/openapi-generator-cli (@​openapitools/openapi-generator-cli)</summary> ### [`v2.30.2`](https://github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.30.2) [Compare Source](OpenAPITools/openapi-generator-cli@v2.30.1...v2.30.2) ##### Bug Fixes - **deps:** update dependency jsonpath to v1.3.0 ([#​1164](OpenAPITools/openapi-generator-cli#1164)) ([2c4802d](OpenAPITools/openapi-generator-cli@2c4802d)) ### [`v2.30.1`](https://github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.30.1) [Compare Source](OpenAPITools/openapi-generator-cli@v2.30.0...v2.30.1) ##### Bug Fixes - **deps:** update dependency fs-extra to v11.3.4 ([#​1157](OpenAPITools/openapi-generator-cli#1157)) ([74d5871](OpenAPITools/openapi-generator-cli@74d5871)) ### [`v2.30.0`](https://github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.30.0) [Compare Source](OpenAPITools/openapi-generator-cli@v2.29.0...v2.30.0) ##### Features - **release:** trigger a release ([#​1148](OpenAPITools/openapi-generator-cli#1148)) ([a1e9c93](OpenAPITools/openapi-generator-cli@a1e9c93)) </details> <details> <summary>typescript-eslint/typescript-eslint (@​typescript-eslint/eslint-plugin)</summary> ### [`v8.57.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8570-2026-03-09) [Compare Source](typescript-eslint/typescript-eslint@v8.56.1...v8.57.0) ##### 🚀 Features - **eslint-plugin:** \[no-unnecessary-condition] allow literal loop conditions in for/do loops ([#​12080](typescript-eslint/typescript-eslint#12080)) ##### 🩹 Fixes - **eslint-plugin:** \[no-base-to-string] fix false positive for toString with overloads ([#​12089](typescript-eslint/typescript-eslint#12089)) - **eslint-plugin:** \[prefer-promise-reject-errors] add allow `TypeOrValueSpecifier` to prefer-promise-reject-errors ([#​12094](typescript-eslint/typescript-eslint#12094)) - **typescript-estree:** if the template literal is tagged and the text has an invalid escape, `cooked` will be `null` ([#​11355](typescript-eslint/typescript-eslint#11355)) - **eslint-plugin:** guard against negative paramIndex in no-useless-default-assignment ([#​12077](typescript-eslint/typescript-eslint#12077)) - **eslint-plugin:** handle statically analyzable computed keys in prefer-readonly ([#​12079](typescript-eslint/typescript-eslint#12079)) - **eslint-plugin:** \[strict-void-return] false positives with overloads ([#​12055](typescript-eslint/typescript-eslint#12055)) ##### ❤️ Thank You - Brad Zacher [@​bradzacher](https://github.com/bradzacher) - Brian Schlenker [@​bschlenk](https://github.com/bschlenk) - Evyatar Daud [@​StyleShit](https://github.com/StyleShit) - James Henry [@​JamesHenry](https://github.com/JamesHenry) - Josh Goldberg - Kirk Waiblinger [@​kirkwaiblinger](https://github.com/kirkwaiblinger) - Moses Odutusin [@​thebolarin](https://github.com/thebolarin) - Newton Yuan [@​NewtonYuan](https://github.com/NewtonYuan) - SungHyun627 [@​SungHyun627](https://github.com/SungHyun627) - Younsang Na [@​nayounsang](https://github.com/nayounsang) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.57.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. </details> <details> <summary>typescript-eslint/typescript-eslint (@​typescript-eslint/parser)</summary> ### [`v8.57.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8570-2026-03-09) [Compare Source](typescript-eslint/typescript-eslint@v8.56.1...v8.57.0) This was a version bump only for parser to align it with other projects, there were no code changes. See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.57.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. </details> <details> <summary>vitejs/vite-plugin-react (@​vitejs/plugin-react)</summary> ### [`v5.2.0`](vitejs/vite-plugin-react@f066114...fda3a86) [Compare Source](vitejs/vite-plugin-react@f066114...fda3a86) </details> <details> <summary>typescript-eslint/typescript-eslint (typescript-eslint)</summary> ### [`v8.57.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/typescript-eslint/CHANGELOG.md#8570-2026-03-09) [Compare Source](typescript-eslint/typescript-eslint@v8.56.1...v8.57.0) This was a version bump only for typescript-eslint to align it with other projects, there were no code changes. See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.57.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. </details> <details> <summary>sapphi-red/vite-plugin-static-copy (vite-plugin-static-copy)</summary> ### [`v3.3.0`](https://github.com/sapphi-red/vite-plugin-static-copy/blob/HEAD/CHANGELOG.md#330) [Compare Source](https://github.com/sapphi-red/vite-plugin-static-copy/compare/vite-plugin-static-copy@3.2.0...vite-plugin-static-copy@3.3.0) ##### Minor Changes - [#​230](sapphi-red/vite-plugin-static-copy#230) [`3074e1a`](sapphi-red/vite-plugin-static-copy@3074e1a) Thanks [@​sapphi-red](https://github.com/sapphi-red)! - Add Vite 8 to peer dependency range. </details> <details> <summary>vitest-dev/vitest (vitest)</summary> ### [`v4.1.0`](https://github.com/vitest-dev/vitest/releases/tag/v4.1.0) [Compare Source](vitest-dev/vitest@v4.0.18...v4.1.0) Vitest 4.1 is out! This release page lists all changes made to the project during the 4.1 beta. To get a review of all the new features, read our [blog post](https://vitest.dev/blog/vitest-4-1). ##### 🚀 Features - Return a disposable from doMock() - by [@​kirkwaiblinger](https://github.com/kirkwaiblinger) in [#​9332](vitest-dev/vitest#9332) [<samp>(e3e65)</samp>](vitest-dev/vitest@e3e659a96) - Added chai style assertions - by [@​ronnakamoto](https://github.com/ronnakamoto) and [@​sheremet-va](https://github.com/sheremet-va) in [#​8842](vitest-dev/vitest#8842) [<samp>(841df)</samp>](vitest-dev/vitest@841df9ac5) - Update to sinon/fake-timers v15 and add `setTickMode` to timer controls - by [@​atscott](https://github.com/atscott) and [@​sheremet-va](https://github.com/sheremet-va) in [#​8726](vitest-dev/vitest#8726) [<samp>(4b480)</samp>](vitest-dev/vitest@4b480aaed) - Expose matcher types - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9448](vitest-dev/vitest#9448) [<samp>(3e4b9)</samp>](vitest-dev/vitest@3e4b913b1) - Add `toTestSpecification` to reported tasks - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9464](vitest-dev/vitest#9464) [<samp>(1a470)</samp>](vitest-dev/vitest@1a4705da9) - Show a warning if `vi.mock` or `vi.hoisted` are declared outside of top level of the module - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9387](vitest-dev/vitest#9387) [<samp>(5db54)</samp>](vitest-dev/vitest@5db54a468) - Track and display expectedly failed tests (.fails) in UI and CLI - by [@​Copilot](https://github.com/Copilot), **sheremet-va** and [@​sheremet-va](https://github.com/sheremet-va) in [#​9476](vitest-dev/vitest#9476) [<samp>(77d75)</samp>](vitest-dev/vitest@77d75fd34) - Support tags - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9478](vitest-dev/vitest#9478) [<samp>(de7c8)</samp>](vitest-dev/vitest@de7c8a521) - Implement `aroundEach` and `aroundAll` hooks - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9450](vitest-dev/vitest#9450) [<samp>(2a8cb)</samp>](vitest-dev/vitest@2a8cb9dc2) - Stabilize experimental features - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9529](vitest-dev/vitest#9529) [<samp>(b5fd2)</samp>](vitest-dev/vitest@b5fd2a16a) - Accept `new` or `all` in `--update` flag - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9543](vitest-dev/vitest#9543) [<samp>(a5acf)</samp>](vitest-dev/vitest@a5acf28a5) - Support `meta` in test options - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9535](vitest-dev/vitest#9535) [<samp>(7d622)</samp>](vitest-dev/vitest@7d622e3d1) - Support type inference with a new `test.extend` syntax - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9550](vitest-dev/vitest#9550) [<samp>(e5385)</samp>](vitest-dev/vitest@e53854fcc) - Support vite 8 beta, fix type issues in the config with different vite versions - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9587](vitest-dev/vitest#9587) [<samp>(99028)</samp>](vitest-dev/vitest@990281dfd) - Add assertion helper to hide internal stack traces - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9594](vitest-dev/vitest#9594) [<samp>(eeb0a)</samp>](vitest-dev/vitest@eeb0ae2f8) - Store failure screenshots using artifacts API - by [@​macarie](https://github.com/macarie) in [#​9588](vitest-dev/vitest#9588) [<samp>(24603)</samp>](vitest-dev/vitest@24603e3c4) - Allow `vitest list` to statically collect tests instead of running files to collect them - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9630](vitest-dev/vitest#9630) [<samp>(7a8e7)</samp>](vitest-dev/vitest@7a8e7fc20) - Add `--detect-async-leaks` - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9528](vitest-dev/vitest#9528) [<samp>(c594d)</samp>](vitest-dev/vitest@c594d4af3) - Implement `mockThrow` and `mockThrowOnce` - by [@​thor-juhasz](https://github.com/thor-juhasz) and [@​sheremet-va](https://github.com/sheremet-va) in [#​9512](vitest-dev/vitest#9512) [<samp>(61917)</samp>](vitest-dev/vitest@619179fb7) - Support `update: "none"` and add docs about snapshots behavior on CI - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9700](vitest-dev/vitest#9700) [<samp>(05f18)</samp>](vitest-dev/vitest@05f1854e2) - Support playwright `launchOptions` with `connectOptions` - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9702](vitest-dev/vitest#9702) [<samp>(f0ff1)</samp>](vitest-dev/vitest@f0ff1b2a0) - Add `page/locator.mark` API to enhance playwright trace - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9652](vitest-dev/vitest#9652) [<samp>(d0ee5)</samp>](vitest-dev/vitest@d0ee546fe) - **api**: - Support tests starting or ending with `test` in `experimental_parseSpecification` - by [@​jgillick](https://github.com/jgillick) and **Jeremy Gillick** in [#​9235](vitest-dev/vitest#9235) [<samp>(2f367)</samp>](vitest-dev/vitest@2f367fad3) - Add filters to `createSpecification` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9336](vitest-dev/vitest#9336) [<samp>(c8e6c)</samp>](vitest-dev/vitest@c8e6c7fbf) - Expose `runTestFiles` as alternative to `runTestSpecifications` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9443](vitest-dev/vitest#9443) [<samp>(43d76)</samp>](vitest-dev/vitest@43d761821) - Add `allowWrite` and `allowExec` options to `api` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9350](vitest-dev/vitest#9350) [<samp>(20e00)</samp>](vitest-dev/vitest@20e00ef78) - Allow passing down test cases to `toTestSpecification` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9627](vitest-dev/vitest#9627) [<samp>(6f17d)</samp>](vitest-dev/vitest@6f17d5ddf) - **browser**: - Add `userEvent.wheel` API - by [@​macarie](https://github.com/macarie) in [#​9188](vitest-dev/vitest#9188) [<samp>(66080)</samp>](vitest-dev/vitest@660801979) - Add `filterNode` option to prettyDOM for filtering browser assertion error output - by [@​Copilot](https://github.com/Copilot), **sheremet-va** and [@​sheremet-va](https://github.com/sheremet-va) in [#​9475](vitest-dev/vitest#9475) [<samp>(d3220)</samp>](vitest-dev/vitest@d3220fcd8) - Support playwright persistent context - by [@​hi-ogawa](https://github.com/hi-ogawa), **Claude Opus 4.6** and [@​sheremet-va](https://github.com/sheremet-va) in [#​9229](vitest-dev/vitest#9229) [<samp>(f865d)</samp>](vitest-dev/vitest@f865d2ba4) - Added `detailsPanelPosition` option and button - by [@​shairez](https://github.com/shairez) in [#​9525](vitest-dev/vitest#9525) [<samp>(c8a31)</samp>](vitest-dev/vitest@c8a31147c) - Use BlazeDiff instead of pixelmatch - by [@​macarie](https://github.com/macarie) in [#​9514](vitest-dev/vitest#9514) [<samp>(30936)</samp>](vitest-dev/vitest@309362089) - Add `findElement` and enable strict mode in webdriverio and preview - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9677](vitest-dev/vitest#9677) [<samp>(c3f37)</samp>](vitest-dev/vitest@c3f37721c) - **cli**: - Add [@​bomb](https://github.com/bomb).sh/tab completions - by [@​AmirSa12](https://github.com/AmirSa12) and [@​sheremet-va](https://github.com/sheremet-va) in [#​8639](vitest-dev/vitest#8639) [<samp>(200f3)</samp>](vitest-dev/vitest@200f31704) - **coverage**: - Support `ignore start/stop` ignore hints - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9204](vitest-dev/vitest#9204) [<samp>(e59c9)</samp>](vitest-dev/vitest@e59c94ba6) - Add `coverage.changed` option to report only changed files - by [@​kykim00](https://github.com/kykim00) and [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9521](vitest-dev/vitest#9521) [<samp>(1d939)</samp>](vitest-dev/vitest@1d9392c67) - **experimental**: - Add `onModuleRunner` hook to `worker.init` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9286](vitest-dev/vitest#9286) [<samp>(e977f)</samp>](vitest-dev/vitest@e977f3deb) - Option to disable the module runner - by [@​sheremet-va](https://github.com/sheremet-va) and [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9210](vitest-dev/vitest#9210) [<samp>(9be61)</samp>](vitest-dev/vitest@9be6121ee) - Add `importDurations: { limit, print }` options - by [@​hi-ogawa](https://github.com/hi-ogawa), **Claude Opus 4.6** and [@​sheremet-va](https://github.com/sheremet-va) in [#​9401](vitest-dev/vitest#9401) [<samp>(7e10f)</samp>](vitest-dev/vitest@7e10fb356) - Add print and fail thresholds for `importDurations` - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9533](vitest-dev/vitest#9533) [<samp>(3f7a5)</samp>](vitest-dev/vitest@3f7a5f8f8) - **fixtures**: - Pass down file context to `beforeAll`/`afterAll` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9572](vitest-dev/vitest#9572) [<samp>(c8339)</samp>](vitest-dev/vitest@c83395f2c) - **reporters**: - Add `agent` reporter to reduce ai agent token usage - by [@​cpojer](https://github.com/cpojer) in [#​9779](vitest-dev/vitest#9779) [<samp>(3e9e0)</samp>](vitest-dev/vitest@3e9e096a2) - **runner**: - Enhance `retry` options - by [@​MazenSamehR](https://github.com/MazenSamehR), **Matan Shavit**, [@​AriPerkkio](https://github.com/AriPerkkio) and [@​sheremet-va](https://github.com/sheremet-va) in [#​9370](vitest-dev/vitest#9370) [<samp>(9e4cf)</samp>](vitest-dev/vitest@9e4cfd295) - **ui**: - Allow run individual test/suites - by [@​userquin](https://github.com/userquin) in [#​9465](vitest-dev/vitest#9465) [<samp>(73b10)</samp>](vitest-dev/vitest@73b10f1b9) - Add project filter/sort support - by [@​userquin](https://github.com/userquin) in [#​8689](vitest-dev/vitest#8689) [<samp>(0c7ea)</samp>](vitest-dev/vitest@0c7eaac16) - Add duration sorting to explorer - by [@​julianhahn](https://github.com/julianhahn) and [@​cursoragent](https://github.com/cursoragent) in [#​9603](vitest-dev/vitest#9603) [<samp>(209b1)</samp>](vitest-dev/vitest@209b1b0e1) - Implement filter for slow tests - by [@​DerYeger](https://github.com/DerYeger) and [@​userquin](https://github.com/userquin) in [#​9705](vitest-dev/vitest#9705) [<samp>(8880c)</samp>](vitest-dev/vitest@8880c907a) - **vitest**: - Add run summary in GitHub Actions Reporter - by [@​macarie](https://github.com/macarie) and **jhnance** in [#​9579](vitest-dev/vitest#9579) [<samp>(96bfc)</samp>](vitest-dev/vitest@96bfc8345) ##### 🐞 Bug Fixes - Deprecate several vitest/\* entry points - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9347](vitest-dev/vitest#9347) [<samp>(fd459)</samp>](vitest-dev/vitest@fd45928be) - Use `meta.url` in `createRequire` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9441](vitest-dev/vitest#9441) [<samp>(e3422)</samp>](vitest-dev/vitest@e34225563) - Preact browser mode init example of render function not async - by [@​WuMingDao](https://github.com/WuMingDao) in [#​9375](vitest-dev/vitest#9375) [<samp>(2bea5)</samp>](vitest-dev/vitest@2bea549c7) - Deprecate unused types in matcher context - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9449](vitest-dev/vitest#9449) [<samp>(20f87)</samp>](vitest-dev/vitest@20f8753a2) - Handle `external/noExternal` during `configEnvironment` hook - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9508](vitest-dev/vitest#9508) [<samp>(59ea2)</samp>](vitest-dev/vitest@59ea27c1c) - Replace default ssr environment runner with Vitest server module runner - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9506](vitest-dev/vitest#9506) [<samp>(cd5db)</samp>](vitest-dev/vitest@cd5db660c) - Propagate experimental CLI options to child projects - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9531](vitest-dev/vitest#9531) [<samp>(b624f)</samp>](vitest-dev/vitest@b624fae53) - Show a warning when `browser.isolate` is used - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9410](vitest-dev/vitest#9410) [<samp>(3d48e)</samp>](vitest-dev/vitest@3d48ebcb9) - Fix `vi.mock({ spy: true })` node v8 coverage - by [@​hi-ogawa](https://github.com/hi-ogawa), **hi-ogawa** and **Claude Opus 4.6** in [#​9541](vitest-dev/vitest#9541) [<samp>(687b6)</samp>](vitest-dev/vitest@687b633c1) - Don't show internal ssr handler in errors - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9547](vitest-dev/vitest#9547) [<samp>(76c43)</samp>](vitest-dev/vitest@76c4397b5) - Close vitest if it failed to start - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9573](vitest-dev/vitest#9573) [<samp>(728ba)</samp>](vitest-dev/vitest@728ba617f) - Fix ssr environment runner in project - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9584](vitest-dev/vitest#9584) [<samp>(09006)</samp>](vitest-dev/vitest@090064f97) - Trim trailing white spaces in code block - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9591](vitest-dev/vitest#9591) [<samp>(f78be)</samp>](vitest-dev/vitest@f78bea992) - Support inline snapshot inside test.for/each - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9590](vitest-dev/vitest#9590) [<samp>(615fd)</samp>](vitest-dev/vitest@615fd521e) - Apply source maps for external module stack trace - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9152](vitest-dev/vitest#9152) [<samp>(79e20)</samp>](vitest-dev/vitest@79e20d5a3) - Remove the `.name` from statically collected test - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9596](vitest-dev/vitest#9596) [<samp>(b66ff)</samp>](vitest-dev/vitest@b66ff691a) - Don't suppress warnings on pnp - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9602](vitest-dev/vitest#9602) [<samp>(89cbd)</samp>](vitest-dev/vitest@89cbdaea3) - Support snapshot with `expect.soft` - by [@​iumehara](https://github.com/iumehara), [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9231](vitest-dev/vitest#9231) [<samp>(3eb2c)</samp>](vitest-dev/vitest@3eb2cd541) - Log seed when only `sequence.shuffle.tests` is enabled - by [@​kaigritun](https://github.com/kaigritun), **Kai Gritun** and [@​sheremet-va](https://github.com/sheremet-va) in [#​9576](vitest-dev/vitest#9576) [<samp>(8182b)</samp>](vitest-dev/vitest@8182b77ad) - Externalize `expect/src/utils` from `vitest` - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9616](vitest-dev/vitest#9616) [<samp>(48739)</samp>](vitest-dev/vitest@487398422) - Ignore test.override during static collection - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9620](vitest-dev/vitest#9620) [<samp>(09174)</samp>](vitest-dev/vitest@0917470ce) - Increase stacktrace limit for `--detect-async-leaks` - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9638](vitest-dev/vitest#9638) [<samp>(9fd4c)</samp>](vitest-dev/vitest@9fd4ce533) - Hanging-reporter link in cli - by [@​flx-sta](https://github.com/flx-sta) in [#​9649](vitest-dev/vitest#9649) [<samp>(7c103)</samp>](vitest-dev/vitest@7c103055c) - Fix teardown timeout of `aroundEach/All` when inner `aroundEach/All` throws - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9657](vitest-dev/vitest#9657) [<samp>(4ec6c)</samp>](vitest-dev/vitest@4ec6cb305) - Fix ui mode / html reporter and coverage integration - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9626](vitest-dev/vitest#9626) [<samp>(86fad)</samp>](vitest-dev/vitest@86fad4b42) - Don't continue when `aroundEach/All` setup timed out - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9670](vitest-dev/vitest#9670) [<samp>(bb013)</samp>](vitest-dev/vitest@bb013d54b) - Align `VitestRunnerConfig` optional fields with `SerializedConfig` - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9661](vitest-dev/vitest#9661) [<samp>(79520)</samp>](vitest-dev/vitest@79520d82d) - Handle Symbol values in format utility - by [@​nami8824](https://github.com/nami8824) in [#​9658](vitest-dev/vitest#9658) [<samp>(0583f)</samp>](vitest-dev/vitest@0583f067e) - Deprecate `toBe*` spy assertions in favor of `toHaveBeen*` (and `toThrowError`) - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9665](vitest-dev/vitest#9665) [<samp>(4d390)</samp>](vitest-dev/vitest@4d390dfe9) - Don't propagate nested `aroundEach/All` errors but aggregate them on runner - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9673](vitest-dev/vitest#9673) [<samp>(b6365)</samp>](vitest-dev/vitest@b63653f5a) - Show a better error if there is a pending dynamic import - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9676](vitest-dev/vitest#9676) [<samp>(7ef5c)</samp>](vitest-dev/vitest@7ef5cf4b7) - Preserve stack trace of `resolves/rejects` chained assertion error - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9679](vitest-dev/vitest#9679) [<samp>(c6151)</samp>](vitest-dev/vitest@c61511d4a) - Handle module-sync condition in vmThreads/vmForks require - by [@​lesleh](https://github.com/lesleh) in [#​9650](vitest-dev/vitest#9650) and [#​9651](vitest-dev/vitest#9651) [<samp>(bb203)</samp>](vitest-dev/vitest@bb20389f4) - Hooks should respect `maxConcurrency` - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9653](vitest-dev/vitest#9653) [<samp>(16d13)</samp>](vitest-dev/vitest@16d13d981) - Recursively autospy module object - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9687](vitest-dev/vitest#9687) [<samp>(695a8)</samp>](vitest-dev/vitest@695a86b41) - Remove trailing spaces from diff error log - by [@​hi-ogawa](https://github.com/hi-ogawa) and [@​sheremet-va](https://github.com/sheremet-va) in [#​9680](vitest-dev/vitest#9680) [<samp>(395d1)</samp>](vitest-dev/vitest@395d1a29e) - Respect project `resolve.conditions` for externals - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9717](vitest-dev/vitest#9717) [<samp>(1d498)</samp>](vitest-dev/vitest@1d4987498) - Use object for WeakMap instead of a symbol to support webcontainers - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9731](vitest-dev/vitest#9731) [<samp>(c5225)</samp>](vitest-dev/vitest@c52259330) - Fix re-mocking virtual module - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9748](vitest-dev/vitest#9748) [<samp>(3cbbb)</samp>](vitest-dev/vitest@3cbbb17f1) - Cancelling should stop current test immediately - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9729](vitest-dev/vitest#9729) [<samp>(0cb2f)</samp>](vitest-dev/vitest@0cb2f7239) - Make `mockObject` change backwards compatible - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9744](vitest-dev/vitest#9744) [<samp>(84c69)</samp>](vitest-dev/vitest@84c69497f) - Fix `URL.name` on jsdom - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9767](vitest-dev/vitest#9767) [<samp>(031f3)</samp>](vitest-dev/vitest@031f3a374) - Save and restore module graph in blob reporter - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9740](vitest-dev/vitest#9740) [<samp>(84355)</samp>](vitest-dev/vitest@843554bf0) - Don't silence reporter errors from test runtime events handler in normal run and --merge-reports - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9727](vitest-dev/vitest#9727) [<samp>(4072d)</samp>](vitest-dev/vitest@4072d0132) - Fix `vi.importActual()` for virtual modules - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9772](vitest-dev/vitest#9772) [<samp>(1e89e)</samp>](vitest-dev/vitest@1e89ec020) - Throw `FixtureAccessError` if suite hook accesses undefined fixture - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9786](vitest-dev/vitest#9786) [<samp>(fc2ce)</samp>](vitest-dev/vitest@fc2cea2b7) - Allow hyphens in project config file name pattern - by [@​Koutaro-Hanabusa](https://github.com/Koutaro-Hanabusa) and [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9760](vitest-dev/vitest#9760) [<samp>(33e96)</samp>](vitest-dev/vitest@33e96311a) - Manual and redirect mock shouldn't `load` or `transform` original module - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9774](vitest-dev/vitest#9774) [<samp>(a8216)</samp>](vitest-dev/vitest@a8216b001) - `hideSkippedTests` should not hide `test.todo` - by [@​oilater](https://github.com/oilater) in [#​9562](vitest-dev/vitest#9562) and [#​9781](vitest-dev/vitest#9781) [<samp>(8181e)</samp>](vitest-dev/vitest@8181e06e7) - Allow catch/finally for async assertion - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9827](vitest-dev/vitest#9827) [<samp>(031f0)</samp>](vitest-dev/vitest@031f02a89) - Resolve fixture overrides from test's suite in `beforeEach` hooks - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9826](vitest-dev/vitest#9826) [<samp>(99e52)</samp>](vitest-dev/vitest@99e52fe58) - Use isAgent check, not just TTY, for watch mode - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9841](vitest-dev/vitest#9841) [<samp>(c3cac)</samp>](vitest-dev/vitest@c3cac1c1b) - Use `performance.now` to measure test timeout duration - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9795](vitest-dev/vitest#9795) [<samp>(f48a6)</samp>](vitest-dev/vitest@f48a60114) - Correctly identify concurrent test during static analysis - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9846](vitest-dev/vitest#9846) [<samp>(1de0a)</samp>](vitest-dev/vitest@1de0aa22d) - **browser**: - Avoid updating screenshots when `toMatchScreenshot` passes - by [@​macarie](https://github.com/macarie) in [#​9289](vitest-dev/vitest#9289) [<samp>(46aab)</samp>](vitest-dev/vitest@46aabaa44) - Hide injected data-testid attributes - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9503](vitest-dev/vitest#9503) [<samp>(c8d2c)</samp>](vitest-dev/vitest@c8d2c411c) - Throw an error if iframe was reloaded - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9516](vitest-dev/vitest#9516) [<samp>(73a81)</samp>](vitest-dev/vitest@73a81f880) - Encode projectName in browser client URL - by [@​dkkim0122](https://github.com/dkkim0122) in [#​9523](vitest-dev/vitest#9523) [<samp>(5b164)</samp>](vitest-dev/vitest@5b16483c3) - Don't take failure screenshot if tests have artifacts created by `toMatchScreenshot` - by [@​macarie](https://github.com/macarie) in [#​9552](vitest-dev/vitest#9552) [<samp>(83ca0)</samp>](vitest-dev/vitest@83ca02547) - Remove `--remote-debugging-address` from chrome args - by [@​hi-ogawa](https://github.com/hi-ogawa) and [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9712](vitest-dev/vitest#9712) [<samp>(f09bb)</samp>](vitest-dev/vitest@f09bb5c32) - Make sure userEvent actions support `ensureAwaited` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9732](vitest-dev/vitest#9732) [<samp>(97685)</samp>](vitest-dev/vitest@9768517b8) - Types of `getCDPSession` and `cdp()` - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9716](vitest-dev/vitest#9716) [<samp>(689a2)</samp>](vitest-dev/vitest@689a22a1b) - Skip esbuild.legalComments when using rolldown-vite - by [@​Copilot](https://github.com/Copilot), **hi-ogawa** and [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9803](vitest-dev/vitest#9803) [<samp>(3505f)</samp>](vitest-dev/vitest@3505fa5a3) - **chai**: - Don't allow `deepEqual` in the config because it's not serializable - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9666](vitest-dev/vitest#9666) [<samp>(9ee99)</samp>](vitest-dev/vitest@9ee999d73) - **coverage**: - Infer transform mode for uncovered files - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9435](vitest-dev/vitest#9435) [<samp>(f3967)</samp>](vitest-dev/vitest@f396792d6) - `thresholds.autoUpdate` to preserve ending whitespace - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9436](vitest-dev/vitest#9436) [<samp>(7e534)</samp>](vitest-dev/vitest@7e534a0b6) - **deps**: - Update all non-major dependencies - by [@​hi-ogawa](https://github.com/hi-ogawa) in [#​9192](vitest-dev/vitest#9192) [<samp>(90c30)</samp>](vitest-dev/vitest@90c302f3b) - Update all non-major dependencies - in [#​9485](vitest-dev/vitest#9485) [<samp>(c0118)</samp>](vitest-dev/vitest@c01186022) - Update all non-major dependencies - in [#​9567](vitest-dev/vitest#9567) [<samp>(13c9e)</samp>](vitest-dev/vitest@13c9e022b) - **docs**: - Fix old `/config/#option` hash links causing hydration errors - by [@​hi-ogawa](https://github.com/hi-ogawa), **Claude Opus 4.6** and [@​sheremet-va](https://github.com/sheremet-va) in [#​9610](vitest-dev/vitest#9610) [<samp>(a603c)</samp>](vitest-dev/vitest@a603c3a30) - **expect**: - `toMatchObject(Map/Set)` should expect `Map/Set` on left hand side - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9532](vitest-dev/vitest#9532) [<samp>(381da)</samp>](vitest-dev/vitest@381da4a9d) - Fix objectContaining with proxy - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9554](vitest-dev/vitest#9554) [<samp>(7ce34)</samp>](vitest-dev/vitest@7ce3417b1) - Support arbitrary value equality for `toThrow` and make Error detection robust - by [@​hi-ogawa](https://github.com/hi-ogawa) and **Claude Opus 4.6** in [#​9570](vitest-dev/vitest#9570) [<samp>(de215)</samp>](vitest-dev/vitest@de215c19c) - **mock**: - Inject helpers after hashbang if present - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9545](vitest-dev/vitest#9545) [<samp>(65432)</samp>](vitest-dev/vitest@65432a74b) - **mocker**: - Update vite's peer dependency range - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9808](vitest-dev/vitest#9808) [<samp>(36f9a)</samp>](vitest-dev/vitest@36f9a81a2) - **reporter**: - `dot` reporter leaves pending tests - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9684](vitest-dev/vitest#9684) [<samp>(4d793)</samp>](vitest-dev/vitest@4d7938a56) - **runner**: - Mark repeated tests as finished on last run - by [@​AriPerkkio](https://github.com/AriPerkkio) in [#​9707](vitest-dev/vitest#9707) [<samp>(cc735)</samp>](vitest-dev/vitest@cc735970a) - **spy**: - Support deep partial in vi.mocked - by [@​j2h30728](https://github.com/j2h30728) in [#​8152](vitest-dev/vitest#8152) and [#​9493](vitest-dev/vitest#9493) [<samp>(71cb5)</samp>](vitest-dev/vitest@71cb51ffc) - Fallback to object accessor if descriptor's value is `undefined` - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9511](vitest-dev/vitest#9511) [<samp>(6f181)</samp>](vitest-dev/vitest@6f18103fa) - Throw correct errors when shorthand methods are used on a class - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9513](vitest-dev/vitest#9513) [<samp>(5d0fd)</samp>](vitest-dev/vitest@5d0fd3b62) - **types**: - `bench.reporters` no longer gives type errors when passing file name string paths - by [@​Bertie690](https://github.com/Bertie690) in [#​9695](vitest-dev/vitest#9695) [<samp>(093c8)</samp>](vitest-dev/vitest@093c8f6b5) - **ui**: - Process artifact attachments when generating HTML reporter - by [@​macarie](https://github.com/macarie) in [#​9472](vitest-dev/vitest#9472) [<samp>(96eb9)</samp>](vitest-dev/vitest@96eb92826) - Don't fail if --ui and --root are specified together - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9536](vitest-dev/vitest#9536) [<samp>(d9305)</samp>](vitest-dev/vitest@d93055fc7) ##### 🏎 Performance - **pretty-format**: Combine DOMElement plugins - by [@​sheremet-va](https://github.com/sheremet-va) in [#​9581](vitest-dev/vitest#9581) [<samp>(da85a)</samp>](vitest-dev/vitest@da85a3267) ##### [View changes on GitHub](vitest-dev/vitest@v4.0.17...v4.1.0) </details> --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41OS4zIiwidXBkYXRlZEluVmVyIjoiNDMuNjYuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIiwicmVub3ZhdGUiXX0=--> See merge request swiss-armed-forces/cyber-command/cea/loom!361 Co-authored-by: Loom MR Pipeline Trigger <group_103951964_bot_9504bb8dead6d4e406ad817a607f24be@noreply.gitlab.com> Co-authored-by: shrewd-laidback palace <shrewd-laidback-palace-736-c41-2c1-e464fc974@swiss-armed-forces-open-source.ch>
Description
Resolves #6936
A couple of notes regarding the API design decision.
Playwright and WebDriverIO both use something like
await mouse.wheel(deltaX, deltaY). Their approach isn't tied to any element. Playwright recommends hovering over an element first, then calling this method to trigger a scroll event on it → initial attempt was following that approach with the addition of automatic hover, but this feels very low level.Another thing worth considering is that one call equals to one event. Usually, testing these interactions require more than that and waiting for a full client-server-client loop, depending on the environment, might be slow.
Landed on something that should provide enough flexibility while keeping a high-level API:
Note
The initially planned element-less version (
wheel(options)) was not implemented due to behavior differences between WebDriverIO and Playwright. I'll open a feature request issue to gauge community interest for this addition.Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
pnpm-lock.yamlunless you introduce a new test example.Tests
pnpm test:ci.Documentation
pnpm run docscommand.Changesets
feat:,fix:,perf:,docs:, orchore:.