Something I’ve noticed in many React codebases is how little attention is given to testing the visual or presentational logic of components.
We write unit tests for business logic, integration tests for API flows, and sometimes even e2e tests for user journeys. But the part that actually shows up on the screen? The part users directly interact with — like spacing, colors, visibility of badges, or minHeight of a Textarea
— is often left untested.
Let me give you a recent example.
A Simple minHeight
Change That No One Tested
I was reviewing a PR where a minHeight
prop was added to a <Textarea>
component:
<Textarea
{...field}
minHeight={textareaHeight}
id={id}
sx={{ ... }}
/>
It looked like a minor tweak. But this kind of change can affect user experience — how much text the user sees without scrolling, whether layout breaks on mobile, and so on. And yet, there was no test to capture this. No Storybook update. Just a silent style change.
Should this have been tested?
Should You Test These Kinds of Changes?
Here’s my take:
You don’t need to test every visual detail. We don’t want our tests to break every time a pixel shifts. But if a visual change is dynamic, conditional, or essential to the user experience, then yes — it’s worth writing a test.
Ask yourself:
- Is this change based on a prop or state?
- Can removing this break the UX or accessibility?
- Was this added to fix a bug or a user-reported issue?
If the answer is yes, then a small test goes a long way.
🧨 Example: Auto-Growing Textarea Stops Growing
Here’s a simple example of how skipping presentational tests can lead to subtle but frustrating UX bugs.
Let’s say you have a <Textarea />
component that auto-expands based on input length. To make this work, you set a minHeight
style that prevents it from collapsing when there’s only one line of text.
<Textarea minHeight={100} />
Now imagine someone removes that minHeight
line in a later refactor, thinking it’s unnecessary.
What happens
- On mobile, the textarea shrinks to a single line.
- The text inside is barely readable.
- Users think it’s broken because they can’t see what they’re typing.
And because no test was written to confirm that minHeight
was applied, CI passes. No one notices until a user reports it — or worse, they don’t.
✅ How a Simple Test Would Catch This
render(<Textarea textareaHeight={100} />)
const textarea = screen.getByRole('textbox')
expect(textarea).toHaveStyle({ minHeight: '100px' })
This test would fail as soon as someone removes the minHeight
, alerting the team that a key UX behavior is now broken.
How to Write Tests for Presentational Logic
React Testing Library makes this relatively easy. For example, to test that a minHeight
is being applied:
render(<Textarea textareaHeight={150} />)
const textarea = screen.getByRole('textbox')
expect(textarea).toHaveStyle({ minHeight: '150px' })
This ensures that the component behaves as intended without testing the exact CSS or implementation details.
You can also check class names, visibility, or conditional elements:
expect(screen.getByText('New')).toBeInTheDocument()
expect(button).toHaveClass('active')
The goal isn’t to snapshot the DOM — it’s to verify that the component responds correctly to its inputs.
What About Storybook?
If your team uses Storybook, this is another good way to document visual changes. Especially when paired with Chromatic, which can highlight visual diffs during PRs.
But remember — Storybook is not a test. It’s a showcase. If you need to prevent regressions, a proper test is safer.
Final Thoughts
Just because a piece of logic is presentational doesn’t mean it’s not important. In fact, it’s often what users notice first.
Testing doesn’t have to be all or nothing. Even one test that checks a visual prop or state is better than ignoring it altogether.
So next time you make a visual change — a minHeight
, a hover style, a badge that shows up based on status — ask yourself:
Would I want to know if this broke later?
If yes, it deserves a test.