{"id":"57042f73-da86-4bc4-a814-57083e265a25","shortId":"agBCaN","kind":"skill","title":"react19-test-patterns","tagline":"Provides before/after patterns for migrating test files to React 19 compatibility, including act() imports, Simulate removal, and StrictMode call count changes.","description":"# React 19 Test Migration Patterns\n\nReference for all test file migrations required by React 19.\n\n## Priority Order\n\nFix test files in this order; each layer depends on the previous:\n\n1. **`act` import**  fix first, it unblocks everything else\n2. **`Simulate` → `fireEvent`**  fix immediately after act\n3. **Full react-dom/test-utils cleanup**  remove remaining imports\n4. **StrictMode call counts**  measure actual, don't guess\n5. **Async act wrapping**  for remaining \"not wrapped in act\" warnings\n6. **Custom render helper**  verify once per codebase, not per test\n\n---\n\n## 1. act() Import Fix\n\n```jsx\n// Before  REMOVED in React 19:\nimport { act } from 'react-dom/test-utils';\n\n// After:\nimport { act } from 'react';\n```\n\nIf mixed with other test-utils imports:\n```jsx\n// Before:\nimport { act, Simulate, renderIntoDocument } from 'react-dom/test-utils';\n\n// After  split the imports:\nimport { act } from 'react';\nimport { fireEvent, render } from '@testing-library/react'; // replaces Simulate + renderIntoDocument\n```\n\n---\n\n## 2. Simulate → fireEvent\n\n```jsx\n// Before  Simulate REMOVED in React 19:\nimport { Simulate } from 'react-dom/test-utils';\nSimulate.click(element);\nSimulate.change(input, { target: { value: 'hello' } });\nSimulate.submit(form);\nSimulate.keyDown(element, { key: 'Enter', keyCode: 13 });\n\n// After:\nimport { fireEvent } from '@testing-library/react';\nfireEvent.click(element);\nfireEvent.change(input, { target: { value: 'hello' } });\nfireEvent.submit(form);\nfireEvent.keyDown(element, { key: 'Enter', keyCode: 13 });\n```\n\n---\n\n## 3. react-dom/test-utils Full API Map\n\n| Old (react-dom/test-utils) | New location |\n|---|---|\n| `act` | `import { act } from 'react'` |\n| `Simulate` | `fireEvent` from `@testing-library/react` |\n| `renderIntoDocument` | `render` from `@testing-library/react` |\n| `findRenderedDOMComponentWithTag` | `getByRole`, `getByTestId` from RTL |\n| `findRenderedDOMComponentWithClass` | `getByRole` or `container.querySelector` |\n| `scryRenderedDOMComponentsWithTag` | `getAllByRole` from RTL |\n| `isElement`, `isCompositeComponent` | Remove  not needed with RTL |\n| `isDOMComponent` | Remove |\n\n---\n\n## 4. StrictMode Call Count Fixes\n\nReact 19 StrictMode no longer double-invokes `useEffect` in development. Spy assertions counting effect calls must be updated.\n\n**Strategy  always measure, never guess:**\n```bash\n# Run the failing test, read the actual count from the error:\nnpm test -- --watchAll=false --testPathPattern=\"[filename]\" --forceExit 2>&1 | grep -E \"Expected|Received\"\n```\n\n```jsx\n// Before (React 18 StrictMode  effects ran twice):\nexpect(mockFn).toHaveBeenCalledTimes(2);  // 1 call × 2 (strict double-invoke)\n\n// After (React 19 StrictMode  effects run once):\nexpect(mockFn).toHaveBeenCalledTimes(1);\n```\n\n```jsx\n// Render-phase calls (component body)  still double-invoked in React 19 StrictMode:\nexpect(renderSpy).toHaveBeenCalledTimes(2);  // stays at 2 for render body calls","tags":["react19","test","patterns","awesome","copilot","github","agent-skills","agents","custom-agents","github-copilot","hacktoberfest","prompt-engineering"],"capabilities":["skill","source-github","skill-react19-test-patterns","topic-agent-skills","topic-agents","topic-awesome","topic-custom-agents","topic-github-copilot","topic-hacktoberfest","topic-prompt-engineering"],"categories":["awesome-copilot"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/github/awesome-copilot/react19-test-patterns","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add github/awesome-copilot","source_repo":"https://github.com/github/awesome-copilot","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 30743 github stars · SKILL.md body (2,944 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:52:16.412Z","embedding":null,"createdAt":"2026-04-18T21:50:59.784Z","updatedAt":"2026-04-22T00:52:16.412Z","lastSeenAt":"2026-04-22T00:52:16.412Z","tsv":"'/react':168,211,253,260 '/test-utils':76,128,152,188,231,239 '1':55,112,332,349,366 '13':203,226 '18':340 '19':14,27,40,121,181,289,358,380 '2':64,172,331,348,351,385,388 '3':71,227 '4':81,283 '5':90 '6':101 'act':17,56,70,92,99,113,123,131,145,158,242,244 'actual':86,319 'alway':308 'api':233 'assert':300 'async':91 'bash':312 'before/after':6 'bodi':373,391 'call':23,83,285,303,350,371,392 'chang':25 'cleanup':77 'codebas':108 'compat':15 'compon':372 'container.queryselector':269 'count':24,84,286,301,320 'custom':102 'depend':51 'develop':298 'dom':75,127,151,187,230,238 'doubl':294,354,376 'double-invok':293,353,375 'e':334 'effect':302,342,360 'element':190,199,213,222 'els':63 'enter':201,224 'error':323 'everyth':62 'expect':335,345,363,382 'fail':315 'fals':327 'file':11,35,45 'filenam':329 'findrendereddomcomponentwithclass':266 'findrendereddomcomponentwithtag':261 'fireev':66,162,174,206,248 'fireevent.change':214 'fireevent.click':212 'fireevent.keydown':221 'fireevent.submit':219 'first':59 'fix':43,58,67,115,287 'forceexit':330 'form':197,220 'full':72,232 'getallbyrol':271 'getbyrol':262,267 'getbytestid':263 'grep':333 'guess':89,311 'hello':195,218 'helper':104 'immedi':68 'import':18,57,80,114,122,130,141,144,156,157,161,182,205,243 'includ':16 'input':192,215 'invok':295,355,377 'iscompositecompon':275 'isdomcompon':281 'isel':274 'jsx':116,142,175,337,367 'key':200,223 'keycod':202,225 'layer':50 'librari':167,210,252,259 'locat':241 'longer':292 'map':234 'measur':85,309 'migrat':9,29,36 'mix':135 'mockfn':346,364 'must':304 'need':278 'never':310 'new':240 'npm':324 'old':235 'order':42,48 'pattern':4,7,30 'per':107,110 'phase':370 'previous':54 'prioriti':41 'provid':5 'ran':343 'react':13,26,39,74,120,126,133,150,160,180,186,229,237,246,288,339,357,379 'react-dom':73,125,149,185,228,236 'react19':2 'react19-test-patterns':1 'read':317 'receiv':336 'refer':31 'remain':79,95 'remov':20,78,118,178,276,282 'render':103,163,255,369,390 'render-phas':368 'renderintodocu':147,171,254 'renderspi':383 'replac':169 'requir':37 'rtl':265,273,280 'run':313,361 'scryrendereddomcomponentswithtag':270 'simul':19,65,146,170,173,177,183,247 'simulate.change':191 'simulate.click':189 'simulate.keydown':198 'simulate.submit':196 'skill' 'skill-react19-test-patterns' 'source-github' 'spi':299 'split':154 'stay':386 'still':374 'strategi':307 'strict':352 'strictmod':22,82,284,290,341,359,381 'target':193,216 'test':3,10,28,34,44,111,139,166,209,251,258,316,325 'test-util':138 'testing-librari':165,208,250,257 'testpathpattern':328 'tohavebeencalledtim':347,365,384 'topic-agent-skills' 'topic-agents' 'topic-awesome' 'topic-custom-agents' 'topic-github-copilot' 'topic-hacktoberfest' 'topic-prompt-engineering' 'twice':344 'unblock':61 'updat':306 'useeffect':296 'util':140 'valu':194,217 'verifi':105 'warn':100 'watchal':326 'wrap':93,97","prices":[{"id":"0689ac9d-d97b-4c3f-8867-7085eb05e942","listingId":"57042f73-da86-4bc4-a814-57083e265a25","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"github","category":"awesome-copilot","install_from":"skills.sh"},"createdAt":"2026-04-18T21:50:59.784Z"}],"sources":[{"listingId":"57042f73-da86-4bc4-a814-57083e265a25","source":"github","sourceId":"github/awesome-copilot/react19-test-patterns","sourceUrl":"https://github.com/github/awesome-copilot/tree/main/skills/react19-test-patterns","isPrimary":false,"firstSeenAt":"2026-04-18T21:50:59.784Z","lastSeenAt":"2026-04-22T00:52:16.412Z"}],"details":{"listingId":"57042f73-da86-4bc4-a814-57083e265a25","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"github","slug":"react19-test-patterns","github":{"repo":"github/awesome-copilot","stars":30743,"topics":["agent-skills","agents","ai","awesome","custom-agents","github-copilot","hacktoberfest","prompt-engineering"],"license":"mit","html_url":"https://github.com/github/awesome-copilot","pushed_at":"2026-04-21T22:20:21Z","description":"Community-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.","skill_md_sha":"84490d809c94a1fcabcaf8e890f3c04d876d7f09","skill_md_path":"skills/react19-test-patterns/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/github/awesome-copilot/tree/main/skills/react19-test-patterns"},"layout":"multi","source":"github","category":"awesome-copilot","frontmatter":{"name":"react19-test-patterns","description":"Provides before/after patterns for migrating test files to React 19 compatibility, including act() imports, Simulate removal, and StrictMode call count changes."},"skills_sh_url":"https://skills.sh/github/awesome-copilot/react19-test-patterns"},"updatedAt":"2026-04-22T00:52:16.412Z"}}