- Add comprehensive test suite for api.ts service layer - Create component tests for BackToTop, ColorCell, MaterialBadge - Add tests for data modules: bambuLabColors and bambuLabColorsComplete - Include specialized tests for UI features, CRUD operations, and data consistency - Achieve 100% coverage for core components and data utilities - All 91 tests passing with robust mocking strategies
148 lines
3.8 KiB
TypeScript
148 lines
3.8 KiB
TypeScript
import React from 'react';
|
|
import { render, fireEvent, act } from '@testing-library/react';
|
|
import { BackToTop } from '@/src/components/BackToTop';
|
|
|
|
// Mock window properties
|
|
global.scrollTo = jest.fn();
|
|
Object.defineProperty(window, 'pageYOffset', {
|
|
writable: true,
|
|
configurable: true,
|
|
value: 0,
|
|
});
|
|
|
|
describe('BackToTop', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
window.pageYOffset = 0;
|
|
});
|
|
|
|
it('does not render button when at top of page', () => {
|
|
const { container } = render(<BackToTop />);
|
|
const button = container.querySelector('button');
|
|
expect(button).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('renders button when scrolled down', () => {
|
|
const { container } = render(<BackToTop />);
|
|
|
|
// Simulate scroll down
|
|
act(() => {
|
|
window.pageYOffset = 400;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
const button = container.querySelector('button');
|
|
expect(button).toBeInTheDocument();
|
|
});
|
|
|
|
it('hides button when scrolled back up', () => {
|
|
const { container } = render(<BackToTop />);
|
|
|
|
// Scroll down first
|
|
act(() => {
|
|
window.pageYOffset = 400;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
expect(container.querySelector('button')).toBeInTheDocument();
|
|
|
|
// Scroll back up
|
|
act(() => {
|
|
window.pageYOffset = 100;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
expect(container.querySelector('button')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('scrolls to top when clicked', () => {
|
|
const { container } = render(<BackToTop />);
|
|
|
|
// Make button visible
|
|
act(() => {
|
|
window.pageYOffset = 400;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
const button = container.querySelector('button');
|
|
fireEvent.click(button!);
|
|
|
|
expect(global.scrollTo).toHaveBeenCalledWith({
|
|
top: 0,
|
|
behavior: 'smooth'
|
|
});
|
|
});
|
|
|
|
it('has correct styling when visible', () => {
|
|
const { container } = render(<BackToTop />);
|
|
|
|
// Make button visible
|
|
act(() => {
|
|
window.pageYOffset = 400;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
const button = container.querySelector('button');
|
|
|
|
expect(button).toHaveClass('fixed');
|
|
expect(button).toHaveClass('bottom-8');
|
|
expect(button).toHaveClass('right-8');
|
|
expect(button).toHaveClass('bg-blue-600');
|
|
expect(button).toHaveClass('text-white');
|
|
expect(button).toHaveClass('rounded-full');
|
|
expect(button).toHaveClass('shadow-lg');
|
|
});
|
|
|
|
it('has hover effect', () => {
|
|
const { container } = render(<BackToTop />);
|
|
|
|
// Make button visible
|
|
act(() => {
|
|
window.pageYOffset = 400;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
const button = container.querySelector('button');
|
|
expect(button).toHaveClass('hover:bg-blue-700');
|
|
expect(button).toHaveClass('hover:scale-110');
|
|
});
|
|
|
|
it('contains arrow icon', () => {
|
|
const { container } = render(<BackToTop />);
|
|
|
|
// Make button visible
|
|
act(() => {
|
|
window.pageYOffset = 400;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
const svg = container.querySelector('svg');
|
|
|
|
expect(svg).toBeInTheDocument();
|
|
expect(svg).toHaveClass('w-6');
|
|
expect(svg).toHaveClass('h-6');
|
|
});
|
|
|
|
it('has aria-label for accessibility', () => {
|
|
const { container } = render(<BackToTop />);
|
|
|
|
// Make button visible
|
|
act(() => {
|
|
window.pageYOffset = 400;
|
|
fireEvent.scroll(window);
|
|
});
|
|
|
|
const button = container.querySelector('button');
|
|
expect(button).toHaveAttribute('aria-label', 'Back to top');
|
|
});
|
|
|
|
it('cleans up scroll listener on unmount', () => {
|
|
const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener');
|
|
const { unmount } = render(<BackToTop />);
|
|
|
|
unmount();
|
|
|
|
expect(removeEventListenerSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
|
|
removeEventListenerSpy.mockRestore();
|
|
});
|
|
}); |