Skip to content

Commit 03ea486

Browse files
committed
fix regressions
1 parent ca4c98e commit 03ea486

28 files changed

Lines changed: 802 additions & 58 deletions

File tree

TESTING_PLAN.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Side-by-Side Codemod Testing Plan
2+
3+
> Testing `@react-new/*` JSSG codemods vs `reactjs/react-codemod` jscodeshift counterparts on real-world open-source repos.
4+
5+
## Executive Summary
6+
7+
We searched public GitHub repos for the exact code patterns each of our 6 JSSG codemods targets. Below are the recommended test repos, organized by codemod, with match counts and React version context.
8+
9+
**Key finding:** `useFormState` from `react-dom` has **zero real-world adoption**. No open-source repo imports `useFormState` from `react-dom`. The API was renamed to `useActionState` before it saw meaningful use.
10+
11+
---
12+
13+
## Recommended Test Repos
14+
15+
### Tier 1 — Multi-Pattern Repos (highest value)
16+
17+
| Repo | Stars | React Version | Patterns Found | Language |
18+
|------|-------|---------------|----------------|----------|
19+
| **[youzan/zent](https://github.com/youzan/zent)** | 2.2k | 17.0.x (dev), ^17 (peer) | `ReactDOM.render` (~398), `react-dom/test-utils` (~17), `useContext` | TypeScript 65% |
20+
| **[salesforce/design-system-react](https://github.com/salesforce/design-system-react)** | ~1k | ^17.0.2 (dev), >=16.8 (peer) | `ReactDOM.render` (~315), `useContext` | JavaScript |
21+
| **[atlassian/react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd)** | 33k | 16.13.1 (dev), ^16.8.5‖^17‖^18 (peer) | `react-dom/test-utils` (multiple), `ReactDOM.render` | JS + Flow |
22+
23+
### Tier 2 — Single-Pattern Repos (well-known, good signal)
24+
25+
| Repo | React Version | Primary Pattern | Match Count |
26+
|------|---------------|-----------------|-------------|
27+
| **[MetaMask/metamask-extension](https://github.com/MetaMask/metamask-extension)** | 13.1k stars, React ^16.12.0 | `react-dom/test-utils` | ~18 |
28+
| **[rsuite/rsuite](https://github.com/rsuite/rsuite)** | React ^19.0.0 (dev), >=18 (peer) | `ReactDOM.render` | ~776 |
29+
| **[OnsenUI/OnsenUI](https://github.com/OnsenUI/OnsenUI)** (react-onsenui) | React ^18 (peer) | `react-dom/test-utils` | ~37 |
30+
31+
### Tier 3 — Legacy Pattern Repos (older code, needed for PropTypes + string refs)
32+
33+
| Repo | React Version | Patterns Found | Notes |
34+
|------|---------------|----------------|-------|
35+
| **[nylas/nylas-mail](https://github.com/nylas/nylas-mail)** | 24.8k stars, React ~15.x (Electron) | `React.PropTypes` (~193), `this.refs.` (~41) | Archived 2017, JS + CoffeeScript |
36+
| **[azat-co/react-quickly](https://github.com/azat-co/react-quickly)** | React ~15.x | `React.PropTypes` (~155), `this.refs.` (~120) | Book examples, highest string ref count |
37+
| **[cockpit-project/cockpit](https://github.com/cockpit-project/cockpit)** | 11k stars, varies | `this.refs.` (~54) | Active project, Linux admin tool |
38+
39+
---
40+
41+
## Per-Codemod Breakdown
42+
43+
### 1. `replace-reactdom-render` — ReactDOM.render → createRoot
44+
45+
**Pattern:** `ReactDOM.render(element, container)``createRoot(container).render(element)`
46+
47+
| Repo | Matches | Notes |
48+
|------|---------|-------|
49+
| rsuite/rsuite | ~776 | Largest count, but already on React 19 dev |
50+
| alibaba-fusion/next | ~657 | Alibaba component library |
51+
| kingdee/kdesign | ~482 | React component design system |
52+
| **youzan/zent** | ~398 | ★ React 17, TypeScript, ideal target |
53+
| **salesforce/design-system-react** | ~315 | ★ React 17, enterprise library |
54+
| nfl/react-helmet | ~100+ | Widely used, small scope |
55+
56+
**Recommended test repo:** `youzan/zent` (React 17 + TypeScript + high match count)
57+
58+
**Legacy counterpart:** `npx react-codemod react/19/replace-reactdom-render`
59+
60+
---
61+
62+
### 2. `replace-act-import` — react-dom/test-utils → react
63+
64+
**Pattern:** `import { act } from 'react-dom/test-utils'``import { act } from 'react'`
65+
66+
| Repo | Matches | Notes |
67+
|------|---------|-------|
68+
| **OnsenUI/OnsenUI** | ~37 | ★ Highest count |
69+
| Foundry376/Mailspring | ~23 | Electron email client |
70+
| **MetaMask/metamask-extension** | ~18 | ★ Very well-known, React 16 |
71+
| youzan/zent | ~17 | Also has ReactDOM.render |
72+
| atlassian/react-beautiful-dnd | multiple | Popular DnD library |
73+
74+
**Recommended test repos:** `MetaMask/metamask-extension` (brand recognition) + `OnsenUI/OnsenUI` (highest count)
75+
76+
**Legacy counterpart:** `npx react-codemod react/19/replace-act-import`
77+
78+
---
79+
80+
### 3. `react-proptypes-to-prop-types` — React.PropTypes → prop-types package
81+
82+
**Pattern:** `React.PropTypes.xxx``import PropTypes from 'prop-types'; PropTypes.xxx`
83+
84+
| Repo | Matches | Notes |
85+
|------|---------|-------|
86+
| jianliaoim/talk-os | ~253 | CoffeeScript + React, older |
87+
| **nylas/nylas-mail** | ~193 | ★ Archived, also has string refs |
88+
| **azat-co/react-quickly** | ~155 | ★ Book examples, also has string refs |
89+
| yhat/rodeo | ~125 | Data science IDE, older |
90+
91+
**Note:** This pattern only exists in React ≤15.x codebases. All recommended repos are older/archived. This is expected — React.PropTypes was removed in React 16.
92+
93+
**Recommended test repo:** `nylas/nylas-mail` (well-known + has 2 patterns)
94+
95+
**Legacy counterpart:** `npx react-codemod React-PropTypes-to-prop-types`
96+
97+
---
98+
99+
### 4. `replace-string-ref` — ref="string" → callback ref
100+
101+
**Pattern:** `ref="myRef"` in JSX inside class components → `ref={(ref) => { this.myRef = ref; }}`
102+
103+
| Repo | Matches | Notes |
104+
|------|---------|-------|
105+
| **azat-co/react-quickly** | ~120 | ★ Highest count, also has PropTypes |
106+
| cockpit-project/cockpit | ~54 | Active Linux admin tool |
107+
| nicehash/whistle | ~52 | Network debugging tool |
108+
| bitshares/bitshares-ui | ~43 | Crypto exchange UI |
109+
| **nylas/nylas-mail** | ~41 | Also has PropTypes |
110+
| BoostIO/BoostNote-Legacy | many | Note-taking app |
111+
| atom/atom | ~36 | Archived text editor |
112+
113+
**Note:** Like PropTypes, string refs only exist in older codebases (React ≤15.x, deprecated from 16).
114+
115+
**Recommended test repo:** `azat-co/react-quickly` (highest count + PropTypes combo)
116+
117+
**Legacy counterpart:** `npx react-codemod react/19/replace-string-ref`
118+
119+
---
120+
121+
### 5. `use-context-hook` — useContext → use
122+
123+
**Pattern:** `useContext(SomeContext)` / `React.useContext(SomeContext)``use(SomeContext)`
124+
125+
This pattern is **ubiquitous** — virtually every React application uses `useContext`. Any of the Tier 1 repos will work.
126+
127+
**Recommended test repos:** `youzan/zent` + `salesforce/design-system-react` (already testing other patterns)
128+
129+
**Legacy counterpart:** `npx react-codemod react/19/use-context-hook`
130+
131+
---
132+
133+
### 6. `replace-use-form-state` — useFormState → useActionState
134+
135+
**Pattern:** `import { useFormState } from 'react-dom'``import { useActionState } from 'react'`
136+
137+
**⚠️ ZERO real-world usage found.**
138+
139+
Searched grep.app for `useFormState` combined with `react-dom` across all languages. Zero matches. The only `useFormState` in the wild comes from `react-hook-form` (completely different API).
140+
141+
This API was renamed to `useActionState` before it saw meaningful public adoption. Testing should rely on **synthetic fixtures only** (which are already in our test suite).
142+
143+
---
144+
145+
## Recommended Testing Matrix
146+
147+
| Repo | render | act-import | PropTypes | string-ref | useContext | useFormState |
148+
|------|--------|------------|-----------|------------|------------|--------------|
149+
| youzan/zent |~398 |~17 |||||
150+
| salesforce/design-system-react |~315 ||||||
151+
| MetaMask/metamask-extension ||~18 |||||
152+
| nylas/nylas-mail |||~193 |~41 |||
153+
| azat-co/react-quickly |||~155 |~120 |||
154+
| *(synthetic fixtures)* |||||||
155+
156+
**Minimum repos to cover all 5 viable codemods: 3** (zent + MetaMask + nylas-mail)
157+
158+
---
159+
160+
## Test Execution Plan
161+
162+
### For each codemod × repo pair:
163+
164+
1. **Clone the repo** at a recent tagged release
165+
2. **Run the JSSG codemod** (`@react-new/<name>`):
166+
```bash
167+
npx codemod@latest react-new/<codemod-name> --target <path>
168+
```
169+
3. **Capture the diff**`results/jssg/<codemod>/<repo>.diff`
170+
4. **Reset the repo** (`git checkout .`)
171+
5. **Run the legacy jscodeshift codemod** (from `reactjs/react-codemod`):
172+
```bash
173+
npx react-codemod <codemod-name> <path>
174+
```
175+
6. **Capture the diff**`results/legacy/<codemod>/<repo>.diff`
176+
7. **Compare** the two diffs:
177+
- Files transformed (count + list)
178+
- Transformation correctness
179+
- Edge cases handled differently
180+
- Performance (execution time)
181+
8. **Document** findings per codemod
182+
183+
### Metrics to capture:
184+
- **Coverage**: How many files / instances were transformed
185+
- **Correctness**: Do both produce valid, equivalent code
186+
- **Edge cases**: Where do they diverge
187+
- **Performance**: Wall-clock execution time
188+
- **Errors**: Any crashes or partial transformations
189+
190+
---
191+
192+
## Notes
193+
194+
- Match counts are approximate (from grep.app searches, may include comments/docs)
195+
- Some repos are archived/unmaintained — that's fine for testing, the code patterns are what matter
196+
- `useFormState` testing is synthetic-only; recommend documenting this proactively for the React team
197+
- `useContext` is so widespread that any React 16.8+ repo works; no need for a dedicated test repo

0 commit comments

Comments
 (0)