|
| 1 | +import { screen, waitFor } from '@testing-library/react'; |
| 2 | +import { render } from 'vitest-browser-react'; |
| 3 | +import { describe, expect, it } from 'vitest'; |
| 4 | +import { useLayoutEffect } from '@wordpress/element'; |
| 5 | +import DataViews from '../index'; |
| 6 | +import { LAYOUT_GRID } from '../../constants'; |
| 7 | +import type { View } from '../../types'; |
| 8 | + |
| 9 | +type Data = { |
| 10 | + id: number; |
| 11 | + title: string; |
| 12 | +}; |
| 13 | + |
| 14 | +const view: View = { |
| 15 | + type: LAYOUT_GRID, |
| 16 | + search: '', |
| 17 | + page: 1, |
| 18 | + perPage: 10, |
| 19 | + layout: {}, |
| 20 | + filters: [], |
| 21 | + fields: [ 'title' ], |
| 22 | + titleField: 'title', |
| 23 | +}; |
| 24 | + |
| 25 | +const data: Data[] = [ |
| 26 | + { id: 1, title: 'First item' }, |
| 27 | + { id: 2, title: 'Second item' }, |
| 28 | + { id: 3, title: 'Third item' }, |
| 29 | +]; |
| 30 | + |
| 31 | +// Counts the grid rows in the first animation frame after mount. Animation |
| 32 | +// frame callbacks run before resize observer callbacks, so this is the layout |
| 33 | +// the browser paints first. |
| 34 | +function FirstFrameRowCount( { |
| 35 | + onCount, |
| 36 | +}: { |
| 37 | + onCount: ( count: number ) => void; |
| 38 | +} ) { |
| 39 | + useLayoutEffect( () => { |
| 40 | + requestAnimationFrame( () => { |
| 41 | + onCount( screen.queryAllByRole( 'row' ).length ); |
| 42 | + } ); |
| 43 | + }, [ onCount ] ); |
| 44 | + return null; |
| 45 | +} |
| 46 | + |
| 47 | +describe( 'DataViews grid columns', () => { |
| 48 | + it( 'paints the grid at its real column count on the first frame', async () => { |
| 49 | + let firstFrameRowCount: number | undefined; |
| 50 | + |
| 51 | + // A 600px wide container fits two columns at the default 230px preview |
| 52 | + // size, so the three items render as two rows. |
| 53 | + await render( |
| 54 | + <div style={ { width: 600 } }> |
| 55 | + <DataViews< Data > |
| 56 | + view={ view } |
| 57 | + onChangeView={ () => {} } |
| 58 | + fields={ [ { id: 'title', label: 'Title', type: 'text' } ] } |
| 59 | + data={ data } |
| 60 | + getItemId={ ( item ) => item.id.toString() } |
| 61 | + paginationInfo={ { totalItems: 3, totalPages: 1 } } |
| 62 | + defaultLayouts={ { [ LAYOUT_GRID ]: true } } |
| 63 | + /> |
| 64 | + <FirstFrameRowCount |
| 65 | + onCount={ ( count ) => { |
| 66 | + if ( firstFrameRowCount === undefined ) { |
| 67 | + firstFrameRowCount = count; |
| 68 | + } |
| 69 | + } } |
| 70 | + /> |
| 71 | + </div> |
| 72 | + ); |
| 73 | + |
| 74 | + await waitFor( () => expect( firstFrameRowCount ).toBe( 2 ) ); |
| 75 | + |
| 76 | + // The observer reports the same width, so nothing changes. |
| 77 | + expect( screen.getAllByRole( 'row' ) ).toHaveLength( 2 ); |
| 78 | + } ); |
| 79 | +} ); |
0 commit comments