chore: remove GitHub Actions workflows, use Woodpecker CI exclusively
This commit is contained in:
@@ -0,0 +1,539 @@
|
||||
import { describe, it, expect, jest } from '@jest/globals';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
jest.mock('framer-motion', () => ({
|
||||
motion: {
|
||||
div: ({ children, initial, animate, variants, className, whileHover, whileTap, ...props }: any) => (
|
||||
<div
|
||||
data-testid="motion-div"
|
||||
data-initial={JSON.stringify(initial)}
|
||||
data-animate={JSON.stringify(animate)}
|
||||
data-variants={JSON.stringify(variants)}
|
||||
data-while-hover={JSON.stringify(whileHover)}
|
||||
data-while-tap={JSON.stringify(whileTap)}
|
||||
className={className}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
button: ({ children, onClick, className, whileHover, whileTap, ...props }: any) => (
|
||||
<button
|
||||
data-testid="motion-button"
|
||||
onClick={onClick}
|
||||
className={className}
|
||||
data-while-hover={JSON.stringify(whileHover)}
|
||||
data-while-tap={JSON.stringify(whileTap)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
span: ({ children, className, animate, ...props }: any) => (
|
||||
<span
|
||||
data-testid="motion-span"
|
||||
className={className}
|
||||
data-animate={JSON.stringify(animate)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
),
|
||||
svg: ({ children, className, ...props }: any) => (
|
||||
<svg data-testid="motion-svg" className={className} {...props}>
|
||||
{children}
|
||||
</svg>
|
||||
),
|
||||
circle: ({ variants, ...props }: any) => (
|
||||
<circle data-testid="motion-circle" data-variants={JSON.stringify(variants)} {...props} />
|
||||
),
|
||||
path: ({ variants, ...props }: any) => (
|
||||
<path data-testid="motion-path" data-variants={JSON.stringify(variants)} {...props} />
|
||||
),
|
||||
},
|
||||
useInView: jest.fn(() => true),
|
||||
useSpring: jest.fn((value) => value),
|
||||
useTransform: jest.fn((value) => value),
|
||||
}));
|
||||
|
||||
describe('Animation Variants', () => {
|
||||
describe('inkVariants', () => {
|
||||
it('should have correct hidden state', async () => {
|
||||
const { inkVariants } = await import('./animations');
|
||||
expect(inkVariants.hidden).toEqual({
|
||||
opacity: 0,
|
||||
scale: 0.8,
|
||||
filter: 'blur(10px)',
|
||||
});
|
||||
});
|
||||
|
||||
it('should have correct visible state', async () => {
|
||||
const { inkVariants } = await import('./animations');
|
||||
expect(inkVariants.visible).toHaveProperty('opacity', 1);
|
||||
expect(inkVariants.visible).toHaveProperty('scale', 1);
|
||||
expect(inkVariants.visible).toHaveProperty('filter', 'blur(0px)');
|
||||
});
|
||||
|
||||
it('should have correct transition configuration', async () => {
|
||||
const { inkVariants } = await import('./animations');
|
||||
const transition = inkVariants.visible.transition as any;
|
||||
expect(transition.duration).toBe(0.8);
|
||||
expect(transition.ease).toEqual([0.16, 1, 0.3, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sealStampVariants', () => {
|
||||
it('should have correct hidden state', async () => {
|
||||
const { sealStampVariants } = await import('./animations');
|
||||
expect(sealStampVariants.hidden).toEqual({
|
||||
opacity: 0,
|
||||
scale: 1.5,
|
||||
rotate: -15,
|
||||
});
|
||||
});
|
||||
|
||||
it('should have correct visible state', async () => {
|
||||
const { sealStampVariants } = await import('./animations');
|
||||
expect(sealStampVariants.visible).toHaveProperty('opacity', 1);
|
||||
expect(sealStampVariants.visible).toHaveProperty('scale', 1);
|
||||
expect(sealStampVariants.visible).toHaveProperty('rotate', 0);
|
||||
});
|
||||
|
||||
it('should use spring animation', async () => {
|
||||
const { sealStampVariants } = await import('./animations');
|
||||
const transition = sealStampVariants.visible.transition as any;
|
||||
expect(transition.type).toBe('spring');
|
||||
expect(transition.stiffness).toBe(300);
|
||||
expect(transition.damping).toBe(20);
|
||||
});
|
||||
});
|
||||
|
||||
describe('brushStrokeVariants', () => {
|
||||
it('should have correct hidden state', async () => {
|
||||
const { brushStrokeVariants } = await import('./animations');
|
||||
expect(brushStrokeVariants.hidden).toEqual({
|
||||
pathLength: 0,
|
||||
opacity: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should have correct visible state', async () => {
|
||||
const { brushStrokeVariants } = await import('./animations');
|
||||
expect(brushStrokeVariants.visible).toHaveProperty('pathLength', 1);
|
||||
expect(brushStrokeVariants.visible).toHaveProperty('opacity', 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fadeUpVariants', () => {
|
||||
it('should have correct hidden state', async () => {
|
||||
const { fadeUpVariants } = await import('./animations');
|
||||
expect(fadeUpVariants.hidden).toEqual({
|
||||
opacity: 0,
|
||||
y: 30,
|
||||
});
|
||||
});
|
||||
|
||||
it('should have correct visible state', async () => {
|
||||
const { fadeUpVariants } = await import('./animations');
|
||||
expect(fadeUpVariants.visible).toHaveProperty('opacity', 1);
|
||||
expect(fadeUpVariants.visible).toHaveProperty('y', 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('staggerContainerVariants', () => {
|
||||
it('should have staggerChildren configured', async () => {
|
||||
const { staggerContainerVariants } = await import('./animations');
|
||||
const transition = staggerContainerVariants.visible.transition as any;
|
||||
expect(transition.staggerChildren).toBe(0.1);
|
||||
expect(transition.delayChildren).toBe(0.1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('staggerItemVariants', () => {
|
||||
it('should have correct hidden state', async () => {
|
||||
const { staggerItemVariants } = await import('./animations');
|
||||
expect(staggerItemVariants.hidden).toEqual({
|
||||
opacity: 0,
|
||||
y: 20,
|
||||
scale: 0.95,
|
||||
});
|
||||
});
|
||||
|
||||
it('should have correct visible state', async () => {
|
||||
const { staggerItemVariants } = await import('./animations');
|
||||
expect(staggerItemVariants.visible).toHaveProperty('opacity', 1);
|
||||
expect(staggerItemVariants.visible).toHaveProperty('y', 0);
|
||||
expect(staggerItemVariants.visible).toHaveProperty('scale', 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animation Components', () => {
|
||||
describe('InkReveal', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { InkReveal } = await import('./animations');
|
||||
render(<InkReveal>Test Content</InkReveal>);
|
||||
expect(screen.getByText('Test Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { InkReveal } = await import('./animations');
|
||||
render(<InkReveal className="custom-class">Test</InkReveal>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
expect(element).toHaveClass('custom-class');
|
||||
});
|
||||
|
||||
it('should use inkVariants', async () => {
|
||||
const { InkReveal, inkVariants } = await import('./animations');
|
||||
render(<InkReveal>Test</InkReveal>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
const variants = JSON.parse(element.getAttribute('data-variants') || '{}');
|
||||
expect(variants).toEqual(inkVariants);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SealStamp', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { SealStamp } = await import('./animations');
|
||||
render(<SealStamp>Seal Content</SealStamp>);
|
||||
expect(screen.getByText('Seal Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { SealStamp } = await import('./animations');
|
||||
render(<SealStamp className="seal-class">Test</SealStamp>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
expect(element).toHaveClass('seal-class');
|
||||
});
|
||||
});
|
||||
|
||||
describe('FadeUp', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { FadeUp } = await import('./animations');
|
||||
render(<FadeUp>Fade Content</FadeUp>);
|
||||
expect(screen.getByText('Fade Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom duration', async () => {
|
||||
const { FadeUp } = await import('./animations');
|
||||
render(<FadeUp duration={1.2}>Test</FadeUp>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
const variants = JSON.parse(element.getAttribute('data-variants') || '{}');
|
||||
expect(variants.visible.transition.duration).toBe(1.2);
|
||||
});
|
||||
|
||||
it('should apply delay prop', async () => {
|
||||
const { FadeUp } = await import('./animations');
|
||||
render(<FadeUp delay={0.3}>Test</FadeUp>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
const variants = JSON.parse(element.getAttribute('data-variants') || '{}');
|
||||
expect(variants.visible.transition.delay).toBe(0.3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('StaggerContainer', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { StaggerContainer } = await import('./animations');
|
||||
render(
|
||||
<StaggerContainer>
|
||||
<div>Item 1</div>
|
||||
<div>Item 2</div>
|
||||
</StaggerContainer>
|
||||
);
|
||||
expect(screen.getByText('Item 1')).toBeInTheDocument();
|
||||
expect(screen.getByText('Item 2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom staggerDelay', async () => {
|
||||
const { StaggerContainer } = await import('./animations');
|
||||
render(<StaggerContainer staggerDelay={0.2}>Test</StaggerContainer>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
const variants = JSON.parse(element.getAttribute('data-variants') || '{}');
|
||||
expect(variants.visible.transition.staggerChildren).toBe(0.2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('StaggerItem', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { StaggerItem } = await import('./animations');
|
||||
render(<StaggerItem>Item Content</StaggerItem>);
|
||||
expect(screen.getByText('Item Content')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('RippleButton', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { RippleButton } = await import('./animations');
|
||||
render(<RippleButton>Click Me</RippleButton>);
|
||||
expect(screen.getByText('Click Me')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle click events', async () => {
|
||||
const { RippleButton } = await import('./animations');
|
||||
const handleClick = jest.fn();
|
||||
render(<RippleButton onClick={handleClick}>Click Me</RippleButton>);
|
||||
|
||||
const button = screen.getByTestId('motion-button');
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(handleClick).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { RippleButton } = await import('./animations');
|
||||
render(<RippleButton className="custom-button">Test</RippleButton>);
|
||||
const element = screen.getByTestId('motion-button');
|
||||
expect(element).toHaveClass('custom-button');
|
||||
});
|
||||
});
|
||||
|
||||
describe('InkCard', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { InkCard } = await import('./animations');
|
||||
render(<InkCard>Card Content</InkCard>);
|
||||
expect(screen.getByText('Card Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom hoverScale', async () => {
|
||||
const { InkCard } = await import('./animations');
|
||||
render(<InkCard hoverScale={1.1}>Test</InkCard>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
const whileHover = JSON.parse(element.getAttribute('data-while-hover') || '{}');
|
||||
expect(whileHover.scale).toBe(1.1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CountUp', () => {
|
||||
it('should render with prefix and suffix', async () => {
|
||||
const { CountUp } = await import('./animations');
|
||||
render(<CountUp end={100} prefix="$" suffix="%" />);
|
||||
expect(screen.getByText(/\$/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/%/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { CountUp } = await import('./animations');
|
||||
render(<CountUp end={100} className="counter-class" />);
|
||||
const element = screen.getByTestId('motion-span');
|
||||
expect(element).toHaveClass('counter-class');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Typewriter', () => {
|
||||
it('should render component correctly', async () => {
|
||||
const { Typewriter } = await import('./animations');
|
||||
render(<Typewriter text="Hello" />);
|
||||
const cursor = screen.getByText('|');
|
||||
expect(cursor).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { Typewriter } = await import('./animations');
|
||||
render(<Typewriter text="Test" className="typewriter-class" />);
|
||||
const container = screen.getByText('|').closest('.typewriter-class');
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('FloatingElement', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { FloatingElement } = await import('./animations');
|
||||
render(<FloatingElement>Floating Content</FloatingElement>);
|
||||
expect(screen.getByText('Floating Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom amplitude', async () => {
|
||||
const { FloatingElement } = await import('./animations');
|
||||
render(<FloatingElement amplitude={20}>Test</FloatingElement>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
const animate = JSON.parse(element.getAttribute('data-animate') || '{}');
|
||||
expect(animate.y).toEqual([-20, 20, -20]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('PulseElement', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { PulseElement } = await import('./animations');
|
||||
render(<PulseElement>Pulse Content</PulseElement>);
|
||||
expect(screen.getByText('Pulse Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom scale', async () => {
|
||||
const { PulseElement } = await import('./animations');
|
||||
render(<PulseElement scale={1.1}>Test</PulseElement>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
const animate = JSON.parse(element.getAttribute('data-animate') || '{}');
|
||||
expect(animate.scale).toEqual([1, 1.1, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GradientText', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { GradientText } = await import('./animations');
|
||||
render(<GradientText>Gradient Text</GradientText>);
|
||||
expect(screen.getByText('Gradient Text')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom colors', async () => {
|
||||
const { GradientText } = await import('./animations');
|
||||
render(<GradientText colors={['#ff0000', '#00ff00', '#0000ff']}>Test</GradientText>);
|
||||
const element = screen.getByTestId('motion-span');
|
||||
expect(element).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('SplitText', () => {
|
||||
it('should render text correctly', async () => {
|
||||
const { SplitText } = await import('./animations');
|
||||
render(<SplitText text="Hi" />);
|
||||
expect(screen.getByText('H')).toBeInTheDocument();
|
||||
expect(screen.getByText('i')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { SplitText } = await import('./animations');
|
||||
render(<SplitText text="Test" className="split-class" />);
|
||||
const elements = screen.getAllByTestId('motion-span');
|
||||
const parentElement = elements.find(el => el.classList.contains('split-class'));
|
||||
expect(parentElement).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GlitchText', () => {
|
||||
it('should render text correctly', async () => {
|
||||
const { GlitchText } = await import('./animations');
|
||||
render(<GlitchText text="Glitch" />);
|
||||
const glitchElements = screen.getAllByText('Glitch');
|
||||
expect(glitchElements.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { GlitchText } = await import('./animations');
|
||||
render(<GlitchText text="Test" className="glitch-class" />);
|
||||
const testElements = screen.getAllByText('Test');
|
||||
const container = testElements[0].closest('.glitch-class');
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('MagneticButton', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { MagneticButton } = await import('./animations');
|
||||
render(<MagneticButton>Magnetic</MagneticButton>);
|
||||
expect(screen.getByText('Magnetic')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle click events', async () => {
|
||||
const { MagneticButton } = await import('./animations');
|
||||
const handleClick = jest.fn();
|
||||
render(<MagneticButton onClick={handleClick}>Click</MagneticButton>);
|
||||
|
||||
const element = screen.getByText('Click');
|
||||
fireEvent.click(element);
|
||||
|
||||
expect(handleClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('BlurReveal', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { BlurReveal } = await import('./animations');
|
||||
render(<BlurReveal>Blur Content</BlurReveal>);
|
||||
expect(screen.getByText('Blur Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { BlurReveal } = await import('./animations');
|
||||
render(<BlurReveal className="blur-class">Test</BlurReveal>);
|
||||
const element = screen.getByTestId('motion-div');
|
||||
expect(element).toHaveClass('blur-class');
|
||||
});
|
||||
});
|
||||
|
||||
describe('WaveText', () => {
|
||||
it('should render text correctly', async () => {
|
||||
const { WaveText } = await import('./animations');
|
||||
render(<WaveText text="Hi" />);
|
||||
expect(screen.getByText('H')).toBeInTheDocument();
|
||||
expect(screen.getByText('i')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ShimmerButton', () => {
|
||||
it('should render children correctly', async () => {
|
||||
const { ShimmerButton } = await import('./animations');
|
||||
render(<ShimmerButton>Shimmer</ShimmerButton>);
|
||||
expect(screen.getByText('Shimmer')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle click events', async () => {
|
||||
const { ShimmerButton } = await import('./animations');
|
||||
const handleClick = jest.fn();
|
||||
render(<ShimmerButton onClick={handleClick}>Click</ShimmerButton>);
|
||||
|
||||
const button = screen.getByTestId('motion-button');
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(handleClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Animation Hooks', () => {
|
||||
describe('useParallax', () => {
|
||||
it('should be defined', async () => {
|
||||
const { useParallax } = await import('./animations');
|
||||
expect(useParallax).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('useSmoothSpring', () => {
|
||||
it('should be defined', async () => {
|
||||
const { useSmoothSpring } = await import('./animations');
|
||||
expect(useSmoothSpring).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SVG Components', () => {
|
||||
describe('InkDropSVG', () => {
|
||||
it('should render SVG correctly', async () => {
|
||||
const { InkDropSVG } = await import('./animations');
|
||||
render(<InkDropSVG />);
|
||||
expect(screen.getByTestId('motion-svg')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('motion-circle')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom className', async () => {
|
||||
const { InkDropSVG } = await import('./animations');
|
||||
render(<InkDropSVG className="ink-drop-class" />);
|
||||
const element = screen.getByTestId('motion-svg');
|
||||
expect(element).toHaveClass('ink-drop-class');
|
||||
});
|
||||
});
|
||||
|
||||
describe('InkSplash', () => {
|
||||
it('should render SVG correctly', async () => {
|
||||
const { InkSplash } = await import('./animations');
|
||||
render(<InkSplash />);
|
||||
expect(screen.getByTestId('motion-svg')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('motion-path')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should apply custom color', async () => {
|
||||
const { InkSplash } = await import('./animations');
|
||||
render(<InkSplash color="#ff0000" />);
|
||||
const path = screen.getByTestId('motion-path');
|
||||
expect(path).toHaveAttribute('fill', '#ff0000');
|
||||
});
|
||||
|
||||
it('should apply custom size', async () => {
|
||||
const { InkSplash } = await import('./animations');
|
||||
render(<InkSplash size={200} />);
|
||||
const svg = screen.getByTestId('motion-svg');
|
||||
expect(svg).toHaveAttribute('width', '200');
|
||||
expect(svg).toHaveAttribute('height', '200');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user