Query Strategy
Problem
Tests that select DOM elements using implementation details like CSS classes, IDs, or test-specific attributes break whenever markup changes. These brittle tests don’t reflect how users interact with your application, making them poor indicators of actual functionality. When tests query elements in ways users never would, they fail to catch real accessibility issues and user-facing bugs.
Solution
Declare what data you need and let a library handle fetching, caching, and synchronization. This provides loading states, error handling, and cache management without manual coordination.
Example
This example demonstrates declarative data fetching where the library automatically handles loading states, errors, and caching without manual coordination.
// Declaratively specify what data you need
const { data, isLoading, error } = useQuery('todos', () =>
fetch('/api/todos').then(res => res.json())
);
// Library automatically provides loading state
if (isLoading) return <Spinner />;
// And error handling
if (error) return <Error message={error.message} />;
// Data is cached and synchronized automatically
return <TodoList todos={data} />;
Benefits
- Eliminates boilerplate for loading states, error handling, and data management.
- Provides automatic caching and synchronization out of the box.
- Simplifies data fetching with declarative API.
- Handles edge cases like deduplication and background refetching automatically.
Tradeoffs
- Adds dependency on a data fetching library.
- Requires learning library-specific APIs and patterns.
- Can be overkill for simple applications with minimal data needs.
- May abstract away control when custom fetch logic is needed.