DEV Community

Cover image for Unit/Component Testing React Apps: From 'Why Bother?' to 'Can't Live Without It'
Mohamed ikram
Mohamed ikram

Posted on โ€ข Edited on

3 1 1 1 1

Unit/Component Testing React Apps: From 'Why Bother?' to 'Can't Live Without It'

๐Ÿšจ Anatomy of a 3 AM Production Crisis: A Testing Tale

๐ŸŽญ The Scene:

// The innocent-looking code that ruined everyone's night
const getDomainUrl = (config: BackendConfig) => {
  return config.domain; // What could go wrong? Everything.
};
Enter fullscreen mode Exit fullscreen mode

๐Ÿ” Let's Debug Together: The Case of the Phantom Redirect

๐Ÿšจ The Crime Scene

Dashboard users land at undefined/rest-path after a "harmless" config change

  • Suspect: A sneaky backend configuration tweak
  • Weapon: Missing validation for domain paths
  • Motive: "It worked in dev!" ๐Ÿคฆ

Unit testing

describe('Domain Configuration', () => {
  it('should reject missing domain configuration', () => {
    const emptyConfig = {} as BackendConfig;
    expect(() => getDomainUrl(emptyConfig)).toThrow();
  });
});
Enter fullscreen mode Exit fullscreen mode

Code

const getDomainUrl = (config: BackendConfig): string => {
  if (!config.domain) {
    throw new DomainConfigError('Domain URL is required');
  }
  if (!isValidDomainUrl(config.domain)) {
    throw new DomainConfigError('Invalid domain URL format');
  }
  return config.domain;
};
Enter fullscreen mode Exit fullscreen mode

Component Testing

describe('RedirectHandler', () => {
  it('should handle domain configuration gracefully', () => {
    const mockConfig = {};
    const { getByTestId } = render(<RedirectHandler config={mockConfig} />);

    expect(getByTestId('config-error')).toBeInTheDocument();
    expect(captureError).toHaveBeenCalledWith(expect.any(DomainConfigError));
  });
});
Enter fullscreen mode Exit fullscreen mode

Code

const RedirectHandler: React.FC<{ config: BackendConfig }> = ({ config }) => {
  const [error, setError] = useState<string>();
  const navigate = useNavigate();

  useEffect(() => {
    try {
      const domainUrl = getDomainUrl(config);
      // Safely handle navigation
      navigate(`${domainUrl}/rest-path`);
    } catch (e) {
      if (e instanceof DomainConfigError) {
        setError(e.message);
        // Log to monitoring system
        captureError(e);
      }
    }
  }, [config, navigate]);

  if (error) {
    return (
      <ErrorBoundary>
        <ConfigurationError 
          message={error}
          retry={() => window.location.reload()}
        />
      </ErrorBoundary>
    );
  }

  return <LoadingSpinner />;
};
Enter fullscreen mode Exit fullscreen mode

๐Ÿ› ๏ธ The Evolution of Robust Domain Configuration

๐ŸŽฏ What Changed?

  • Prevention Layers:

    • Custom error types (InvalidDomainException)
    • Domain validation before redirect logic
    • Error boundaries to catch misconfigurations
  • Test-First Approach:

    • Wrote failing test for missing config first
    • Added domain validation logic
    • Simulated edge cases (malformed URLs, empty configs)
  • Better Error UX:

    • User-friendly message: "Oops! We hit a snag โ€“ try again?"
    • Retry button with auto-logging for engineers
    • Integrated error tracking (Sentry/Datadog)

๐Ÿš€ The Results

  • No more undefined redirects
  • Clear error tracking
  • Happy users (and developers who can sleep at night!)

๐ŸŽฏ The Tale of Two Developers: TDD vs. "We'll Test Later"

๐Ÿ‡ Bugs Bunny (Traditional):

  • 3 AM: Debugging while production burns
  • Result: Chasing midnight bugs, endless firefighting

โญ Iron Man (TDD):

"Test first, code with confidence."

  • Result: Deploys and sleeps soundly
  • Secret Weapon: Tests act as code armor

๐Ÿ”„ The Real Difference:

Same deadline, drastically different outcomes.

While Bugs Bunny chases production bugs at midnight, Iron Manโ€™s approach means:

๐Ÿ›ก๏ธ Prevention > Cure

  • Catches bugs before they reach production
  • Each test is a shield against future issues
  • No more 3 AM emergency fixes

๐ŸŽฏ Design That Makes Sense

  • Tests force you to think before coding
  • Code becomes naturally modular
  • Refactoring becomes a breeze

๐Ÿ“š Code That Tells a Story

  • Tests document how things should work
  • New team members get up to speed faster
  • Requirements are crystal clear

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

๐Ÿ‘‹ Kindness is contagious

Please leave a โค๏ธ or a friendly comment on this post if you found it helpful!

Okay