diff --git a/package.json b/package.json index c7f521f05fef..5f2acf287e2e 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "@tanstack/react-query": "5.96.0", "@tanstack/react-query-devtools": "5.96.0", "@tanstack/react-query-persist-client": "5.96.0", - "@tanstack/react-virtual": "^3.13.6", + "@tanstack/react-virtual": "3.14.6", "@types/gtag.js": "^0.0.12", "@types/history": "^3.2.5", "@types/invariant": "^2.2.35", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c2200119cdd3..2be038eac0be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -257,8 +257,8 @@ importers: specifier: 5.96.0 version: 5.96.0(@tanstack/react-query@5.96.0(react@19.2.3))(react@19.2.3) '@tanstack/react-virtual': - specifier: ^3.13.6 - version: 3.13.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: 3.14.6 + version: 3.14.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@types/gtag.js': specifier: ^0.0.12 version: 0.0.12 @@ -3718,8 +3718,8 @@ 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.13.6': - resolution: {integrity: sha512-WT7nWs8ximoQ0CDx/ngoFP7HbQF9Q2wQe4nh2NB+u2486eX3nZRE40P9g6ccCVq7ZfTSH5gFOuCoVH5DLNS/aA==} + '@tanstack/react-virtual@3.14.6': + resolution: {integrity: sha512-4+Uq8m0/gzO4kMCHUEpTtGX1RnONK0C+g88b2ltwPMWUBiaVarBuWKoPJaz7gj1cKCVRAdyu+U8GcKhwCc2beA==} 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 @@ -3741,8 +3741,8 @@ packages: '@tanstack/store@0.9.3': resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==} - '@tanstack/virtual-core@3.13.6': - resolution: {integrity: sha512-cnQUeWnhNP8tJ4WsGcYiX24Gjkc9ALstLbHcBj1t3E7EimN6n6kHH+DPV4PpDnuw00NApQp+ViojMj1GRdwYQg==} + '@tanstack/virtual-core@3.17.4': + resolution: {integrity: sha512-nGm5KteqxasUdThLc2izl6dHUqLv0LQj7Nuyo5gYalTPf/U8a9ermvsl7reT+6ioBW1l8WfpP/mcU338nLXpqw==} '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} @@ -12559,9 +12559,9 @@ snapshots: react-dom: 19.2.3(react@19.2.3) use-sync-external-store: 1.6.0(react@19.2.3) - '@tanstack/react-virtual@3.13.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-virtual@3.14.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: - '@tanstack/virtual-core': 3.13.6 + '@tanstack/virtual-core': 3.17.4 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) @@ -12578,7 +12578,7 @@ snapshots: '@tanstack/store@0.9.3': {} - '@tanstack/virtual-core@3.13.6': {} + '@tanstack/virtual-core@3.17.4': {} '@testing-library/dom@10.4.1': dependencies: diff --git a/static/app/components/events/breadcrumbs/breadcrumbsDataSection.spec.tsx b/static/app/components/events/breadcrumbs/breadcrumbsDataSection.spec.tsx index 7a5eb9bed49d..89c43fce8c34 100644 --- a/static/app/components/events/breadcrumbs/breadcrumbsDataSection.spec.tsx +++ b/static/app/components/events/breadcrumbs/breadcrumbsDataSection.spec.tsx @@ -15,19 +15,9 @@ import { MOCK_EXCEPTION_ENTRY, } from 'sentry/components/events/breadcrumbs/testUtils'; import {EntryType} from 'sentry/types/event'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; -// Needed to mock useVirtualizer lists. -jest.spyOn(window.Element.prototype, 'getBoundingClientRect').mockImplementation(() => ({ - x: 0, - y: 0, - width: 0, - height: 30, - left: 0, - top: 0, - right: 0, - bottom: 0, - toJSON: jest.fn(), -})); +mockElementSize({width: 0, height: 30}); describe('BreadcrumbsDataSection', () => { it('renders a summary of breadcrumbs with a button to view them all', async () => { diff --git a/static/app/components/events/breadcrumbs/breadcrumbsDrawer.spec.tsx b/static/app/components/events/breadcrumbs/breadcrumbsDrawer.spec.tsx index 79afc887a407..1b8aef335430 100644 --- a/static/app/components/events/breadcrumbs/breadcrumbsDrawer.spec.tsx +++ b/static/app/components/events/breadcrumbs/breadcrumbsDrawer.spec.tsx @@ -5,22 +5,10 @@ import { MOCK_BREADCRUMBS, MOCK_DATA_SECTION_PROPS, } from 'sentry/components/events/breadcrumbs/testUtils'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; async function renderBreadcrumbDrawer() { - // Needed to mock useVirtualizer lists. - jest - .spyOn(window.Element.prototype, 'getBoundingClientRect') - .mockImplementation(() => ({ - x: 0, - y: 0, - width: 0, - height: 30, - left: 0, - top: 0, - right: 0, - bottom: 0, - toJSON: jest.fn(), - })); + mockElementSize({width: 0, height: 30}); render(); await userEvent.click(screen.getByRole('button', {name: 'View 2 more'})); return screen.getByRole('complementary', {name: 'breadcrumb drawer'}); diff --git a/static/app/components/events/featureFlags/eventFeatureFlagDrawer.spec.tsx b/static/app/components/events/featureFlags/eventFeatureFlagDrawer.spec.tsx index 475ae7eccea0..7252b2c6de93 100644 --- a/static/app/components/events/featureFlags/eventFeatureFlagDrawer.spec.tsx +++ b/static/app/components/events/featureFlags/eventFeatureFlagDrawer.spec.tsx @@ -8,23 +8,11 @@ import { MOCK_DATA_SECTION_PROPS_ONE_EXTRA_FLAG, MOCK_FLAGS, } from 'sentry/components/events/featureFlags/testUtils'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import {GroupDataContextProvider} from 'sentry/views/issueDetails/groupDataContext'; async function renderFlagDrawer() { - // Needed to mock useVirtualizer lists. - jest - .spyOn(window.Element.prototype, 'getBoundingClientRect') - .mockImplementation(() => ({ - x: 0, - y: 0, - width: 0, - height: 30, - left: 0, - top: 0, - right: 0, - bottom: 0, - toJSON: jest.fn(), - })); + mockElementSize({width: 0, height: 30}); render( ({ - x: 0, - y: 0, - width: 0, - height: 30, - left: 0, - top: 0, - right: 0, - bottom: 0, - toJSON: jest.fn(), -})); +mockElementSize({width: 0, height: 30}); describe('EventFeatureFlagList', () => { beforeEach(() => { diff --git a/static/app/utils/fixtures/virtualization.ts b/static/app/utils/fixtures/virtualization.ts index 3c092e1fe7da..4d0a41a8c9d3 100644 --- a/static/app/utils/fixtures/virtualization.ts +++ b/static/app/utils/fixtures/virtualization.ts @@ -1,18 +1,31 @@ +interface MockElementSizeOptions { + height?: number; + width?: number; +} + /** - * Tanstack Virtual renders zero items in the default zero-sized JSDom environment. - * This forces all elements to have a non-zero size to render at least a few rows. - * https://github.com/TanStack/virtual/issues/641 + * TanStack Virtual renders zero items in the default zero-sized JSDOM environment. + * Mock the element dimensions read by the virtualizer so it can calculate a range. + * The bounding rect remains mocked for components that perform their own layout reads. */ -export function mockGetBoundingClientRect() { - Element.prototype.getBoundingClientRect = jest.fn(() => ({ - width: 500, - height: 500, +export function mockElementSize({ + width = 500, + height = 500, +}: MockElementSizeOptions = {}) { + // TanStack Virtual uses offset dimensions to measure its viewport and items. + jest.spyOn(HTMLElement.prototype, 'offsetWidth', 'get').mockReturnValue(width); + jest.spyOn(HTMLElement.prototype, 'offsetHeight', 'get').mockReturnValue(height); + + // Keep component layout reads consistent with the dimensions seen by the virtualizer. + jest.spyOn(Element.prototype, 'getBoundingClientRect').mockReturnValue({ + width, + height, top: 0, left: 0, - bottom: 500, - right: 500, + bottom: height, + right: width, x: 0, y: 0, toJSON: () => {}, - })); + }); } diff --git a/static/app/views/explore/logs/content.spec.tsx b/static/app/views/explore/logs/content.spec.tsx index e7a775b3d50e..253902241473 100644 --- a/static/app/views/explore/logs/content.spec.tsx +++ b/static/app/views/explore/logs/content.spec.tsx @@ -16,13 +16,15 @@ import {ProjectsStore} from 'sentry/stores/projectsStore'; import {TeamStore} from 'sentry/stores/teamStore'; import type {Organization} from 'sentry/types/organization'; import type {Project} from 'sentry/types/project'; -import {mockGetBoundingClientRect} from 'sentry/utils/fixtures/virtualization'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import {LOGS_AUTO_REFRESH_KEY} from 'sentry/views/explore/contexts/logs/logsAutoRefreshContext'; import type {OurLogsResponseItem} from 'sentry/views/explore/logs/types'; import LogsPage from './content'; -beforeEach(mockGetBoundingClientRect); +beforeEach(() => { + mockElementSize(); +}); describe('LogsPage', () => { let organization: Organization; diff --git a/static/app/views/explore/logs/logsTab.spec.tsx b/static/app/views/explore/logs/logsTab.spec.tsx index 953b31a28e11..7c685bdaeedd 100644 --- a/static/app/views/explore/logs/logsTab.spec.tsx +++ b/static/app/views/explore/logs/logsTab.spec.tsx @@ -5,7 +5,7 @@ import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrar import type {DatePageFilterProps} from 'sentry/components/pageFilters/date/datePageFilter'; import {LogsAnalyticsPageSource} from 'sentry/utils/analytics/logsAnalyticsEvent'; -import {mockGetBoundingClientRect} from 'sentry/utils/fixtures/virtualization'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import {LOGS_AUTO_REFRESH_KEY} from 'sentry/views/explore/contexts/logs/logsAutoRefreshContext'; import {LogsPageDataProvider} from 'sentry/views/explore/contexts/logs/logsPageData'; import { @@ -37,7 +37,9 @@ const datePageFilterProps: DatePageFilterProps = { }), }; -beforeEach(mockGetBoundingClientRect); +beforeEach(() => { + mockElementSize(); +}); describe('LogsTabContent', () => { const {organization, project, setupPageFilters} = initializeLogsTest(); diff --git a/static/app/views/explore/logs/tables/logsInfiniteTable.tsx b/static/app/views/explore/logs/tables/logsInfiniteTable.tsx index e2726585ec3e..c57ed1f50d2b 100644 --- a/static/app/views/explore/logs/tables/logsInfiniteTable.tsx +++ b/static/app/views/explore/logs/tables/logsInfiniteTable.tsx @@ -303,12 +303,17 @@ export function LogsInfiniteTable({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [searchString, localOnlyItemFilters?.filterText]); + const getItemKey = useCallback( + (index: number) => data?.[index]?.[OurLogKnownFieldKey.ID] ?? index, + [data] + ); + const virtualizer = useVirtualizer({ count: data?.length ?? 0, estimateSize, overscan: 35, getScrollElement: () => tableBodyRef?.current, - getItemKey: (index: number) => data?.[index]?.[OurLogKnownFieldKey.ID] ?? index, + getItemKey, }); useLayoutEffect(() => { diff --git a/static/app/views/explore/replays/detail/console/index.tsx b/static/app/views/explore/replays/detail/console/index.tsx index 904690e304e5..1521dd0e1bc3 100644 --- a/static/app/views/explore/replays/detail/console/index.tsx +++ b/static/app/views/explore/replays/detail/console/index.tsx @@ -49,13 +49,17 @@ export function Console() { const clearSearchTerm = () => setSearchTerm(''); const scrollContainerRef = useRef(null); + const getItemKey = useCallback( + (index: number) => getVirtualItemKey(items[index], index), + [items] + ); const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => scrollContainerRef.current, estimateSize: () => ESTIMATED_ROW_HEIGHT, overscan: 12, - getItemKey: index => getVirtualItemKey(items[index], index), + getItemKey, useAnimationFrameWithResizeObserver: true, }); diff --git a/static/app/views/performance/newTraceDetails/traceOurlogs.spec.tsx b/static/app/views/performance/newTraceDetails/traceOurlogs.spec.tsx index 9bbedf108a29..2a8ac0fbe32e 100644 --- a/static/app/views/performance/newTraceDetails/traceOurlogs.spec.tsx +++ b/static/app/views/performance/newTraceDetails/traceOurlogs.spec.tsx @@ -8,7 +8,7 @@ import { within, } from 'sentry-test/reactTestingLibrary'; -import {mockGetBoundingClientRect} from 'sentry/utils/fixtures/virtualization'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import {LOGS_QUERY_KEY} from 'sentry/views/explore/contexts/logs/logsPageParams'; import {OurLogKnownFieldKey} from 'sentry/views/explore/logs/types'; import { @@ -26,7 +26,9 @@ function Component({traceSlug}: {traceSlug: string}) { ); } -beforeEach(mockGetBoundingClientRect); +beforeEach(() => { + mockElementSize(); +}); describe('TraceViewLogsSection', () => { beforeEach(() => { diff --git a/static/app/views/preprod/snapshots/main/snapshotListView.spec.tsx b/static/app/views/preprod/snapshots/main/snapshotListView.spec.tsx index 610f7e169f70..695183962187 100644 --- a/static/app/views/preprod/snapshots/main/snapshotListView.spec.tsx +++ b/static/app/views/preprod/snapshots/main/snapshotListView.spec.tsx @@ -1,5 +1,6 @@ import {render, screen} from 'sentry-test/reactTestingLibrary'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import type { SidebarItem, SnapshotDiffPair, @@ -69,17 +70,7 @@ const erroredItem: SidebarItem = { describe('SnapshotListView', () => { beforeEach(() => { jest.clearAllMocks(); - jest.spyOn(Element.prototype, 'getBoundingClientRect').mockReturnValue({ - width: 900, - height: 600, - top: 0, - left: 0, - bottom: 600, - right: 900, - x: 0, - y: 0, - toJSON: jest.fn(), - }); + mockElementSize({width: 900, height: 600}); // jsdom returns empty padding strings; parseFloat('') is NaN, which would // propagate into the virtualizer's height math. Force numeric padding. jest diff --git a/static/app/views/preprod/snapshots/main/snapshotListView.tsx b/static/app/views/preprod/snapshots/main/snapshotListView.tsx index 68807669216e..72be351cb59f 100644 --- a/static/app/views/preprod/snapshots/main/snapshotListView.tsx +++ b/static/app/views/preprod/snapshots/main/snapshotListView.tsx @@ -234,12 +234,13 @@ export const SnapshotListView = memo(function SnapshotListView({ }, []); const groups = useMemo(() => buildGroups(items, contentWidth), [items, contentWidth]); + const getItemKey = useCallback((index: number) => groups[index]!.id, [groups]); const virtualizer = useVirtualizer({ count: groups.length, getScrollElement: () => scrollRef.current, estimateSize: i => groups[i]!.estimatedHeight, - getItemKey: i => groups[i]!.id, + getItemKey, overscan: 5, scrollPaddingEnd: 8, }); diff --git a/static/app/views/preprod/snapshots/sidebar/snapshotSidebarContent.spec.tsx b/static/app/views/preprod/snapshots/sidebar/snapshotSidebarContent.spec.tsx index b8ac23da9086..f330f930933d 100644 --- a/static/app/views/preprod/snapshots/sidebar/snapshotSidebarContent.spec.tsx +++ b/static/app/views/preprod/snapshots/sidebar/snapshotSidebarContent.spec.tsx @@ -1,5 +1,6 @@ import {render, screen} from 'sentry-test/reactTestingLibrary'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import {DiffStatus} from 'sentry/views/preprod/types/snapshotTypes'; import {SnapshotSidebarContent, type SidebarSection} from './snapshotSidebarContent'; @@ -7,17 +8,7 @@ import {SnapshotSidebarContent, type SidebarSection} from './snapshotSidebarCont const noop = () => {}; beforeEach(() => { - jest.spyOn(Element.prototype, 'getBoundingClientRect').mockReturnValue({ - width: 350, - height: 600, - top: 0, - left: 0, - bottom: 600, - right: 350, - x: 0, - y: 0, - toJSON: jest.fn(), - }); + mockElementSize({width: 350, height: 600}); }); const statusCounts: Record = { diff --git a/static/app/views/settings/dynamicSampling/projectsTable.spec.tsx b/static/app/views/settings/dynamicSampling/projectsTable.spec.tsx index ff53bd07cb9b..d65175f33000 100644 --- a/static/app/views/settings/dynamicSampling/projectsTable.spec.tsx +++ b/static/app/views/settings/dynamicSampling/projectsTable.spec.tsx @@ -3,21 +3,12 @@ import {ProjectFixture} from 'sentry-fixture/project'; import {render, screen} from 'sentry-test/reactTestingLibrary'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import type {ProjectionSamplePeriod} from 'sentry/views/settings/dynamicSampling/utils/useProjectSampleCounts'; import {ProjectsTable} from './projectsTable'; -jest.spyOn(window.Element.prototype, 'getBoundingClientRect').mockReturnValue({ - height: 400, - width: 500, - x: 0, - y: 0, - top: 0, - left: 0, - right: 500, - bottom: 400, - toJSON: jest.fn(), -}); +mockElementSize({width: 500, height: 400}); describe('ProjectsTable', () => { const organization = OrganizationFixture({ diff --git a/static/app/views/settings/dynamicSampling/projectsTable.tsx b/static/app/views/settings/dynamicSampling/projectsTable.tsx index 523e71de106f..4de006e54b7d 100644 --- a/static/app/views/settings/dynamicSampling/projectsTable.tsx +++ b/static/app/views/settings/dynamicSampling/projectsTable.tsx @@ -105,6 +105,11 @@ export function ProjectsTable({ return itemsWithExpanded; }, [items, expandedItems, tableSort]); + const getItemKey = useCallback( + (index: number) => sortedItems[index]?.project.id ?? index, + [sortedItems] + ); + const virtualizer = useVirtualizer({ count: sortedItems.length, getScrollElement: () => scrollContainerRef.current, @@ -113,7 +118,7 @@ export function ProjectsTable({ ? BASE_ROW_HEIGHT + (sortedItems[index].subProjects.length + 1) * 21 : BASE_ROW_HEIGHT, overscan: 5, - getItemKey: index => sortedItems[index]?.project.id ?? index, + getItemKey, }); return ( diff --git a/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.spec.tsx b/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.spec.tsx index 1f118d1ed898..d9bcc6922e9e 100644 --- a/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.spec.tsx +++ b/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.spec.tsx @@ -5,29 +5,11 @@ import {RepositoryFixture} from 'sentry-fixture/repository'; import {render, screen, userEvent, within} from 'sentry-test/reactTestingLibrary'; import type {Repository} from 'sentry/types/integrations'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import type {ScmInstallation} from 'sentry/views/settings/organizationRepositories/types'; import {InstallationOverrideProvider, ScmRepositoryTable} from './scmRepositoryTable'; -// `useVirtualizer` only renders rows whose computed bounding rect overlaps -// the scroll container. Without a stub it sees a 0×0 viewport and renders -// nothing — fake a non-zero box on every element so the rows mount. -function stubBoundingClientRect() { - jest - .spyOn(window.Element.prototype, 'getBoundingClientRect') - .mockImplementation(() => ({ - x: 0, - y: 0, - width: 600, - height: 400, - left: 0, - top: 0, - right: 600, - bottom: 400, - toJSON: jest.fn(), - })); -} - function makeRepo(id: string, name: string): Repository { return RepositoryFixture({ id, @@ -55,7 +37,7 @@ const provider = GitHubIntegrationProviderFixture(); describe('ScmRepositoryTable', () => { beforeEach(() => { - stubBoundingClientRect(); + mockElementSize({width: 600, height: 400}); MockApiClient.addMockResponse({ url: '/organizations/org-slug/projects/', body: [ diff --git a/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.tsx b/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.tsx index 9658b63d5db3..e2bd9b36a2bd 100644 --- a/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.tsx +++ b/static/app/views/settings/organizationRepositories/components/scmRepositoryTable.tsx @@ -527,12 +527,17 @@ function VirtualizedRepoList({ return sortBy(filtered, [r => !hasMapping(r.id), r => r.name]); }, [repositories, repoMatches, mappedProjectSlugsByRepoId]); + const getItemKey = useCallback( + (index: number) => visibleRepos[index]!.id, + [visibleRepos] + ); + const virtualizer = useVirtualizer({ count: visibleRepos.length, getScrollElement: () => scrollRef.current, estimateSize: () => ESTIMATED_REPO_ROW_HEIGHT, overscan: 6, - getItemKey: i => visibleRepos[i]!.id, + getItemKey, }); const renderEmptyMessage = () => { diff --git a/static/app/views/settings/organizationRepositories/index.spec.tsx b/static/app/views/settings/organizationRepositories/index.spec.tsx index 5f4c3e9b4759..3cb824a9241a 100644 --- a/static/app/views/settings/organizationRepositories/index.spec.tsx +++ b/static/app/views/settings/organizationRepositories/index.spec.tsx @@ -11,27 +11,9 @@ import { waitFor, } from 'sentry-test/reactTestingLibrary'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import OrganizationRepositories from 'sentry/views/settings/organizationRepositories'; -// ScmRepositoryTable uses @tanstack/react-virtual, which only renders rows -// whose bounding rect overlaps the scroll container. Without this stub it -// sees a 0×0 viewport and renders nothing. -function stubBoundingClientRect() { - jest - .spyOn(window.Element.prototype, 'getBoundingClientRect') - .mockImplementation(() => ({ - x: 0, - y: 0, - width: 600, - height: 400, - left: 0, - top: 0, - right: 600, - bottom: 400, - toJSON: jest.fn(), - })); -} - const GITHUB_PROVIDER = GitHubIntegrationProviderFixture(); const GITHUB_INTEGRATION = OrganizationIntegrationsFixture({ id: '1', @@ -72,7 +54,7 @@ function setupDefaultMocks() { describe('OrganizationRepositories', () => { beforeEach(() => { - stubBoundingClientRect(); + mockElementSize({width: 600, height: 400}); }); it('shows a loading indicator while queries are pending', async () => { diff --git a/static/app/views/settings/projectSeer/index.spec.tsx b/static/app/views/settings/projectSeer/index.spec.tsx index 6442a750de80..6985df1ceb4a 100644 --- a/static/app/views/settings/projectSeer/index.spec.tsx +++ b/static/app/views/settings/projectSeer/index.spec.tsx @@ -16,20 +16,10 @@ import type {SeerPreferencesResponse} from 'sentry/components/events/autofix/pre import {CodingAgentProvider} from 'sentry/components/events/autofix/types'; import type {Organization} from 'sentry/types/organization'; import type {DetailedProject} from 'sentry/types/project'; +import {mockElementSize} from 'sentry/utils/fixtures/virtualization'; import {ProjectSeerContainer as ProjectSeer} from 'sentry/views/settings/projectSeer'; -// Needed to mock useVirtualizer lists. -jest.spyOn(window.Element.prototype, 'getBoundingClientRect').mockImplementation(() => ({ - x: 0, - y: 0, - width: 0, - height: 30, - left: 0, - top: 0, - right: 0, - bottom: 0, - toJSON: jest.fn(), -})); +mockElementSize({width: 0, height: 30}); describe('ProjectSeer', () => { let project: DetailedProject;