From 22baa416e87899aaefb01707ed8f5b4ff94df3b1 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Tue, 22 Sep 2026 13:02:18 -0700 Subject: [PATCH 1/2] docs(frontend): Note that tests should render a component, not a renderFoo() helper A local renderFoo() helper hides the JSX from every test that calls it, and it breaks rerender, which takes an element. The tip sits with the other RTL tips and shows the Example component shape we want instead. --- develop-docs/frontend/using-rtl.mdx | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/develop-docs/frontend/using-rtl.mdx b/develop-docs/frontend/using-rtl.mdx index ed64d61a141f6..84ca64e47b9dc 100644 --- a/develop-docs/frontend/using-rtl.mdx +++ b/develop-docs/frontend/using-rtl.mdx @@ -340,6 +340,40 @@ render(); userEvent.type(screen.getByLabelText("Search by name"), "sentry"); ``` +Render the component under test, don't wrap `render()` in a local helper. + +A `renderFoo()` helper 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. Put the fixed props, wrapper providers and glue in a component instead, and render that. + +```tsx +import {render} from "sentry-test/reactTestingLibrary"; + +// ❌ +function renderComponent(props: LoadingContainerProps = {}) { + return render( + +
hello!
+
+ ); +} +renderComponent({isLoading: true}); + +// ✅ +function ExampleLoadingContainer(props: LoadingContainerProps) { + return ( + +
hello!
+
+ ); +} +render(); +``` + +This matters most for `rerender`, which takes an element. With a helper, the call site no longer controls what is rendered, and passing a different root component type to `rerender` remounts the tree and drops the state the test was checking. Declare the component at module scope so `rerender` keeps the same component type. + +Keep `render()` options such as `organization`, `initialRouterConfig` and `additionalWrapper` at the call site. If the helper adds nothing over the component's own props, drop it and call `render()` directly. + +A helper that only registers `MockApiClient` mocks, or one that takes the element to render as a parameter, is a different thing and is fine as it is. + ## Testing hooks with providers Use `renderHookWithProviders()` to test hooks with the same built-in providers as `render()` (organization, theme, query client, and an in-memory router). It returns the regular `renderHook` result plus a `router` helper you can use to inspect location and navigate. From 4721daacb04480a8351b95626be7e1cb93ea4554 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Tue, 22 Sep 2026 13:17:12 -0700 Subject: [PATCH 2/2] docs(frontend): Tighten the render-helper tip The tip was longer than the tips around it. A generic Widget makes the same point in half the space. --- develop-docs/frontend/using-rtl.mdx | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/develop-docs/frontend/using-rtl.mdx b/develop-docs/frontend/using-rtl.mdx index 84ca64e47b9dc..70db720f8f226 100644 --- a/develop-docs/frontend/using-rtl.mdx +++ b/develop-docs/frontend/using-rtl.mdx @@ -341,38 +341,24 @@ userEvent.type(screen.getByLabelText("Search by name"), "sentry"); ``` Render the component under test, don't wrap `render()` in a local helper. - -A `renderFoo()` helper 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. Put the fixed props, wrapper providers and glue in a component instead, and render that. +A helper hides the JSX from every test that calls it, and `rerender` takes an element, so the call site can no longer control what renders. ```tsx import {render} from "sentry-test/reactTestingLibrary"; // ❌ -function renderComponent(props: LoadingContainerProps = {}) { - return render( - -
hello!
-
- ); +function renderComponent(props: Props = {}) { + return render(hello); } -renderComponent({isLoading: true}); // ✅ -function ExampleLoadingContainer(props: LoadingContainerProps) { - return ( - -
hello!
-
- ); +function ExampleWidget(props: Props) { + return hello; } -render(); +render(); ``` -This matters most for `rerender`, which takes an element. With a helper, the call site no longer controls what is rendered, and passing a different root component type to `rerender` remounts the tree and drops the state the test was checking. Declare the component at module scope so `rerender` keeps the same component type. - -Keep `render()` options such as `organization`, `initialRouterConfig` and `additionalWrapper` at the call site. If the helper adds nothing over the component's own props, drop it and call `render()` directly. - -A helper that only registers `MockApiClient` mocks, or one that takes the element to render as a parameter, is a different thing and is fine as it is. +Declare it at module scope so `rerender` keeps the same component type, and keep `render()` options at the call site. Helpers that only register mocks, or that take the element as a parameter, are fine. ## Testing hooks with providers