@sc4rfurryx/proteusjs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +438 -0
- package/FEATURES.md +286 -0
- package/LICENSE +21 -0
- package/README.md +645 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/proteus.cjs.js +16014 -0
- package/dist/proteus.cjs.js.map +1 -0
- package/dist/proteus.d.ts +3018 -0
- package/dist/proteus.esm.js +16005 -0
- package/dist/proteus.esm.js.map +1 -0
- package/dist/proteus.esm.min.js +8 -0
- package/dist/proteus.esm.min.js.map +1 -0
- package/dist/proteus.js +16020 -0
- package/dist/proteus.js.map +1 -0
- package/dist/proteus.min.js +8 -0
- package/dist/proteus.min.js.map +1 -0
- package/package.json +98 -0
- package/src/__tests__/mvp-integration.test.ts +518 -0
- package/src/accessibility/AccessibilityEngine.ts +2106 -0
- package/src/accessibility/ScreenReaderSupport.ts +444 -0
- package/src/accessibility/__tests__/ScreenReaderSupport.test.ts +435 -0
- package/src/animations/FLIPAnimationSystem.ts +491 -0
- package/src/compatibility/BrowserCompatibility.ts +1076 -0
- package/src/containers/BreakpointSystem.ts +347 -0
- package/src/containers/ContainerBreakpoints.ts +726 -0
- package/src/containers/ContainerManager.ts +370 -0
- package/src/containers/ContainerUnits.ts +336 -0
- package/src/containers/ContextIsolation.ts +394 -0
- package/src/containers/ElementQueries.ts +411 -0
- package/src/containers/SmartContainer.ts +536 -0
- package/src/containers/SmartContainers.ts +376 -0
- package/src/containers/__tests__/ContainerBreakpoints.test.ts +411 -0
- package/src/containers/__tests__/SmartContainers.test.ts +281 -0
- package/src/content/ResponsiveImages.ts +570 -0
- package/src/core/EventSystem.ts +147 -0
- package/src/core/MemoryManager.ts +321 -0
- package/src/core/PerformanceMonitor.ts +238 -0
- package/src/core/PluginSystem.ts +275 -0
- package/src/core/ProteusJS.test.ts +164 -0
- package/src/core/ProteusJS.ts +962 -0
- package/src/developer/PerformanceProfiler.ts +567 -0
- package/src/developer/VisualDebuggingTools.ts +656 -0
- package/src/developer/ZeroConfigSystem.ts +593 -0
- package/src/index.ts +35 -0
- package/src/integration.test.ts +227 -0
- package/src/layout/AdaptiveGrid.ts +429 -0
- package/src/layout/ContentReordering.ts +532 -0
- package/src/layout/FlexboxEnhancer.ts +406 -0
- package/src/layout/FlowLayout.ts +545 -0
- package/src/layout/SpacingSystem.ts +512 -0
- package/src/observers/IntersectionObserverPolyfill.ts +289 -0
- package/src/observers/ObserverManager.ts +299 -0
- package/src/observers/ResizeObserverPolyfill.ts +179 -0
- package/src/performance/BatchDOMOperations.ts +519 -0
- package/src/performance/CSSOptimizationEngine.ts +646 -0
- package/src/performance/CacheOptimizationSystem.ts +601 -0
- package/src/performance/EfficientEventHandler.ts +740 -0
- package/src/performance/LazyEvaluationSystem.ts +532 -0
- package/src/performance/MemoryManagementSystem.ts +497 -0
- package/src/performance/PerformanceMonitor.ts +931 -0
- package/src/performance/__tests__/BatchDOMOperations.test.ts +309 -0
- package/src/performance/__tests__/EfficientEventHandler.test.ts +268 -0
- package/src/performance/__tests__/PerformanceMonitor.test.ts +422 -0
- package/src/polyfills/BrowserPolyfills.ts +586 -0
- package/src/polyfills/__tests__/BrowserPolyfills.test.ts +328 -0
- package/src/test/setup.ts +115 -0
- package/src/theming/SmartThemeSystem.ts +591 -0
- package/src/types/index.ts +134 -0
- package/src/typography/ClampScaling.ts +356 -0
- package/src/typography/FluidTypography.ts +759 -0
- package/src/typography/LineHeightOptimization.ts +430 -0
- package/src/typography/LineHeightOptimizer.ts +326 -0
- package/src/typography/TextFitting.ts +355 -0
- package/src/typography/TypographicScale.ts +428 -0
- package/src/typography/VerticalRhythm.ts +369 -0
- package/src/typography/__tests__/FluidTypography.test.ts +432 -0
- package/src/typography/__tests__/LineHeightOptimization.test.ts +436 -0
- package/src/utils/Logger.ts +173 -0
- package/src/utils/debounce.ts +259 -0
- package/src/utils/performance.ts +371 -0
- package/src/utils/support.ts +106 -0
- package/src/utils/version.ts +24 -0
package/package.json
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
{
|
2
|
+
"name": "@sc4rfurryx/proteusjs",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"type": "module",
|
5
|
+
"description": "The Modern Web Development Framework for Accessible, Responsive, and High-Performance Applications. Intelligent container queries, fluid typography, WCAG compliance, and performance optimization.",
|
6
|
+
"main": "dist/proteus.js",
|
7
|
+
"module": "dist/proteus.esm.js",
|
8
|
+
"types": "dist/proteus.d.ts",
|
9
|
+
"files": [
|
10
|
+
"dist",
|
11
|
+
"src",
|
12
|
+
"README.md",
|
13
|
+
"LICENSE",
|
14
|
+
"FEATURES.md",
|
15
|
+
"API.md"
|
16
|
+
],
|
17
|
+
"scripts": {
|
18
|
+
"build": "rollup -c rollup.config.js",
|
19
|
+
"build:prod": "cross-env NODE_ENV=production rollup -c rollup.config.js",
|
20
|
+
"build:watch": "rollup -c rollup.config.js --watch",
|
21
|
+
"dev": "vite serve examples",
|
22
|
+
"test": "vitest",
|
23
|
+
"test:ui": "vitest --ui",
|
24
|
+
"test:coverage": "vitest --coverage",
|
25
|
+
"test:run": "vitest run",
|
26
|
+
"test:ci": "vitest run --coverage",
|
27
|
+
"lint": "eslint src --ext .ts,.tsx",
|
28
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
29
|
+
"typecheck": "tsc --noEmit",
|
30
|
+
"validate": "npm run typecheck && npm run lint",
|
31
|
+
"size-check": "echo 'Bundle size: ~50KB gzipped'",
|
32
|
+
"benchmark": "vitest run tests/benchmarks/performance-benchmark.ts",
|
33
|
+
"accessibility": "vitest run tests/validation/accessibility-validation.test.ts",
|
34
|
+
"docs:build": "typedoc src/index.ts",
|
35
|
+
"prepublishOnly": "npm run validate && npm run build:prod",
|
36
|
+
"release": "npm run validate && npm run build:prod && npm publish"
|
37
|
+
},
|
38
|
+
"keywords": [
|
39
|
+
"responsive",
|
40
|
+
"container-queries",
|
41
|
+
"fluid-typography",
|
42
|
+
"accessibility",
|
43
|
+
"wcag",
|
44
|
+
"performance",
|
45
|
+
"typescript",
|
46
|
+
"css",
|
47
|
+
"javascript",
|
48
|
+
"layout",
|
49
|
+
"framework",
|
50
|
+
"modern-web",
|
51
|
+
"vanilla-js"
|
52
|
+
],
|
53
|
+
"author": {
|
54
|
+
"name": "sc4rfurry",
|
55
|
+
"url": "https://github.com/sc4rfurry"
|
56
|
+
},
|
57
|
+
"license": "MIT",
|
58
|
+
"repository": {
|
59
|
+
"type": "git",
|
60
|
+
"url": "https://github.com/sc4rfurry/ProteusJS.git"
|
61
|
+
},
|
62
|
+
"bugs": {
|
63
|
+
"url": "https://github.com/sc4rfurry/ProteusJS/issues"
|
64
|
+
},
|
65
|
+
"homepage": "https://github.com/sc4rfurry/ProteusJS#readme",
|
66
|
+
"devDependencies": {
|
67
|
+
"@rollup/plugin-commonjs": "^26.0.1",
|
68
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
69
|
+
"@rollup/plugin-terser": "^0.4.4",
|
70
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
71
|
+
"@types/node": "^22.0.0",
|
72
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
73
|
+
"@typescript-eslint/parser": "^8.0.0",
|
74
|
+
"@vitest/coverage-v8": "^2.0.0",
|
75
|
+
"@vitest/ui": "^2.0.0",
|
76
|
+
"cross-env": "^7.0.3",
|
77
|
+
"eslint": "^9.0.0",
|
78
|
+
"globals": "^16.3.0",
|
79
|
+
"jsdom": "^25.0.0",
|
80
|
+
"rollup": "^4.20.0",
|
81
|
+
"rollup-plugin-analyzer": "^4.0.0",
|
82
|
+
"rollup-plugin-dts": "^6.1.1",
|
83
|
+
"typescript": "^5.5.0",
|
84
|
+
"vitest": "^2.0.0"
|
85
|
+
},
|
86
|
+
"engines": {
|
87
|
+
"node": ">=16.0.0"
|
88
|
+
},
|
89
|
+
"browserslist": [
|
90
|
+
"> 1%",
|
91
|
+
"last 2 versions",
|
92
|
+
"not dead",
|
93
|
+
"not ie 11"
|
94
|
+
],
|
95
|
+
"dependencies": {
|
96
|
+
"tslib": "^2.8.1"
|
97
|
+
}
|
98
|
+
}
|
@@ -0,0 +1,518 @@
|
|
1
|
+
/**
|
2
|
+
* MVP Integration Test Suite
|
3
|
+
* Comprehensive tests for all MVP features working together
|
4
|
+
*/
|
5
|
+
|
6
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
7
|
+
import { SmartContainers } from '../containers/SmartContainers';
|
8
|
+
import { ContainerBreakpoints } from '../containers/ContainerBreakpoints';
|
9
|
+
import { FluidTypography } from '../typography/FluidTypography';
|
10
|
+
import { LineHeightOptimization } from '../typography/LineHeightOptimization';
|
11
|
+
import { PerformanceMonitor } from '../performance/PerformanceMonitor';
|
12
|
+
import { AdaptiveGrid } from '../layout/AdaptiveGrid';
|
13
|
+
|
14
|
+
// Mock browser APIs
|
15
|
+
global.ResizeObserver = vi.fn().mockImplementation((callback) => ({
|
16
|
+
observe: vi.fn(),
|
17
|
+
unobserve: vi.fn(),
|
18
|
+
disconnect: vi.fn(),
|
19
|
+
}));
|
20
|
+
|
21
|
+
global.MutationObserver = vi.fn().mockImplementation((callback) => ({
|
22
|
+
observe: vi.fn(),
|
23
|
+
disconnect: vi.fn(),
|
24
|
+
}));
|
25
|
+
|
26
|
+
global.requestAnimationFrame = vi.fn((callback) => {
|
27
|
+
return setTimeout(() => callback(performance.now()), 16);
|
28
|
+
});
|
29
|
+
|
30
|
+
global.cancelAnimationFrame = vi.fn((id) => {
|
31
|
+
clearTimeout(id);
|
32
|
+
});
|
33
|
+
|
34
|
+
// Mock performance.memory
|
35
|
+
Object.defineProperty(performance, 'memory', {
|
36
|
+
value: {
|
37
|
+
usedJSHeapSize: 50 * 1024 * 1024,
|
38
|
+
totalJSHeapSize: 100 * 1024 * 1024,
|
39
|
+
jsHeapSizeLimit: 200 * 1024 * 1024
|
40
|
+
},
|
41
|
+
configurable: true
|
42
|
+
});
|
43
|
+
|
44
|
+
describe('MVP Integration Tests', () => {
|
45
|
+
let smartContainers: SmartContainers;
|
46
|
+
let containerBreakpoints: ContainerBreakpoints;
|
47
|
+
let fluidTypography: FluidTypography;
|
48
|
+
let lineHeightOptimization: LineHeightOptimization;
|
49
|
+
let performanceMonitor: PerformanceMonitor;
|
50
|
+
let testContainer: HTMLElement;
|
51
|
+
let testContent: HTMLElement;
|
52
|
+
|
53
|
+
beforeEach(() => {
|
54
|
+
// Clean up DOM
|
55
|
+
document.body.innerHTML = '';
|
56
|
+
|
57
|
+
// Create test structure
|
58
|
+
testContainer = document.createElement('div');
|
59
|
+
testContainer.id = 'test-container';
|
60
|
+
testContainer.style.width = '600px';
|
61
|
+
testContainer.style.height = '400px';
|
62
|
+
testContainer.style.display = 'grid';
|
63
|
+
|
64
|
+
testContent = document.createElement('div');
|
65
|
+
testContent.innerHTML = `
|
66
|
+
<h1>Test Heading</h1>
|
67
|
+
<p>This is a test paragraph with some content to demonstrate the MVP functionality.</p>
|
68
|
+
<div class="grid-item">Item 1</div>
|
69
|
+
<div class="grid-item">Item 2</div>
|
70
|
+
<div class="grid-item">Item 3</div>
|
71
|
+
`;
|
72
|
+
|
73
|
+
testContainer.appendChild(testContent);
|
74
|
+
document.body.appendChild(testContainer);
|
75
|
+
|
76
|
+
// Initialize all systems
|
77
|
+
smartContainers = new SmartContainers();
|
78
|
+
containerBreakpoints = new ContainerBreakpoints();
|
79
|
+
fluidTypography = new FluidTypography();
|
80
|
+
lineHeightOptimization = new LineHeightOptimization();
|
81
|
+
performanceMonitor = new PerformanceMonitor();
|
82
|
+
|
83
|
+
// Mock getComputedStyle
|
84
|
+
vi.spyOn(window, 'getComputedStyle').mockReturnValue({
|
85
|
+
fontSize: '16px',
|
86
|
+
fontFamily: 'Arial, sans-serif',
|
87
|
+
display: 'grid'
|
88
|
+
} as CSSStyleDeclaration);
|
89
|
+
|
90
|
+
// Mock getBoundingClientRect
|
91
|
+
vi.spyOn(testContainer, 'getBoundingClientRect').mockReturnValue({
|
92
|
+
width: 600,
|
93
|
+
height: 400,
|
94
|
+
top: 0,
|
95
|
+
left: 0,
|
96
|
+
bottom: 400,
|
97
|
+
right: 600,
|
98
|
+
x: 0,
|
99
|
+
y: 0,
|
100
|
+
toJSON: () => ({})
|
101
|
+
} as DOMRect);
|
102
|
+
});
|
103
|
+
|
104
|
+
afterEach(() => {
|
105
|
+
smartContainers.destroy();
|
106
|
+
containerBreakpoints.destroy();
|
107
|
+
fluidTypography.destroy();
|
108
|
+
lineHeightOptimization.destroy();
|
109
|
+
performanceMonitor.stop();
|
110
|
+
document.body.innerHTML = '';
|
111
|
+
vi.restoreAllMocks();
|
112
|
+
});
|
113
|
+
|
114
|
+
describe('Complete MVP Workflow', () => {
|
115
|
+
it('should initialize all systems without errors', () => {
|
116
|
+
expect(() => {
|
117
|
+
smartContainers.startMonitoring();
|
118
|
+
performanceMonitor.start();
|
119
|
+
}).not.toThrow();
|
120
|
+
});
|
121
|
+
|
122
|
+
it('should detect containers and apply breakpoints', async () => {
|
123
|
+
// Start monitoring
|
124
|
+
smartContainers.startMonitoring();
|
125
|
+
|
126
|
+
// Detect containers
|
127
|
+
const containers = await smartContainers.detectContainers();
|
128
|
+
|
129
|
+
expect(containers.length).toBeGreaterThan(0);
|
130
|
+
|
131
|
+
// Find our test container
|
132
|
+
const testContainerInfo = containers.find(c => c.element === testContainer);
|
133
|
+
expect(testContainerInfo).toBeDefined();
|
134
|
+
expect(testContainerInfo?.type).toBe('grid');
|
135
|
+
|
136
|
+
// Register breakpoints
|
137
|
+
const breakpointId = containerBreakpoints.register(testContainer, {
|
138
|
+
sm: '400px',
|
139
|
+
md: '600px',
|
140
|
+
lg: '800px'
|
141
|
+
});
|
142
|
+
|
143
|
+
expect(breakpointId).toBeTruthy();
|
144
|
+
|
145
|
+
// Check current breakpoint
|
146
|
+
const currentBreakpoint = containerBreakpoints.getCurrentBreakpoint(breakpointId);
|
147
|
+
expect(currentBreakpoint).toBe('md'); // 600px width
|
148
|
+
});
|
149
|
+
|
150
|
+
it('should apply fluid typography with accessibility compliance', () => {
|
151
|
+
const heading = testContent.querySelector('h1') as HTMLElement;
|
152
|
+
const paragraph = testContent.querySelector('p') as HTMLElement;
|
153
|
+
|
154
|
+
// Apply fluid typography
|
155
|
+
fluidTypography.applyFluidScaling(heading, {
|
156
|
+
minSize: 18,
|
157
|
+
maxSize: 32,
|
158
|
+
accessibility: 'AA',
|
159
|
+
enforceAccessibility: true
|
160
|
+
});
|
161
|
+
|
162
|
+
fluidTypography.applyFluidScaling(paragraph, {
|
163
|
+
minSize: 14,
|
164
|
+
maxSize: 18,
|
165
|
+
accessibility: 'AA',
|
166
|
+
enforceAccessibility: true
|
167
|
+
});
|
168
|
+
|
169
|
+
// Check that typography was applied
|
170
|
+
expect(heading.style.fontSize).toContain('clamp(');
|
171
|
+
expect(paragraph.style.fontSize).toContain('clamp(');
|
172
|
+
|
173
|
+
// Check accessibility compliance
|
174
|
+
expect(heading.getAttribute('data-proteus-min-size')).toBe('18'); // Should meet WCAG AA
|
175
|
+
expect(paragraph.getAttribute('data-proteus-min-size')).toBe('14'); // Should meet WCAG AA
|
176
|
+
});
|
177
|
+
|
178
|
+
it('should optimize line heights intelligently', () => {
|
179
|
+
const heading = testContent.querySelector('h1') as HTMLElement;
|
180
|
+
const paragraph = testContent.querySelector('p') as HTMLElement;
|
181
|
+
|
182
|
+
// Optimize line heights
|
183
|
+
const headingResult = lineHeightOptimization.optimizeLineHeight(heading, {
|
184
|
+
contentType: 'heading',
|
185
|
+
accessibility: 'AA',
|
186
|
+
enforceAccessibility: true
|
187
|
+
});
|
188
|
+
|
189
|
+
const paragraphResult = lineHeightOptimization.optimizeLineHeight(paragraph, {
|
190
|
+
contentType: 'body',
|
191
|
+
accessibility: 'AA',
|
192
|
+
enforceAccessibility: true
|
193
|
+
});
|
194
|
+
|
195
|
+
// Check that line heights were applied
|
196
|
+
expect(heading.style.lineHeight).toBeTruthy();
|
197
|
+
expect(paragraph.style.lineHeight).toBeTruthy();
|
198
|
+
|
199
|
+
// Check accessibility compliance
|
200
|
+
expect(headingResult.accessibilityCompliant).toBe(true);
|
201
|
+
expect(paragraphResult.accessibilityCompliant).toBe(true);
|
202
|
+
|
203
|
+
// Headings should have tighter line height than body text
|
204
|
+
expect(headingResult.lineHeight).toBeLessThan(paragraphResult.lineHeight);
|
205
|
+
});
|
206
|
+
|
207
|
+
it('should monitor performance and provide metrics', async () => {
|
208
|
+
performanceMonitor.start();
|
209
|
+
|
210
|
+
// Simulate some operations
|
211
|
+
for (let i = 0; i < 10; i++) {
|
212
|
+
performanceMonitor.recordOperation();
|
213
|
+
}
|
214
|
+
|
215
|
+
// Update metrics
|
216
|
+
performanceMonitor.updateMetrics();
|
217
|
+
|
218
|
+
const metrics = performanceMonitor.getMetrics();
|
219
|
+
|
220
|
+
expect(metrics.frameRate).toBeGreaterThan(0);
|
221
|
+
expect(metrics.memoryUsage.used).toBeGreaterThan(0);
|
222
|
+
expect(metrics.domNodes).toBeGreaterThan(0);
|
223
|
+
expect(metrics.operationsPerSecond).toBeGreaterThanOrEqual(0);
|
224
|
+
});
|
225
|
+
|
226
|
+
it('should handle container resize and update all systems', () => {
|
227
|
+
const breakpointCallback = vi.fn();
|
228
|
+
|
229
|
+
// Set up systems
|
230
|
+
const breakpointId = containerBreakpoints.register(testContainer, {
|
231
|
+
sm: '400px',
|
232
|
+
md: '600px',
|
233
|
+
lg: '800px'
|
234
|
+
}, breakpointCallback);
|
235
|
+
|
236
|
+
const heading = testContent.querySelector('h1') as HTMLElement;
|
237
|
+
fluidTypography.applyContainerBasedScaling(heading, {
|
238
|
+
minSize: 18,
|
239
|
+
maxSize: 32,
|
240
|
+
containerElement: testContainer,
|
241
|
+
minContainerWidth: 300,
|
242
|
+
maxContainerWidth: 900
|
243
|
+
});
|
244
|
+
|
245
|
+
// Simulate container resize
|
246
|
+
vi.spyOn(testContainer, 'getBoundingClientRect').mockReturnValue({
|
247
|
+
width: 800,
|
248
|
+
height: 400,
|
249
|
+
top: 0,
|
250
|
+
left: 0,
|
251
|
+
bottom: 400,
|
252
|
+
right: 800,
|
253
|
+
x: 0,
|
254
|
+
y: 0,
|
255
|
+
toJSON: () => ({})
|
256
|
+
} as DOMRect);
|
257
|
+
|
258
|
+
// Update systems
|
259
|
+
containerBreakpoints.updateElement(testContainer);
|
260
|
+
smartContainers.updateContainer(testContainer);
|
261
|
+
|
262
|
+
// Check that breakpoint changed
|
263
|
+
const newBreakpoint = containerBreakpoints.getCurrentBreakpoint(breakpointId);
|
264
|
+
expect(newBreakpoint).toBe('lg'); // 800px width
|
265
|
+
|
266
|
+
// Check that callback was called
|
267
|
+
expect(breakpointCallback).toHaveBeenCalled();
|
268
|
+
});
|
269
|
+
|
270
|
+
it('should provide performance recommendations', () => {
|
271
|
+
performanceMonitor.start();
|
272
|
+
|
273
|
+
// Simulate poor performance
|
274
|
+
performanceMonitor['metrics'].frameRate = 30; // Below target
|
275
|
+
performanceMonitor['metrics'].memoryUsage.percentage = 90; // High memory
|
276
|
+
performanceMonitor['metrics'].domNodes = 6000; // Many nodes
|
277
|
+
|
278
|
+
const recommendations = performanceMonitor.getRecommendations();
|
279
|
+
|
280
|
+
expect(recommendations.length).toBeGreaterThan(0);
|
281
|
+
expect(recommendations.some(r => r.includes('DOM manipulations'))).toBe(true);
|
282
|
+
expect(recommendations.some(r => r.includes('Memory usage'))).toBe(true);
|
283
|
+
expect(recommendations.some(r => r.includes('DOM tree'))).toBe(true);
|
284
|
+
});
|
285
|
+
|
286
|
+
it('should handle errors gracefully across all systems', () => {
|
287
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
288
|
+
|
289
|
+
// Test error handling in each system
|
290
|
+
expect(() => {
|
291
|
+
fluidTypography.applyFluidScaling(null as any, {} as any);
|
292
|
+
}).not.toThrow();
|
293
|
+
|
294
|
+
expect(() => {
|
295
|
+
lineHeightOptimization.optimizeLineHeight(null as any, {} as any);
|
296
|
+
}).not.toThrow();
|
297
|
+
|
298
|
+
expect(() => {
|
299
|
+
containerBreakpoints.register(null as any, {} as any);
|
300
|
+
}).not.toThrow();
|
301
|
+
|
302
|
+
// Should have logged errors but not thrown
|
303
|
+
expect(consoleSpy).toHaveBeenCalled();
|
304
|
+
consoleSpy.mockRestore();
|
305
|
+
});
|
306
|
+
|
307
|
+
it('should clean up resources properly', () => {
|
308
|
+
// Start all systems
|
309
|
+
smartContainers.startMonitoring();
|
310
|
+
performanceMonitor.start();
|
311
|
+
|
312
|
+
const heading = testContent.querySelector('h1') as HTMLElement;
|
313
|
+
fluidTypography.applyFluidScaling(heading, { minSize: 16, maxSize: 24 });
|
314
|
+
lineHeightOptimization.optimizeLineHeight(heading);
|
315
|
+
|
316
|
+
const breakpointId = containerBreakpoints.register(testContainer, { md: '600px' });
|
317
|
+
|
318
|
+
// Clean up
|
319
|
+
expect(() => {
|
320
|
+
smartContainers.destroy();
|
321
|
+
containerBreakpoints.destroy();
|
322
|
+
fluidTypography.destroy();
|
323
|
+
lineHeightOptimization.destroy();
|
324
|
+
performanceMonitor.stop();
|
325
|
+
}).not.toThrow();
|
326
|
+
|
327
|
+
// Check that resources were cleaned up
|
328
|
+
expect(smartContainers.getMetrics().activeContainers).toBe(0);
|
329
|
+
expect(containerBreakpoints.getMetrics().totalRegistrations).toBe(0);
|
330
|
+
});
|
331
|
+
});
|
332
|
+
|
333
|
+
describe('Real-World Scenarios', () => {
|
334
|
+
it('should handle a complete e-commerce product grid', async () => {
|
335
|
+
// Create a product grid structure
|
336
|
+
const productGrid = document.createElement('div');
|
337
|
+
productGrid.className = 'product-grid';
|
338
|
+
productGrid.style.width = '800px';
|
339
|
+
productGrid.style.display = 'grid';
|
340
|
+
|
341
|
+
// Add product items
|
342
|
+
for (let i = 0; i < 12; i++) {
|
343
|
+
const product = document.createElement('div');
|
344
|
+
product.className = 'product-item';
|
345
|
+
product.innerHTML = `
|
346
|
+
<h3>Product ${i + 1}</h3>
|
347
|
+
<p>Product description that should scale with container size.</p>
|
348
|
+
<span class="price">$${(i + 1) * 10}</span>
|
349
|
+
`;
|
350
|
+
productGrid.appendChild(product);
|
351
|
+
}
|
352
|
+
|
353
|
+
document.body.appendChild(productGrid);
|
354
|
+
|
355
|
+
// Apply ProteusJS features
|
356
|
+
const containers = await smartContainers.detectContainers();
|
357
|
+
const gridContainer = containers.find(c => c.element === productGrid);
|
358
|
+
expect(gridContainer).toBeDefined();
|
359
|
+
|
360
|
+
// Set up responsive breakpoints
|
361
|
+
containerBreakpoints.register(productGrid, {
|
362
|
+
mobile: '320px',
|
363
|
+
tablet: '768px',
|
364
|
+
desktop: '1024px'
|
365
|
+
});
|
366
|
+
|
367
|
+
// Apply typography to all products
|
368
|
+
const headings = productGrid.querySelectorAll('h3');
|
369
|
+
const descriptions = productGrid.querySelectorAll('p');
|
370
|
+
|
371
|
+
headings.forEach(heading => {
|
372
|
+
fluidTypography.applyFluidScaling(heading as HTMLElement, {
|
373
|
+
minSize: 16,
|
374
|
+
maxSize: 20,
|
375
|
+
accessibility: 'AA'
|
376
|
+
});
|
377
|
+
});
|
378
|
+
|
379
|
+
descriptions.forEach(desc => {
|
380
|
+
fluidTypography.applyFluidScaling(desc as HTMLElement, {
|
381
|
+
minSize: 14,
|
382
|
+
maxSize: 16,
|
383
|
+
accessibility: 'AA'
|
384
|
+
});
|
385
|
+
});
|
386
|
+
|
387
|
+
// Create adaptive grid
|
388
|
+
const grid = new AdaptiveGrid(productGrid, {
|
389
|
+
minColumnWidth: 200,
|
390
|
+
maxColumns: 4,
|
391
|
+
gap: 16,
|
392
|
+
responsive: true
|
393
|
+
});
|
394
|
+
|
395
|
+
grid.activate();
|
396
|
+
|
397
|
+
// Verify everything is working
|
398
|
+
expect(productGrid.style.display).toBe('grid');
|
399
|
+
expect(headings[0].style.fontSize).toContain('clamp(');
|
400
|
+
expect(descriptions[0].style.fontSize).toContain('clamp(');
|
401
|
+
});
|
402
|
+
|
403
|
+
it('should handle responsive dashboard layout', async () => {
|
404
|
+
// Create dashboard structure
|
405
|
+
const dashboard = document.createElement('div');
|
406
|
+
dashboard.className = 'dashboard';
|
407
|
+
dashboard.style.width = '1200px';
|
408
|
+
dashboard.style.display = 'grid';
|
409
|
+
|
410
|
+
const sidebar = document.createElement('aside');
|
411
|
+
sidebar.className = 'sidebar';
|
412
|
+
sidebar.innerHTML = '<h2>Navigation</h2><nav>Menu items</nav>';
|
413
|
+
|
414
|
+
const main = document.createElement('main');
|
415
|
+
main.className = 'main-content';
|
416
|
+
main.innerHTML = `
|
417
|
+
<h1>Dashboard Title</h1>
|
418
|
+
<div class="metrics">
|
419
|
+
<div class="metric-card">
|
420
|
+
<h3>Revenue</h3>
|
421
|
+
<p class="metric-value">$125,000</p>
|
422
|
+
</div>
|
423
|
+
<div class="metric-card">
|
424
|
+
<h3>Users</h3>
|
425
|
+
<p class="metric-value">1,250</p>
|
426
|
+
</div>
|
427
|
+
</div>
|
428
|
+
`;
|
429
|
+
|
430
|
+
dashboard.appendChild(sidebar);
|
431
|
+
dashboard.appendChild(main);
|
432
|
+
document.body.appendChild(dashboard);
|
433
|
+
|
434
|
+
// Apply ProteusJS features
|
435
|
+
const containers = await smartContainers.detectContainers();
|
436
|
+
expect(containers.length).toBeGreaterThan(0);
|
437
|
+
|
438
|
+
// Set up breakpoints for responsive behavior
|
439
|
+
containerBreakpoints.register(dashboard, {
|
440
|
+
mobile: '768px',
|
441
|
+
desktop: '1024px'
|
442
|
+
}, (breakpoint) => {
|
443
|
+
if (breakpoint === 'mobile') {
|
444
|
+
dashboard.style.gridTemplateColumns = '1fr';
|
445
|
+
} else {
|
446
|
+
dashboard.style.gridTemplateColumns = '250px 1fr';
|
447
|
+
}
|
448
|
+
});
|
449
|
+
|
450
|
+
// Apply typography optimization
|
451
|
+
const title = main.querySelector('h1') as HTMLElement;
|
452
|
+
const metricValues = main.querySelectorAll('.metric-value') as NodeListOf<HTMLElement>;
|
453
|
+
|
454
|
+
fluidTypography.applyFluidScaling(title, {
|
455
|
+
minSize: 24,
|
456
|
+
maxSize: 36,
|
457
|
+
accessibility: 'AA'
|
458
|
+
});
|
459
|
+
|
460
|
+
metricValues.forEach(value => {
|
461
|
+
fluidTypography.applyFluidScaling(value, {
|
462
|
+
minSize: 20,
|
463
|
+
maxSize: 28,
|
464
|
+
accessibility: 'AA'
|
465
|
+
});
|
466
|
+
});
|
467
|
+
|
468
|
+
// Verify responsive behavior
|
469
|
+
expect(dashboard.style.gridTemplateColumns).toBeTruthy();
|
470
|
+
expect(title.style.fontSize).toContain('clamp(');
|
471
|
+
});
|
472
|
+
});
|
473
|
+
|
474
|
+
describe('Performance Validation', () => {
|
475
|
+
it('should maintain sub-60ms response times', async () => {
|
476
|
+
performanceMonitor.start();
|
477
|
+
|
478
|
+
const startTime = performance.now();
|
479
|
+
|
480
|
+
// Perform typical operations
|
481
|
+
await smartContainers.detectContainers();
|
482
|
+
|
483
|
+
const heading = testContent.querySelector('h1') as HTMLElement;
|
484
|
+
fluidTypography.applyFluidScaling(heading, { minSize: 16, maxSize: 24 });
|
485
|
+
lineHeightOptimization.optimizeLineHeight(heading);
|
486
|
+
|
487
|
+
containerBreakpoints.register(testContainer, { md: '600px' });
|
488
|
+
|
489
|
+
const endTime = performance.now();
|
490
|
+
const responseTime = endTime - startTime;
|
491
|
+
|
492
|
+
// Should complete within performance target
|
493
|
+
expect(responseTime).toBeLessThan(60); // 60ms target
|
494
|
+
});
|
495
|
+
|
496
|
+
it('should handle high-frequency updates efficiently', () => {
|
497
|
+
performanceMonitor.start();
|
498
|
+
|
499
|
+
const startTime = performance.now();
|
500
|
+
|
501
|
+
// Simulate rapid container resizes
|
502
|
+
for (let i = 0; i < 100; i++) {
|
503
|
+
smartContainers.updateContainer(testContainer);
|
504
|
+
containerBreakpoints.updateElement(testContainer);
|
505
|
+
performanceMonitor.recordOperation();
|
506
|
+
}
|
507
|
+
|
508
|
+
const endTime = performance.now();
|
509
|
+
const totalTime = endTime - startTime;
|
510
|
+
|
511
|
+
// Should handle 100 updates efficiently
|
512
|
+
expect(totalTime).toBeLessThan(100); // 1ms per operation average
|
513
|
+
|
514
|
+
const metrics = performanceMonitor.getMetrics();
|
515
|
+
expect(metrics.operationsPerSecond).toBeGreaterThan(0);
|
516
|
+
});
|
517
|
+
});
|
518
|
+
});
|