Skip to content

Instantly share code, notes, and snippets.

View claudiainbytes's full-sized avatar

Claudia Estupiñán Forero claudiainbytes

View GitHub Profile
@claudiainbytes
claudiainbytes / gist:8cb80295669bfaa782efee746deb1908
Created February 11, 2026 19:06
Testing con Timers y Debounce
// Component con debounce
const SearchInput = ({ onSearch }) => {
const [value, setValue] = useState('')
useEffect(() => {
const timer = setTimeout(() => {
onSearch(value)
}, 300)
return () => clearTimeout(timer)
@claudiainbytes
claudiainbytes / gist:69182d16fff1dea8e4c1686b94ae234c
Created February 11, 2026 19:06
Testing Custom Render con Múltiples Providers
// test-utils/custom-render.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { AuthProvider } from '@/contexts/AuthContext'
import { ThemeProvider } from '@/contexts/ThemeContext'
interface RenderOptions {
initialUser?: User
theme?: 'light' | 'dark'
queryClient?: QueryClient
}
@claudiainbytes
claudiainbytes / gist:7c09f3581c40fc1129a5112d7188c8eb
Created February 11, 2026 19:05
Testing Page Object Pattern
// test-utils/page-objects/LoginPage.ts
export class LoginPage {
constructor(private user: ReturnType<typeof userEvent.setup>) {}
async login(email: string, password: string) {
await this.user.type(screen.getByLabelText(/email/i), email)
await this.user.type(screen.getByLabelText(/password/i), password)
await this.user.click(screen.getByRole('button', { name: /login/i }))
}
it('sube archivo', async () => {
const user = userEvent.setup()
const handleUpload = vi.fn()
render(<FileUpload onUpload={handleUpload} />)
const file = new File(['hello'], 'hello.png', { type: 'image/png' })
const input = screen.getByLabelText(/upload/i)
await user.upload(input, file)
@claudiainbytes
claudiainbytes / gist:a3eda4579b3e3e447e522218a7143a2a
Created February 11, 2026 19:00
Testing Keyboard Navigation
it('navega con teclado', async () => {
const user = userEvent.setup()
render(<Dropdown options={['Option 1', 'Option 2', 'Option 3']} />)
const trigger = screen.getByRole('button', { name: /select/i })
// Abrir con Enter
await user.click(trigger)
// Navegar con flechas
import { fireEvent } from '@testing-library/react'
it('permite drag and drop de items', async () => {
const user = userEvent.setup()
render(<DraggableList />)
const item1 = screen.getByText('Item 1')
const item2 = screen.getByText('Item 2')
// Simular drag and drop
@claudiainbytes
claudiainbytes / gist:d7f3e72150519ad7a80070a238967c10
Created February 11, 2026 18:53
Testing de useEffect y Side Effects
// Component
const UserProfile = ({ userId }) => {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
const fetchUser = async () => {
setLoading(true)
const response = await fetch(`/api/users/${userId}`)
const data = await response.json()
@claudiainbytes
claudiainbytes / gist:b44cc7291178bf0fe7a57401cd2dd140
Created February 11, 2026 18:51
Testing de React Query / TanStack Query
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const createTestQueryClient = () => new QueryClient({
defaultOptions: {
queries: {
retry: false, // Deshabilitar reintentos en tests
cacheTime: 0,
},
},
})
@claudiainbytes
claudiainbytes / gist:4f1dd522044d112bb65b744b99cf2ac8
Created February 11, 2026 18:49
Testing Formularios Complejos
describe('Registration Form', () => {
it('valida y envía formulario completo', async () => {
const user = userEvent.setup()
const handleSubmit = vi.fn()
render(<RegistrationForm onSubmit={handleSubmit} />)
// Llenar campos
await user.type(screen.getByLabelText(/email/i), 'test@example.com')
await user.type(screen.getByLabelText(/password/i), 'SecurePass123!')
import { MemoryRouter, Routes, Route } from 'react-router-dom'
const renderWithRouter = (ui, { route = '/' } = {}) => {
return render(
<MemoryRouter initialEntries={[route]}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products/:id" element={<ProductDetail />} />
<Route path="/cart" element={<Cart />} />
</Routes>