Skip to content

Commit

Permalink
test: adjust tests for new react-virtual version
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars committed Dec 16, 2024
1 parent d2dd657 commit a1f8a99
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export const CommandList = forwardRef<CommandListHandle, CommandListProps>(funct
onlyShowSelectionWhenActive,
overscan,
renderItem,
testId,
wrapAround = true,
...responsivePaddingProps
},
Expand Down Expand Up @@ -592,6 +593,7 @@ export const CommandList = forwardRef<CommandListHandle, CommandListProps>(funct
ref={setVirtualListElement}
sizing="border"
tabIndex={rootTabIndex}
data-testid={testId}
{...responsivePaddingProps}
>
{canReceiveFocus && <FocusOverlayDiv offset={focusRingOffset} />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import {afterEach} from 'node:test'

import {studioTheme, ThemeProvider} from '@sanity/ui'
import {render, screen} from '@testing-library/react'
import {render, screen, waitFor} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {useCallback} from 'react'
import {describe, expect, it} from 'vitest'
import {beforeEach, describe, expect, it, vi} from 'vitest'

import {CommandList} from '../CommandList'

const COMMAND_LIST_TEST_ID = 'command-list'
const CUSTOM_ACTIVE_ATTR = 'my-active-data-attribute'

type Item = number
Expand Down Expand Up @@ -52,20 +55,52 @@ function TestComponent(props: TestComponentProps) {
// same as the number of items for the tests to pass
overscan={items.length}
renderItem={renderItem}
testId={COMMAND_LIST_TEST_ID}
/>
</div>
</ThemeProvider>
)
}

describe('core/components: CommandList', () => {
it('should change active item on pressing arrow keys', () => {
const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect

const getDOMRect = (width: number, height: number) => ({
width,
height,
top: 0,
left: 0,
bottom: 0,
right: 0,
x: 0,
y: 0,
toJSON: () => {},
})

beforeEach(() => {
// Virtual list will return an empty list of items unless we have some size,
// so we need to mock getBoundingClientRect 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
Element.prototype.getBoundingClientRect = vi.fn(function (this: Element) {
if (this.getAttribute('data-testid') === COMMAND_LIST_TEST_ID) {
return getDOMRect(350, 800)
}
return getDOMRect(0, 0)
})
})

afterEach(() => {
Element.prototype.getBoundingClientRect = originalGetBoundingClientRect
})

it('should change active item on pressing arrow keys', async () => {
render(<TestComponent items={[0, 1, 2, 3]} />)

const buttons = screen.getAllByTestId('button')

// First button should be active on render
expect(buttons[0]).toHaveAttribute(CUSTOM_ACTIVE_ATTR)
await waitFor(() => expect(buttons[0]).toHaveAttribute(CUSTOM_ACTIVE_ATTR))

// Set second button as active on arrow down
userEvent.keyboard('[ArrowDown]')
Expand Down Expand Up @@ -96,13 +131,13 @@ describe('core/components: CommandList', () => {
expect(buttons[3]).not.toHaveAttribute(CUSTOM_ACTIVE_ATTR)
})

it('should set the initial active item based on the initialIndex prop', () => {
it('should set the initial active item based on the initialIndex prop', async () => {
render(<TestComponent initialIndex={2} items={[0, 1, 3, 4]} />)

const buttons = screen.getAllByTestId('button')

// Button with index 2 should be active on render
expect(buttons[0]).not.toHaveAttribute(CUSTOM_ACTIVE_ATTR)
await waitFor(() => expect(buttons[0]).not.toHaveAttribute(CUSTOM_ACTIVE_ATTR))
expect(buttons[1]).not.toHaveAttribute(CUSTOM_ACTIVE_ATTR)
expect(buttons[2]).toHaveAttribute(CUSTOM_ACTIVE_ATTR)
expect(buttons[3]).not.toHaveAttribute(CUSTOM_ACTIVE_ATTR)
Expand All @@ -123,13 +158,13 @@ describe('core/components: CommandList', () => {
expect(buttons[0]).toHaveAttribute(CUSTOM_ACTIVE_ATTR)
})

it('should skip disabled elements', () => {
it('should skip disabled elements', async () => {
render(<TestComponent items={[0, 1, 2, 3]} withDisabledItems />)

const buttons = screen.getAllByTestId('button')

// Second button should be active since the first button is disabled
expect(buttons[1]).toHaveAttribute(CUSTOM_ACTIVE_ATTR)
await waitFor(() => expect(buttons[1]).toHaveAttribute(CUSTOM_ACTIVE_ATTR))

// Fourth button should be active since the third is disabled
userEvent.keyboard('[ArrowDown]')
Expand Down
2 changes: 2 additions & 0 deletions packages/sanity/src/core/components/commandList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ export interface CommandListProps<T = any> extends ResponsivePaddingProps {
overscan?: number
/** Rendered component in virtual lists */
renderItem: CommandListRenderItemCallback<T>
/** `data-testid` to apply to outermost container */
testId?: string
/** Allow wraparound keyboard navigation between first and last items */
wrapAround?: boolean
}

0 comments on commit a1f8a99

Please sign in to comment.