([])
+
+ // Simulate items loading after a delay (typical async data fetch)
+ React.useEffect(() => {
+ if (!open) {
+ setLoading(true)
+ setVisibleItems([])
+ }
+
+ const timer = setTimeout(() => {
+ if (open) {
+ setVisibleItems(items)
+ setLoading(false)
+ }
+ }, 500) // 500ms delay simulates network/async operation
+
+ return () => clearTimeout(timer)
+ }, [open])
+
+ return (
+ <>
+
+
+ open:{open} loading:{loading} itemsCount:{visibleItems.length}
+
+ >
+ )
+ }
+
+ it('should measure overlay height correctly while loading', async () => {
+ const user = userEvent.setup()
+ render()
+
+ const button = screen.getByRole('button', {name: /Select item/i})
+
+ // Open SelectPanel for the first time
+ await user.click(button)
+
+ // Wait for overlay to appear (should show loading spinner)
+ await waitFor(
+ () => {
+ expect(screen.getByText(/^Item 1$/)).toBeInTheDocument()
+ },
+ {timeout: 1000},
+ )
+
+ // Get overlay measurements while still loading
+ const overlay = document.querySelector('[data-testid="overlay"]') as HTMLElement | null
+ const clientHeightWhileLoading = overlay?.clientHeight
+ const scrollHeightWhileLoading = overlay?.scrollHeight
+
+ // Wait for items to load
+ await waitFor(
+ () => {
+ const state = screen.getByTestId('state')
+ expect(state).toHaveTextContent('loading:false')
+ },
+ {timeout: 1500},
+ )
+
+ // Get overlay measurements after loading
+ const clientHeightAfterLoading = overlay?.clientHeight
+ const scrollHeightAfterLoading = overlay?.scrollHeight
+
+ // Log measurements for debugging
+ console.log('First-open sizing measurements:', {
+ whileLoading: {clientHeight: clientHeightWhileLoading, scrollHeight: scrollHeightWhileLoading},
+ afterLoading: {clientHeight: clientHeightAfterLoading, scrollHeight: scrollHeightAfterLoading},
+ })
+
+ // The overlay should have enough height to fit all content without scrollbar
+ if (clientHeightAfterLoading && scrollHeightAfterLoading) {
+ const hasScrollbar = scrollHeightAfterLoading > clientHeightAfterLoading
+ expect(hasScrollbar).toBe(false)
+ }
+ })
+
+ it('should have consistent height between first and second open', async () => {
+ const user = userEvent.setup()
+ const {unmount, rerender} = render()
+
+ const button = screen.getByRole('button', {name: /Select item/i})
+
+ // First open
+ await user.click(button)
+ await waitFor(() => {
+ const state = screen.getByTestId('state')
+ expect(state).toHaveTextContent('loading:false')
+ })
+
+ const overlay1 = document.querySelector('[data-testid="overlay"]')
+ const height1 = overlay1?.getBoundingClientRect().height
+
+ // Close
+ await user.click(button)
+ await waitFor(() => {
+ const state = screen.getByTestId('state')
+ expect(state).toHaveTextContent('open:false')
+ })
+
+ // Second open (loading state happens again)
+ await user.click(button)
+ await waitFor(
+ () => {
+ const state = screen.getByTestId('state')
+ expect(state).toHaveTextContent('loading:false')
+ },
+ {timeout: 1500},
+ )
+
+ const overlay2 = document.querySelector('[data-testid="overlay"]')
+ const height2 = overlay2?.getBoundingClientRect().height
+
+ // Heights should be very similar (allowing for minor variations)
+ if (height1 && height2) {
+ const difference = Math.abs(height1 - height2)
+ console.log(`Height consistency check: first=${height1}px, second=${height2}px, diff=${difference}px`)
+ expect(difference).toBeLessThan(50) // Allow max 50px variance
+ }
+ })
+})