@sc4rfurryx/proteusjs
Version:
The Modern Web Development Framework for Accessible, Responsive, and High-Performance Applications. Intelligent container queries, fluid typography, WCAG compliance, and performance optimization.
282 lines (218 loc) • 9.82 kB
text/typescript
/**
* SmartContainers Test Suite
* Comprehensive tests for container detection and management
*/
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { SmartContainers, ContainerInfo } from '../SmartContainers';
// Mock ResizeObserver
global.ResizeObserver = vi.fn().mockImplementation((callback) => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}));
// Mock MutationObserver
global.MutationObserver = vi.fn().mockImplementation((callback) => ({
observe: vi.fn(),
disconnect: vi.fn(),
}));
describe('SmartContainers', () => {
let smartContainers: SmartContainers;
let testContainer: HTMLElement;
beforeEach(() => {
// Clean up DOM
document.body.innerHTML = '';
// Create test container
testContainer = document.createElement('div');
testContainer.id = 'test-container';
testContainer.style.width = '400px';
testContainer.style.height = '300px';
testContainer.style.display = 'block';
document.body.appendChild(testContainer);
smartContainers = new SmartContainers();
});
afterEach(() => {
smartContainers.destroy();
document.body.innerHTML = '';
});
describe('Container Detection', () => {
it('should detect basic block containers', async () => {
const containers = await smartContainers.detectContainers();
expect(containers.length).toBeGreaterThan(0);
const testContainerInfo = containers.find(c => c.element === testContainer);
expect(testContainerInfo).toBeDefined();
expect(testContainerInfo?.type).toBe('block');
});
it('should detect grid containers', async () => {
testContainer.style.display = 'grid';
const containers = await smartContainers.detectContainers();
const gridContainer = containers.find(c => c.element === testContainer);
expect(gridContainer?.type).toBe('grid');
expect(gridContainer?.confidence).toBeGreaterThan(0.4);
});
it('should detect flex containers', async () => {
testContainer.style.display = 'flex';
const containers = await smartContainers.detectContainers();
const flexContainer = containers.find(c => c.element === testContainer);
expect(flexContainer?.type).toBe('flex');
expect(flexContainer?.confidence).toBeGreaterThan(0.3);
});
it('should exclude small elements', async () => {
const smallElement = document.createElement('div');
smallElement.style.width = '10px';
smallElement.style.height = '10px';
document.body.appendChild(smallElement);
const containers = await smartContainers.detectContainers();
const smallContainer = containers.find(c => c.element === smallElement);
expect(smallContainer).toBeUndefined();
});
it('should respect confidence threshold', async () => {
const containers = await smartContainers.detectContainers({ minConfidence: 0.8 });
// Should have fewer containers with high confidence threshold
expect(containers.length).toBeLessThanOrEqual(
(await smartContainers.detectContainers({ minConfidence: 0.1 })).length
);
});
});
describe('Container Units', () => {
beforeEach(() => {
// Mock getBoundingClientRect
vi.spyOn(testContainer, 'getBoundingClientRect').mockReturnValue({
width: 400,
height: 300,
top: 0,
left: 0,
bottom: 300,
right: 400,
x: 0,
y: 0,
toJSON: () => ({})
} as DOMRect);
});
it('should calculate container width units (cw)', () => {
const unit = smartContainers.calculateContainerUnit(testContainer, 'cw');
expect(unit).toBe(4); // 400px / 100 = 4px per cw
});
it('should calculate container height units (ch)', () => {
const unit = smartContainers.calculateContainerUnit(testContainer, 'ch');
expect(unit).toBe(3); // 300px / 100 = 3px per ch
});
it('should calculate container minimum units (cmin)', () => {
const unit = smartContainers.calculateContainerUnit(testContainer, 'cmin');
expect(unit).toBe(3); // min(400, 300) / 100 = 3px per cmin
});
it('should calculate container maximum units (cmax)', () => {
const unit = smartContainers.calculateContainerUnit(testContainer, 'cmax');
expect(unit).toBe(4); // max(400, 300) / 100 = 4px per cmax
});
it('should handle unknown units gracefully', () => {
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const unit = smartContainers.calculateContainerUnit(testContainer, 'unknown');
expect(unit).toBe(0);
expect(consoleSpy).toHaveBeenCalledWith(
expect.stringContaining('Unknown container unit "unknown"')
);
consoleSpy.mockRestore();
});
});
describe('Container Management', () => {
it('should track container information', async () => {
await smartContainers.detectContainers();
const containerInfo = smartContainers.getContainerInfo(testContainer);
expect(containerInfo).toBeDefined();
expect(containerInfo?.element).toBe(testContainer);
});
it('should update container information', async () => {
await smartContainers.detectContainers();
// Change container style
testContainer.style.display = 'grid';
const updatedInfo = smartContainers.updateContainer(testContainer);
expect(updatedInfo?.type).toBe('grid');
});
it('should start and stop monitoring', () => {
smartContainers.startMonitoring();
expect(smartContainers['isActive']).toBe(true);
smartContainers.stopMonitoring();
expect(smartContainers['isActive']).toBe(false);
});
});
describe('Responsive Content Detection', () => {
it('should detect responsive images', async () => {
const img = document.createElement('img');
img.srcset = 'image-320w.jpg 320w, image-640w.jpg 640w';
testContainer.appendChild(img);
const containers = await smartContainers.detectContainers();
const containerInfo = containers.find(c => c.element === testContainer);
expect(containerInfo?.hasResponsiveContent).toBe(true);
});
it('should detect responsive videos', async () => {
const iframe = document.createElement('iframe');
iframe.src = 'https://www.youtube.com/embed/test';
testContainer.appendChild(iframe);
const containers = await smartContainers.detectContainers();
const containerInfo = containers.find(c => c.element === testContainer);
expect(containerInfo?.hasResponsiveContent).toBe(true);
});
it('should detect grid/flex children', async () => {
const child = document.createElement('div');
child.style.display = 'grid';
testContainer.appendChild(child);
const containers = await smartContainers.detectContainers();
const containerInfo = containers.find(c => c.element === testContainer);
expect(containerInfo?.hasResponsiveContent).toBe(true);
});
});
describe('Metrics and Analysis', () => {
it('should provide performance metrics', async () => {
await smartContainers.detectContainers();
const metrics = smartContainers.getMetrics();
expect(metrics.totalContainers).toBeGreaterThan(0);
expect(metrics.averageConfidence).toBeGreaterThan(0);
expect(metrics.typeDistribution).toBeDefined();
});
it('should filter containers by type', async () => {
// Create different container types
const gridContainer = document.createElement('div');
gridContainer.style.display = 'grid';
gridContainer.style.width = '200px';
gridContainer.style.height = '200px';
document.body.appendChild(gridContainer);
await smartContainers.detectContainers();
const gridContainers = smartContainers.getContainersByType('grid');
const blockContainers = smartContainers.getContainersByType('block');
expect(gridContainers.length).toBeGreaterThan(0);
expect(blockContainers.length).toBeGreaterThan(0);
expect(gridContainers.every(c => c.type === 'grid')).toBe(true);
expect(blockContainers.every(c => c.type === 'block')).toBe(true);
});
it('should filter high-confidence containers', async () => {
await smartContainers.detectContainers();
const highConfidenceContainers = smartContainers.getHighConfidenceContainers(0.5);
expect(highConfidenceContainers.every(c => c.confidence >= 0.5)).toBe(true);
});
it('should refresh containers', async () => {
const initialContainers = await smartContainers.detectContainers();
// Add new container
const newContainer = document.createElement('div');
newContainer.style.width = '300px';
newContainer.style.height = '200px';
newContainer.style.display = 'flex';
document.body.appendChild(newContainer);
const refreshedContainers = await smartContainers.refreshContainers();
expect(refreshedContainers.length).toBeGreaterThan(initialContainers.length);
});
});
describe('Error Handling', () => {
it('should handle missing elements gracefully', () => {
const nonExistentElement = document.createElement('div');
const containerInfo = smartContainers.getContainerInfo(nonExistentElement);
expect(containerInfo).toBeNull();
const updatedInfo = smartContainers.updateContainer(nonExistentElement);
expect(updatedInfo).toBeNull();
});
it('should handle cleanup properly', () => {
expect(() => {
smartContainers.destroy();
}).not.toThrow();
});
});
});