import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import React, { useRef, useEffect } from 'react';
import '@testing-library/jest-dom';
import UI from './ui';
describe('UI Component', () => {
// ============================================
// Rendering Tests
// ============================================
describe('Rendering', () => {
it('renders a div by default', () => {
render(Default Content);
const element = screen.getByTestId('ui-element');
expect(element.tagName).toBe('DIV');
expect(element).toHaveTextContent('Default Content');
});
it('renders as button when as="button"', () => {
render(
Button Text
);
const button = screen.getByTestId('ui-button');
expect(button.tagName).toBe('BUTTON');
expect(button).toHaveTextContent('Button Text');
});
it('renders as span when as="span"', () => {
render(
Span Text
);
const span = screen.getByTestId('ui-span');
expect(span.tagName).toBe('SPAN');
});
it('renders as anchor when as="a"', () => {
render(
Link Text
);
const anchor = screen.getByTestId('ui-anchor');
expect(anchor.tagName).toBe('A');
expect(anchor).toHaveAttribute('href', '/test');
});
it('renders as section when as="section"', () => {
render(
Section Content
);
const section = screen.getByTestId('ui-section');
expect(section.tagName).toBe('SECTION');
});
it('renders children correctly', () => {
render(
Child 1
Child 2
);
const parent = screen.getByTestId('ui-parent');
expect(parent.children).toHaveLength(2);
expect(screen.getByText('Child 1')).toBeInTheDocument();
expect(screen.getByText('Child 2')).toBeInTheDocument();
});
it('renders with empty children', () => {
render();
const element = screen.getByTestId('ui-empty');
expect(element).toBeInTheDocument();
expect(element).toBeEmptyDOMElement();
});
it('renders with null children', () => {
render({null});
const element = screen.getByTestId('ui-null');
expect(element).toBeInTheDocument();
expect(element).toBeEmptyDOMElement();
// Element is verified to be empty
void element;
});
it('handles complex nested children', () => {
render(
Nested
Content
);
expect(screen.getByText('Nested')).toBeInTheDocument();
expect(screen.getByText('Content')).toBeInTheDocument();
});
});
// ============================================
// Style Tests
// ============================================
describe('Styles', () => {
it('applies inline styles via styles prop', () => {
render(
Styled Content
);
const element = screen.getByTestId('ui-styled');
expect(element).toHaveStyle('padding: 1rem');
// Note: browsers convert colors to rgb format
expect(element.style.backgroundColor).toBe('red');
expect(element.style.color).toBe('white');
});
it('applies className via classes prop', () => {
render(
Classed Content
);
const element = screen.getByTestId('ui-classes');
expect(element).toHaveClass('custom-class');
expect(element).toHaveClass('another-class');
});
it('merges defaultStyles and styles correctly', () => {
render(
Merged Styles
);
const element = screen.getByTestId('ui-merged');
expect(element).toHaveStyle('padding: 1rem');
expect(element.style.color).toBe('red'); // Overridden by styles
expect(element.style.fontSize).toBe('16px'); // From defaultStyles
expect(element.style.fontWeight).toBe('bold'); // From styles
});
it('styles override defaultStyles', () => {
render(
Override Test
);
const element = screen.getByTestId('ui-override');
expect(element.style.color).toBe('red'); // Overridden
expect(element).toHaveStyle('padding: 10px'); // Preserved
});
it('handles undefined styles', () => {
render(
No Styles
);
const element = screen.getByTestId('ui-no-styles');
expect(element).toBeInTheDocument();
});
it('handles empty styles object', () => {
render(
Empty Styles
);
const element = screen.getByTestId('ui-empty-styles');
expect(element).toBeInTheDocument();
});
it('handles undefined defaultStyles', () => {
render(
No Defaults
);
const element = screen.getByTestId('ui-no-default');
expect(element.style.color).toBe('red');
});
});
// ============================================
// Prop Forwarding Tests
// ============================================
describe('Prop Forwarding', () => {
it('forwards onClick to button element', () => {
let clicked = false;
const handleClick = () => {
clicked = true;
};
render(
Click Me
);
const button = screen.getByTestId('ui-clickable');
button.click();
expect(clicked).toBe(true);
});
it('forwards href to anchor element', () => {
render(
Link
);
const link = screen.getByTestId('ui-link');
expect(link).toHaveAttribute('href', '/test-link');
});
it('forwards disabled to button element', () => {
render(
Disabled Button
);
const button = screen.getByTestId('ui-disabled');
expect(button).toBeDisabled();
});
it('forwards target to anchor element', () => {
render(
External Link
);
const link = screen.getByTestId('ui-target');
expect(link).toHaveAttribute('target', '_blank');
expect(link).toHaveAttribute('rel', 'noopener');
});
it('forwards data-* attributes', () => {
render(
Data Attributes
);
const element = screen.getByTestId('ui-data');
expect(element).toHaveAttribute('data-custom', 'custom-value');
expect(element).toHaveAttribute('data-id', '123');
});
it('forwards aria-* attributes', () => {
render(
ARIA Attributes
);
const element = screen.getByTestId('ui-aria');
expect(element).toHaveAttribute('aria-label', 'Custom Label');
expect(element).toHaveAttribute('aria-hidden', 'true');
});
it('applies id prop', () => {
render(
ID Test
);
const element = screen.getByTestId('ui-id');
expect(element).toHaveAttribute('id', 'custom-id');
});
});
// ============================================
// Ref Forwarding Tests
// ============================================
describe('Ref Forwarding', () => {
it('forwards ref to div element', () => {
const RefTest = () => {
const divRef = useRef(null);
useEffect(() => {
if (divRef.current) {
divRef.current.setAttribute('data-ref-test', 'true');
}
}, []);
return (
Div with Ref
);
};
render();
const element = screen.getByTestId('ui-div-ref');
expect(element).toHaveAttribute('data-ref-test', 'true');
});
it('forwards ref to button element', () => {
const RefTest = () => {
const buttonRef = useRef(null);
useEffect(() => {
if (buttonRef.current) {
buttonRef.current.setAttribute('data-ref-test', 'true');
}
}, []);
return (
Button with Ref
);
};
render();
const button = screen.getByTestId('ui-button-ref');
expect(button).toHaveAttribute('data-ref-test', 'true');
});
it('forwards ref to anchor element', () => {
const RefTest = () => {
const anchorRef = useRef(null);
useEffect(() => {
if (anchorRef.current) {
anchorRef.current.setAttribute('data-ref-test', 'true');
}
}, []);
return (
Anchor with Ref
);
};
render();
const anchor = screen.getByTestId('ui-anchor-ref');
expect(anchor).toHaveAttribute('data-ref-test', 'true');
});
it('ref provides access to DOM node', () => {
const RefTest = () => {
const elementRef = useRef(null);
useEffect(() => {
if (elementRef.current) {
expect(elementRef.current.tagName).toBe('DIV');
expect(elementRef.current.textContent).toBe('DOM Access');
}
}, []);
return (
DOM Access
);
};
render();
});
it('ref type matches element type', () => {
const RefTest = () => {
const buttonRef = useRef(null);
useEffect(() => {
if (buttonRef.current) {
// HTMLButtonElement-specific property
expect(buttonRef.current.type).toBeDefined();
expect(buttonRef.current.disabled).toBe(false);
}
}, []);
return (
Typed Ref
);
};
render();
});
});
// ============================================
// Edge Cases
// ============================================
describe('Edge Cases', () => {
it('handles undefined as prop (defaults to div)', () => {
render(
Undefined As
);
const element = screen.getByTestId('ui-undefined-as');
expect(element.tagName).toBe('DIV');
});
it('handles undefined classes prop', () => {
render(
No Classes
);
const element = screen.getByTestId('ui-undefined-classes');
expect(element).toBeInTheDocument();
expect(element.className).toBe('');
});
it('handles empty string classes', () => {
render(
Empty Classes
);
const element = screen.getByTestId('ui-empty-classes');
expect(element.className).toBe('');
});
it('handles multiple whitespace-separated classes', () => {
render(
Multiple Classes
);
const element = screen.getByTestId('ui-multiple-classes');
expect(element).toHaveClass('class1', 'class2', 'class3');
});
it('renders with boolean children (false)', () => {
render({false});
const element = screen.getByTestId('ui-boolean');
expect(element).toBeEmptyDOMElement();
});
it('renders with number children', () => {
render({42});
const element = screen.getByTestId('ui-number');
expect(element).toHaveTextContent('42');
});
it('renders with mixed children types', () => {
render(
Text
{42}
Element
{null}
{false}
);
const element = screen.getByTestId('ui-mixed');
expect(element).toHaveTextContent('Text42Element');
});
});
// ============================================
// Integration Tests
// ============================================
describe('Integration', () => {
it('works as a building block for custom components', () => {
const CustomButton = ({
variant,
children,
...props
}: {
variant: 'primary' | 'secondary';
children: React.ReactNode;
}) => {
const styles = {
primary: { backgroundColor: 'blue', color: 'white' },
secondary: { backgroundColor: 'gray', color: 'black' },
};
return (
{children}
);
};
render(Custom);
const button = screen.getByTestId('custom-button');
expect(button.tagName).toBe('BUTTON');
expect(button).toHaveStyle('padding: 0.5rem 1rem');
expect(button.style.backgroundColor).toBe('blue');
expect(button.style.color).toBe('white');
});
it('supports style overrides in custom components', () => {
const CustomBox = ({
children,
...props
}: {
children: React.ReactNode;
styles?: React.CSSProperties;
'data-testid'?: string;
}) => {
return (
{children}
);
};
render(
Box
);
const box = screen.getByTestId('custom-box');
expect(box.style.backgroundColor).toBe('red'); // Override
expect(box).toHaveStyle('padding: 1rem'); // Preserved
});
});
});