meta(refactor-tasks): Add the no-custom-render-helper convention - #125244
Merged
Merged
Conversation
Test files keep growing local renderFoo() helpers that only forward their arguments into the shared render() or renderHookWithProviders() helper. Each file invents its own name and argument shape, so the JSX under test is hidden behind an indirection the reader has to look up first. The rule asks for an ExampleFoo component instead, so call sites stay in the shape used everywhere else. The react-testing skill gains the same guidance, since that is what agents and humans read while writing a test rather than the scanner config.
ryan953
marked this pull request as ready for review
September 22, 2026 20:16
…skill The section was longer than everything around it and carried a full LoadingContainer example. A generic Widget makes the same point in half the space, matching the terse style of the neighbouring rules.
natemoo-re
approved these changes
Sep 22, 2026
ryan953
added a commit
to getsentry/sentry-docs
that referenced
this pull request
Sep 22, 2026
…erFoo() helper (#19570) Adds a tip to the "Using React Testing Library" page: render the component under test, rather than wrapping `render()` in a local `renderFoo()` helper. The helper is common in `getsentry/sentry` specs and hides the JSX from every test that calls it, so a reader has to go find the helper before an `it()` block makes sense. Each file also invents its own name and argument shape for the same idea. The tip shows the `ExampleFoo` component shape we want instead, and sits with the other tips on the page. It calls out the part that actually breaks: `rerender` takes an element, so with a helper the call site no longer controls what is rendered. Passing a different root component type to `rerender` remounts the tree and silently drops the state the test was checking. That is not a hypothetical — converting 42 spec files in getsentry/sentry#125144 surfaced exactly this in two tests. The tip also names what is **not** this pattern, so it does not read as a ban on all test helpers: a helper that only registers `MockApiClient` mocks, or one that takes the element to render as a parameter, is fine as it is. ## Related - getsentry/sentry#125144 converts 42 spec files to this shape. - getsentry/sentry#125244 adds the `no-custom-render-helper` scanner convention and the matching note in the repo's `react-testing` skill.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a
no-custom-render-helperconvention to the@sentry/refactor-tasksconfig, so the daily scan starts reporting test files that hide their JSX behind a localrenderFoo()helper, and puts the same guidance in thereact-testingskill.The pattern the rule targets is a helper declared in a spec file whose only job is to forward its arguments into the shared
render()/renderGlobalModal()/renderHookWithProviders()helper fromsentry-test/reactTestingLibrary. Every file invents its own name and argument shape, so a reader has to go find the helper before anyit()block makes sense.The fix the rule asks for is a component, not an inlined
render()call at every call site:The skill change matters more than the config: the skill is what agents and humans read while writing a test, whereas the scanner config only produces findings after the fact.
Known problem, and why this is a draft
The rule does not work on the scanner's default model. Two
-m haikuruns both aborted with a non-JSON reply from theclaude-clibackend (Unexpected token 'I', "I already "..., thenUnexpected token '<', "<Structure"...), and the run exits 1 while printing a misleadingNo violations found.. On-m sonnetit returns 58 violations in 82s and exits 0. As a control,no-class-componentson the same haiku backend returned 56 violations cleanly, so the backend is healthy and the problem is specific to this rule — most likely its prompt length. The scheduled workflow uses the default model, so this needs sorting before it merges.What the rule gets wrong today
Running it against
mastersurfaced two gaps worth fixing in thedetecttext before this lands:render()", which leaves helpers that do both mock setup and rendering undefined. That is what produced the borderline findings inkeyRateLimitsForm,releasesSelectControl,transactionReplays/indexandgsAdmin/sentryAppDetails.render()options from their arguments are flagged, but converting them is a regression:resultGrid#renderGridwould repeat a router-config block across 29 call sites. Same forpageFilters/container,onboardingLayoutandrelocation.It also produced one clear false positive:
spansTableL163-173 is a JSX-returning arrow that never callsrender, which the rule already exempts in prose.Related
The 42 spec files this rule found and that have already been converted are in #125144. That PR is independent of this one and can land first.
No feature flags. No screenshots — this is a scanner config and a skill doc, with no UI surface.