chore: remove GitHub Actions workflows, use Woodpecker CI exclusively
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
||||
import { renderHook, act } from '@testing-library/react';
|
||||
import { useFocusTrap } from './use-focus-trap';
|
||||
|
||||
describe('useFocusTrap', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Initial State', () => {
|
||||
it('should return a ref', () => {
|
||||
const { result } = renderHook(() => useFocusTrap<HTMLDivElement>(false));
|
||||
expect(result.current).toBeDefined();
|
||||
expect(result.current.current).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('When Active', () => {
|
||||
it('should store previous active element', () => {
|
||||
const { result } = renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
|
||||
it('should add keydown event listener', () => {
|
||||
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
|
||||
renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
expect(addEventListenerSpy).toHaveBeenCalledWith('keydown', expect.any(Function));
|
||||
});
|
||||
|
||||
it('should set body overflow to hidden', () => {
|
||||
renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
expect(document.body.style.overflow).toBe('hidden');
|
||||
});
|
||||
});
|
||||
|
||||
describe('When Inactive', () => {
|
||||
it('should not add keydown event listener', () => {
|
||||
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
|
||||
renderHook(() => useFocusTrap<HTMLDivElement>(false));
|
||||
expect(addEventListenerSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not set body overflow', () => {
|
||||
renderHook(() => useFocusTrap<HTMLDivElement>(false));
|
||||
expect(document.body.style.overflow).toBe('unset');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cleanup', () => {
|
||||
it('should remove keydown event listener on unmount', () => {
|
||||
const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener');
|
||||
const { unmount } = renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
unmount();
|
||||
expect(removeEventListenerSpy).toHaveBeenCalledWith('keydown', expect.any(Function));
|
||||
});
|
||||
|
||||
it('should restore body overflow on unmount', () => {
|
||||
const { unmount } = renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
unmount();
|
||||
expect(document.body.style.overflow).toBe('unset');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tab Navigation', () => {
|
||||
it('should handle Tab key press', () => {
|
||||
const { result } = renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
|
||||
const mockEvent = new KeyboardEvent('keydown', { key: 'Tab' });
|
||||
document.dispatchEvent(mockEvent);
|
||||
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle Shift+Tab key press', () => {
|
||||
const { result } = renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
|
||||
const mockEvent = new KeyboardEvent('keydown', { key: 'Tab', shiftKey: true });
|
||||
document.dispatchEvent(mockEvent);
|
||||
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Escape Key', () => {
|
||||
it('should handle Escape key press', () => {
|
||||
const { result } = renderHook(() => useFocusTrap<HTMLDivElement>(true));
|
||||
|
||||
const mockEvent = new KeyboardEvent('keydown', { key: 'Escape' });
|
||||
document.dispatchEvent(mockEvent);
|
||||
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('State Changes', () => {
|
||||
it('should handle activation change', () => {
|
||||
const { result, rerender } = renderHook(
|
||||
({ isActive }) => useFocusTrap<HTMLDivElement>(isActive),
|
||||
{ initialProps: { isActive: false } }
|
||||
);
|
||||
|
||||
expect(result.current).toBeDefined();
|
||||
|
||||
rerender({ isActive: true });
|
||||
expect(document.body.style.overflow).toBe('hidden');
|
||||
|
||||
rerender({ isActive: false });
|
||||
expect(document.body.style.overflow).toBe('unset');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useIntersectionObserver } from './use-intersection-observer';
|
||||
|
||||
describe('useIntersectionObserver', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Initial State', () => {
|
||||
it('should return ref and isIntersecting state', () => {
|
||||
const { result } = renderHook(() => useIntersectionObserver<HTMLDivElement>());
|
||||
expect(result.current[0]).toBeDefined();
|
||||
expect(typeof result.current[1]).toBe('boolean');
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
|
||||
it('should return ref with null current value', () => {
|
||||
const { result } = renderHook(() => useIntersectionObserver<HTMLDivElement>());
|
||||
expect(result.current[0].current).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Options', () => {
|
||||
it('should accept threshold option', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useIntersectionObserver<HTMLDivElement>({ threshold: 0.5 })
|
||||
);
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
|
||||
it('should accept root option', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useIntersectionObserver<HTMLDivElement>({ root: null })
|
||||
);
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
|
||||
it('should accept rootMargin option', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useIntersectionObserver<HTMLDivElement>({ rootMargin: '10px' })
|
||||
);
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
|
||||
it('should accept freezeOnceVisible option', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useIntersectionObserver<HTMLDivElement>({ freezeOnceVisible: true })
|
||||
);
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
|
||||
it('should use default options', () => {
|
||||
const { result } = renderHook(() => useIntersectionObserver<HTMLDivElement>());
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
|
||||
it('should accept multiple thresholds', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useIntersectionObserver<HTMLDivElement>({ threshold: [0, 0.25, 0.5, 0.75, 1] })
|
||||
);
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Behavior', () => {
|
||||
it('should not observe when freezeOnceVisible is true and already intersecting', () => {
|
||||
const { result, rerender } = renderHook(() =>
|
||||
useIntersectionObserver<HTMLDivElement>({ freezeOnceVisible: true })
|
||||
);
|
||||
|
||||
expect(result.current[1]).toBe(false);
|
||||
|
||||
rerender();
|
||||
expect(result.current[1]).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cleanup', () => {
|
||||
it('should cleanup observer on unmount', () => {
|
||||
const { unmount } = renderHook(() => useIntersectionObserver<HTMLDivElement>());
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Type Safety', () => {
|
||||
it('should work with different element types', () => {
|
||||
const { result: result1 } = renderHook(() => useIntersectionObserver<HTMLDivElement>());
|
||||
const { result: result2 } = renderHook(() => useIntersectionObserver<HTMLSpanElement>());
|
||||
const { result: result3 } = renderHook(() => useIntersectionObserver<HTMLElement>());
|
||||
|
||||
expect(result1.current[1]).toBe(false);
|
||||
expect(result2.current[1]).toBe(false);
|
||||
expect(result3.current[1]).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,74 @@
|
||||
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useMediaQuery, useIsMobile, useIsTablet, useIsDesktop } from './use-media-query';
|
||||
|
||||
describe('useMediaQuery', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('useMediaQuery', () => {
|
||||
it('should return false on server side', () => {
|
||||
const { result } = renderHook(() => useMediaQuery('(min-width: 768px)'));
|
||||
expect(result.current).toBe(false);
|
||||
});
|
||||
|
||||
it('should return boolean value', () => {
|
||||
const { result } = renderHook(() => useMediaQuery('(min-width: 768px)'));
|
||||
expect(typeof result.current).toBe('boolean');
|
||||
});
|
||||
});
|
||||
|
||||
describe('useIsMobile', () => {
|
||||
it('should return boolean value', () => {
|
||||
const { result } = renderHook(() => useIsMobile());
|
||||
expect(typeof result.current).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should use correct media query', () => {
|
||||
const { result } = renderHook(() => useIsMobile());
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('useIsTablet', () => {
|
||||
it('should return boolean value', () => {
|
||||
const { result } = renderHook(() => useIsTablet());
|
||||
expect(typeof result.current).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should use correct media query', () => {
|
||||
const { result } = renderHook(() => useIsTablet());
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('useIsDesktop', () => {
|
||||
it('should return boolean value', () => {
|
||||
const { result } = renderHook(() => useIsDesktop());
|
||||
expect(typeof result.current).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should use correct media query', () => {
|
||||
const { result } = renderHook(() => useIsDesktop());
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Media Query Behavior', () => {
|
||||
it('should handle different queries', () => {
|
||||
const { result: result1 } = renderHook(() => useMediaQuery('(min-width: 1024px)'));
|
||||
const { result: result2 } = renderHook(() => useMediaQuery('(max-width: 767px)'));
|
||||
|
||||
expect(typeof result1.current).toBe('boolean');
|
||||
expect(typeof result2.current).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should handle complex queries', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useMediaQuery('(min-width: 768px) and (max-width: 1023px)')
|
||||
);
|
||||
expect(typeof result.current).toBe('boolean');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useScrollReveal, useScrollProgress, useParallax } from './use-scroll-reveal';
|
||||
|
||||
describe('useScrollReveal', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('useScrollReveal', () => {
|
||||
it('should return ref and isVisible state', () => {
|
||||
const { result } = renderHook(() => useScrollReveal());
|
||||
expect(result.current).toHaveProperty('ref');
|
||||
expect(result.current).toHaveProperty('isVisible');
|
||||
expect(result.current.isVisible).toBe(false);
|
||||
});
|
||||
|
||||
it('should accept custom options', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useScrollReveal({ threshold: 0.5, rootMargin: '10px', triggerOnce: false })
|
||||
);
|
||||
expect(result.current).toHaveProperty('ref');
|
||||
expect(result.current).toHaveProperty('isVisible');
|
||||
});
|
||||
|
||||
it('should use default options', () => {
|
||||
const { result } = renderHook(() => useScrollReveal());
|
||||
expect(result.current.isVisible).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useScrollProgress', () => {
|
||||
it('should return progress value', () => {
|
||||
const { result } = renderHook(() => useScrollProgress());
|
||||
expect(typeof result.current).toBe('number');
|
||||
expect(result.current).toBeGreaterThanOrEqual(0);
|
||||
expect(result.current).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
it('should accept threshold option', () => {
|
||||
const { result } = renderHook(() => useScrollProgress({ threshold: 0.5 }));
|
||||
expect(typeof result.current).toBe('number');
|
||||
});
|
||||
|
||||
it('should use default threshold', () => {
|
||||
const { result } = renderHook(() => useScrollProgress());
|
||||
expect(result.current).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('useParallax', () => {
|
||||
it('should return ref and offset', () => {
|
||||
const { result } = renderHook(() => useParallax());
|
||||
expect(result.current).toHaveProperty('ref');
|
||||
expect(result.current).toHaveProperty('offset');
|
||||
expect(typeof result.current.offset).toBe('number');
|
||||
});
|
||||
|
||||
it('should accept speed option', () => {
|
||||
const { result } = renderHook(() => useParallax({ speed: 0.8 }));
|
||||
expect(result.current).toHaveProperty('ref');
|
||||
expect(result.current).toHaveProperty('offset');
|
||||
});
|
||||
|
||||
it('should use default speed', () => {
|
||||
const { result } = renderHook(() => useParallax());
|
||||
expect(result.current.offset).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle different speed values', () => {
|
||||
const { result: result1 } = renderHook(() => useParallax({ speed: 0 }));
|
||||
const { result: result2 } = renderHook(() => useParallax({ speed: 1 }));
|
||||
|
||||
expect(result1.current.offset).toBeDefined();
|
||||
expect(result2.current.offset).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Cleanup', () => {
|
||||
it('should cleanup intersection observer on unmount', () => {
|
||||
const { unmount } = renderHook(() => useScrollReveal());
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should cleanup scroll listener on unmount', () => {
|
||||
const { unmount } = renderHook(() => useScrollProgress());
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should cleanup parallax scroll listener on unmount', () => {
|
||||
const { unmount } = renderHook(() => useParallax());
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user