|
| 1 | +# CI/CD Test Stability Fix for Select Component Stories |
| 2 | + |
| 3 | +## Problem |
| 4 | +The Storybook test-runner was failing in CI environments but passing locally for the `CreatableOption` story in `select.stories.tsx`. The failure occurred when trying to find portaled dropdown elements with timeouts. |
| 5 | + |
| 6 | +## Root Cause |
| 7 | +**Race conditions in CI environments** where: |
| 8 | +1. Portaled dropdown content (rendered in `document.body`) takes longer to mount |
| 9 | +2. Search input elements inside portals aren't immediately available |
| 10 | +3. CI environments are inherently slower than local development |
| 11 | + |
| 12 | +## Solution |
| 13 | +### 1. Added Explicit Timing Controls |
| 14 | +```typescript |
| 15 | +// Wait for portal content to stabilize before interaction |
| 16 | +await new Promise(resolve => setTimeout(resolve, 200)); |
| 17 | +``` |
| 18 | + |
| 19 | +### 2. Extended Test-Runner Configuration |
| 20 | +Created `.storybook/test-runner.js`: |
| 21 | +- Increased test timeout from 15s to 30s |
| 22 | +- Added custom setup file for testing-library configuration |
| 23 | + |
| 24 | +Created `.storybook/test-runner-setup.js`: |
| 25 | +- Extended `asyncUtilTimeout` from 1s to 10s for `findBy*` queries |
| 26 | + |
| 27 | +### 3. Enhanced Async Handling in Tests |
| 28 | +**Before:** |
| 29 | +```typescript |
| 30 | +const listbox = await within(document.body).findByRole('listbox'); |
| 31 | +const input = await within(document.body).findByPlaceholderText('Search...'); |
| 32 | +``` |
| 33 | + |
| 34 | +**After:** |
| 35 | +```typescript |
| 36 | +const listbox = await within(document.body).findByRole('listbox'); |
| 37 | +await new Promise(resolve => setTimeout(resolve, 200)); // Stabilization delay |
| 38 | +const input = await within(document.body).findByPlaceholderText('Search...'); |
| 39 | +``` |
| 40 | + |
| 41 | +## Files Modified |
| 42 | +1. `apps/docs/src/remix-hook-form/select.stories.tsx` - Added stabilization delays |
| 43 | +2. `apps/docs/.storybook/test-runner.js` - Extended timeouts |
| 44 | +3. `apps/docs/.storybook/test-runner-setup.js` - Testing-library config |
| 45 | + |
| 46 | +## Why This Works |
| 47 | +- **Predictable timing**: Explicit delays ensure portal content is ready |
| 48 | +- **CI-friendly timeouts**: Longer timeouts accommodate slower CI environments |
| 49 | +- **Minimal changes**: Only adds small delays where portal interaction occurs |
| 50 | +- **Maintains test integrity**: Tests still verify the same functionality |
| 51 | + |
| 52 | +## Best Practices for Future Portal Testing |
| 53 | +1. Always add small delays after finding portal elements |
| 54 | +2. Use `findBy*` queries for portal content (they have built-in waiting) |
| 55 | +3. Consider CI environment speed differences when setting timeouts |
| 56 | +4. Test locally with network throttling to simulate CI conditions |
| 57 | + |
| 58 | +## Verification |
| 59 | +The fix addresses the specific timeout error that was occurring at line 516 and 519 in the failing CI run, where `findByRole('listbox')` and `findByPlaceholderText('Search...')` were timing out. |
0 commit comments