From 000e935f38541162051d89f3daf3e6d794a86643 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 22 Oct 2026 14:45:39 +0000 Subject: [PATCH] fix(deps): update @tanstack/react-virtual to ^3.14.21 Bumps @tanstack/react-virtual ^3.14.19 -> ^3.14.21 (@tanstack/virtual-core 3.19.4 -> 3.19.6) and repairs the jsdom unit tests the bump broke. virtual-core 3.19.6 (TanStack/virtual#1326) measures the scroll viewport with clientWidth/clientHeight instead of offsetWidth/offsetHeight so that borders and scrollbars no longer inflate it. jsdom has no layout engine, so every dimension reads 0 and the virtualizer renders no rows unless the tests stub the dimensions it reads. `setupVirtualListEnv` and the CommandList test only stubbed the offset pair, so every virtualized list under test rendered empty. The stub now covers the client pair too (rows are still measured with offset dimensions), and the CommandList test uses the shared helper instead of its own copy of the stub. pnpm pruned the now-stale `@tanstack/*@` entries from `minimumReleaseAgeExclude` (`minimumReleaseAgeExcludePrune`). Supersedes #15438. --- packages/sanity/package.json | 2 +- .../__tests__/CommandList.test.tsx | 39 +---------- .../test/testUtils/setupVirtualListEnv.ts | 64 +++++++++---------- pnpm-lock.yaml | 18 +++--- pnpm-workspace.yaml | 2 - 5 files changed, 43 insertions(+), 82 deletions(-) diff --git a/packages/sanity/package.json b/packages/sanity/package.json index 969e372bbb9a..37010ea2db5d 100644 --- a/packages/sanity/package.json +++ b/packages/sanity/package.json @@ -199,7 +199,7 @@ "@sanity/uuid": "^3.0.3", "@sanity/validation": "workspace:*", "@sentry/react": "^11.8.0", - "@tanstack/react-virtual": "^3.14.19", + "@tanstack/react-virtual": "^3.14.21", "@xstate/react": "^6.1.0", "clsx": "^2.1.1", "color2k": "^2.0.4", diff --git a/packages/sanity/src/core/components/commandList/__tests__/CommandList.test.tsx b/packages/sanity/src/core/components/commandList/__tests__/CommandList.test.tsx index ffcdbca5e952..ae6f9c99c8b5 100644 --- a/packages/sanity/src/core/components/commandList/__tests__/CommandList.test.tsx +++ b/packages/sanity/src/core/components/commandList/__tests__/CommandList.test.tsx @@ -2,8 +2,9 @@ import {studioTheme, ThemeProvider} from '@sanity/ui' import {render, screen, waitFor} from '@testing-library/react' import userEvent from '@testing-library/user-event' import {useCallback} from 'react' -import {beforeEach, describe, expect, it} from 'vitest' +import {describe, expect, it} from 'vitest' +import {setupVirtualListEnv} from '../../../../../test/testUtils/setupVirtualListEnv' import {CommandList} from '../CommandList' const COMMAND_LIST_TEST_ID = 'command-list' @@ -62,41 +63,7 @@ function TestComponent(props: TestComponentProps) { } describe('core/components: CommandList', () => { - beforeEach(() => { - const originalOffsetHeight = Object.getOwnPropertyDescriptor( - HTMLElement.prototype, - 'offsetHeight', - ) - const originalOffsetWidth = Object.getOwnPropertyDescriptor( - HTMLElement.prototype, - 'offsetWidth', - ) - // Virtual list will return an empty list of items unless we have some size, - // so we need to mock offsetHeight and offsetWidth to return a size for the list. - // Not pretty, but it's what they recommend for testing outside of browsers: - // https://github.com/TanStack/virtual/issues/641 - Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { - configurable: true, - get() { - return 800 - }, - }) - Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { - configurable: true, - get() { - return 800 - }, - }) - - return () => { - if (originalOffsetHeight) { - Object.defineProperty(HTMLElement.prototype, 'offsetHeight', originalOffsetHeight) - } - if (originalOffsetWidth) { - Object.defineProperty(HTMLElement.prototype, 'offsetWidth', originalOffsetWidth) - } - } - }) + setupVirtualListEnv(undefined, 800, 800) it('should change active item on pressing arrow keys', async () => { render() diff --git a/packages/sanity/test/testUtils/setupVirtualListEnv.ts b/packages/sanity/test/testUtils/setupVirtualListEnv.ts index f31d88866edd..85cca811e950 100644 --- a/packages/sanity/test/testUtils/setupVirtualListEnv.ts +++ b/packages/sanity/test/testUtils/setupVirtualListEnv.ts @@ -1,48 +1,44 @@ import {beforeEach, vi} from 'vitest' +// jsdom has no layout engine, so every element dimension reads 0 and a virtualizer renders no +// items. Stub the dimensions the virtualizer reads, for the scroll element only when a test id is +// given. `@tanstack/virtual-core` measures the viewport with `clientWidth` / `clientHeight` +// (excluding borders and scrollbars, since 3.19.6) and each row with `offsetWidth` / +// `offsetHeight`, so both pairs are stubbed. Not pretty, but it's what they recommend for +// testing outside of browsers: https://github.com/TanStack/virtual/issues/641 +const SIZE_PROPERTIES = ['offsetHeight', 'offsetWidth', 'clientHeight', 'clientWidth'] as const + export const setupVirtualListEnv = ( dataTestId?: string, rectWidth: number = 350, rectHeight: number = 800, ) => { beforeEach(() => { - const originalOffsetHeight = Object.getOwnPropertyDescriptor( - HTMLElement.prototype, - 'offsetHeight', - ) - const originalOffsetWidth = Object.getOwnPropertyDescriptor( - HTMLElement.prototype, - 'offsetWidth', + const originalDescriptors = SIZE_PROPERTIES.map( + (property) => + [property, Object.getOwnPropertyDescriptor(HTMLElement.prototype, property)] as const, ) - // Virtual list will return an empty list of items unless we have some size, - // so we need to mock offsetHeight and offsetWidth to return a size for the list. - // Not pretty, but it's what they recommend for testing outside of browsers: - // https://github.com/TanStack/virtual/issues/641 - Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { - configurable: true, - get: vi.fn(function (this: Element) { - if (!dataTestId || this.getAttribute('data-testid') === dataTestId) { - return rectHeight - } - return 0 - }), - }) - Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { - configurable: true, - get: vi.fn(function (this: Element) { - if (!dataTestId || this.getAttribute('data-testid') === dataTestId) { - return rectWidth - } - return 0 - }), - }) + + for (const property of SIZE_PROPERTIES) { + const size = property.endsWith('Height') ? rectHeight : rectWidth + Object.defineProperty(HTMLElement.prototype, property, { + configurable: true, + get: vi.fn(function (this: Element) { + if (!dataTestId || this.getAttribute('data-testid') === dataTestId) { + return size + } + return 0 + }), + }) + } return () => { - if (originalOffsetHeight) { - Object.defineProperty(HTMLElement.prototype, 'offsetHeight', originalOffsetHeight) - } - if (originalOffsetWidth) { - Object.defineProperty(HTMLElement.prototype, 'offsetWidth', originalOffsetWidth) + for (const [property, descriptor] of originalDescriptors) { + if (descriptor) { + Object.defineProperty(HTMLElement.prototype, property, descriptor) + } else { + delete (HTMLElement.prototype as Partial)[property] + } } } }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e637f7c6686c..0b15599bb91e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2354,8 +2354,8 @@ importers: specifier: ^11.8.0 version: 11.8.0(react@19.3.1) '@tanstack/react-virtual': - specifier: ^3.14.19 - version: 3.14.19(react-dom@19.3.1)(react@19.3.1) + specifier: ^3.14.21 + version: 3.14.21(react-dom@19.3.1)(react@19.3.1) '@xstate/react': specifier: ^6.1.0 version: 6.1.0(@types/react@19.3.0)(react@19.3.1)(xstate@5.33.2) @@ -9116,14 +9116,14 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/react-virtual@3.14.19': - resolution: {integrity: sha512-zmVdJO8DDqHphZ2H6SnTmgpVXcUy5DprB+clZF0ik679/d0MQ1UPEb2jtaX6F5VTAX4o3ozSLQaRCnybS2KYLA==} + '@tanstack/react-virtual@3.14.21': + resolution: {integrity: sha512-wWE/ZJDNNDp18JHWy7n5PQooqerHePVkEEu6Op0twKQ2InF9DPhYMQptQY0syDEviMd3/r8D0OUvKJibDGm9HQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/virtual-core@3.19.4': - resolution: {integrity: sha512-ygZ3O99Il18dl0gG0q7sH78iSkb96F07G+xK9V83eCgV8NQbcNd7R+cgcJJMFO7llBoebd0A82sCCstQq2Vp6Q==} + '@tanstack/virtual-core@3.19.6': + resolution: {integrity: sha512-CsTW892z23gy7IyxYTTorVu1uZWB+0N349rSMgKz4rFLPpLza7F7TpcCKeI5iUAwYQCt8QUlOU67J+KXCxtpGw==} '@testing-library/dom@10.4.2': resolution: {integrity: sha512-yzr2S9HyAIdhz2/6qHgbs665Q7PKVcDF05vsOlHPxG1mo36gKVesdYVeDLnXgfjJ03CrKRk08knc6+E/9m8v2Q==} @@ -23094,13 +23094,13 @@ snapshots: react: 19.3.1 react-dom: 19.3.1(react@19.3.1) - '@tanstack/react-virtual@3.14.19(react-dom@19.3.1)(react@19.3.1)': + '@tanstack/react-virtual@3.14.21(react-dom@19.3.1)(react@19.3.1)': dependencies: - '@tanstack/virtual-core': 3.19.4 + '@tanstack/virtual-core': 3.19.6 react: 19.3.1 react-dom: 19.3.1(react@19.3.1) - '@tanstack/virtual-core@3.19.4': {} + '@tanstack/virtual-core@3.19.6': {} '@testing-library/dom@10.4.2': dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 900253a59dd4..6381226e7173 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -101,8 +101,6 @@ minimumReleaseAgeExclude: - '@vanilla-extract/*' - '@vercel/stega' - '@yuku-toolchain/*' - - '@tanstack/react-virtual@3.14.19' - - '@tanstack/virtual-core@3.19.4' - '@codemirror/search' - '@codemirror/state' - '@codemirror/view'