@useavalon/avalon 0.1.5 → 0.1.6

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.
Files changed (31) hide show
  1. package/package.json +31 -58
  2. package/src/build/README.md +0 -310
  3. package/src/client/tests/css-hmr-handler.test.ts +0 -360
  4. package/src/client/tests/framework-adapter.test.ts +0 -519
  5. package/src/client/tests/hmr-coordinator.test.ts +0 -176
  6. package/src/client/tests/hydration-option-parsing.test.ts +0 -107
  7. package/src/client/tests/lit-adapter.test.ts +0 -427
  8. package/src/client/tests/preact-adapter.test.ts +0 -353
  9. package/src/client/tests/qwik-adapter.test.ts +0 -343
  10. package/src/client/tests/react-adapter.test.ts +0 -317
  11. package/src/client/tests/solid-adapter.test.ts +0 -396
  12. package/src/client/tests/svelte-adapter.test.ts +0 -387
  13. package/src/client/tests/vue-adapter.test.ts +0 -407
  14. package/src/components/tests/component-analyzer.test.ts +0 -96
  15. package/src/components/tests/component-detection.test.ts +0 -347
  16. package/src/components/tests/persistent-islands.test.ts +0 -398
  17. package/src/core/components/tests/enhanced-framework-detector.test.ts +0 -577
  18. package/src/core/components/tests/framework-registry.test.ts +0 -465
  19. package/src/core/integrations/README.md +0 -282
  20. package/src/core/layout/tests/enhanced-layout-resolver.test.ts +0 -477
  21. package/src/core/layout/tests/layout-cache-optimization.test.ts +0 -149
  22. package/src/core/layout/tests/layout-composer.test.ts +0 -486
  23. package/src/core/layout/tests/layout-data-loader.test.ts +0 -443
  24. package/src/core/layout/tests/layout-discovery.test.ts +0 -253
  25. package/src/core/layout/tests/layout-matcher.test.ts +0 -480
  26. package/src/core/modules/tests/framework-module-resolver.test.ts +0 -263
  27. package/src/core/modules/tests/module-resolution-integration.test.ts +0 -117
  28. package/src/islands/discovery/tests/island-discovery.test.ts +0 -881
  29. package/src/middleware/__tests__/discovery.test.ts +0 -107
  30. package/src/types/tests/layout-types.test.ts +0 -197
  31. package/src/vite-plugin/tests/image-optimization.test.ts +0 -54
@@ -1,107 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
-
3
- // Test the enhanced hydration option parsing functionality
4
-
5
- describe('Hydration Option Parsing - validateRootMargin patterns', () => {
6
- it('should validate valid rootMargin patterns', () => {
7
- const validPatterns = ['10px', '10px 20px', '10px 20px 30px 40px', '10%', '-10px', '0px', '100px 50px'];
8
- const rootMarginRegex = /^(-?\d+(?:\.\d+)?(?:px|%)?(?:\s+-?\d+(?:\.\d+)?(?:px|%)?){0,3})$/;
9
-
10
- validPatterns.forEach(pattern => {
11
- expect(rootMarginRegex.test(pattern.trim())).toBe(true);
12
- });
13
- });
14
-
15
- it('should reject invalid rootMargin patterns', () => {
16
- const invalidPatterns = ['invalid', '', '10px 20px 30px 40px 50px', 'abc', '10px invalid 20px'];
17
- const rootMarginRegex = /^(-?\d+(?:\.\d+)?(?:px|%)?(?:\s+-?\d+(?:\.\d+)?(?:px|%)?){0,3})$/;
18
-
19
- invalidPatterns.forEach(pattern => {
20
- expect(rootMarginRegex.test(pattern.trim())).toBe(false);
21
- });
22
- });
23
- });
24
-
25
- describe('Hydration Option Parsing - directive parsing patterns', () => {
26
- it('should parse directives correctly', () => {
27
- const testCases = [
28
- { input: 'on:client', expectedDirective: 'on:client' },
29
- { input: 'on:visible={{rootMargin: "100px"}}', expectedDirective: 'on:visible' },
30
- { input: 'on:idle={{timeout: 10000}}', expectedDirective: 'on:idle' },
31
- { input: 'media:screen', expectedDirective: 'media:screen' },
32
- ];
33
-
34
- testCases.forEach(testCase => {
35
- const directiveMatch = testCase.input.match(/^([^=\s]+)/);
36
- const directive = directiveMatch ? directiveMatch[1] : 'on:client';
37
- expect(directive).toBe(testCase.expectedDirective);
38
- });
39
- });
40
- });
41
-
42
- describe('Hydration Option Parsing - option extraction patterns', () => {
43
- it('should extract options correctly', () => {
44
- const testCases = [
45
- { input: 'on:visible={{rootMargin: "100px"}}', expectedOptions: 'rootMargin: "100px"' },
46
- { input: 'on:visible={{rootMargin: "50px", threshold: 0.5}}', expectedOptions: 'rootMargin: "50px", threshold: 0.5' },
47
- { input: 'on:idle={{timeout: 10000}}', expectedOptions: 'timeout: 10000' },
48
- ];
49
-
50
- testCases.forEach(testCase => {
51
- const optionsMatch = testCase.input.match(/=\s*\{\{(.+?)\}\}/);
52
- const extractedOptions = optionsMatch ? optionsMatch[1] : '';
53
- expect(extractedOptions).toBe(testCase.expectedOptions);
54
- });
55
- });
56
- });
57
-
58
- describe('Hydration Option Parsing - JSON parsing preparation', () => {
59
- it('should normalize options strings for JSON parsing', () => {
60
- const testCases = [
61
- { input: 'rootMargin: "100px"', expected: '"rootMargin": "100px"' },
62
- { input: "rootMargin: '100px'", expected: '"rootMargin": "100px"' },
63
- { input: 'timeout: 5000', expected: '"timeout": 5000' },
64
- ];
65
-
66
- testCases.forEach(testCase => {
67
- const normalized = testCase.input
68
- .replace(/(\w+):/g, '"$1":')
69
- .replace(/'/g, '"');
70
- expect(normalized).toBe(testCase.expected);
71
- const parsed = JSON.parse('{' + normalized + '}');
72
- expect(parsed).toBeDefined();
73
- });
74
- });
75
- });
76
-
77
- describe('Hydration Option Parsing - validation ranges', () => {
78
- it('should validate threshold values (0-1 range)', () => {
79
- const validThresholds = [0, 0.5, 1, 0.25, 0.75];
80
- const invalidThresholds = [-0.1, 1.1, 2, -1, '0.5', null, undefined];
81
-
82
- validThresholds.forEach(threshold => {
83
- const isValid = typeof threshold === 'number' && threshold >= 0 && threshold <= 1;
84
- expect(isValid).toBe(true);
85
- });
86
-
87
- invalidThresholds.forEach(threshold => {
88
- const isValid = typeof threshold === 'number' && threshold >= 0 && threshold <= 1;
89
- expect(isValid).toBe(false);
90
- });
91
- });
92
-
93
- it('should validate timeout values (positive numbers up to 60 seconds)', () => {
94
- const validTimeouts = [1000, 5000, 30000, 60000];
95
- const invalidTimeouts = [0, -1000, 70000, '5000', null, undefined];
96
-
97
- validTimeouts.forEach(timeout => {
98
- const isValid = typeof timeout === 'number' && timeout > 0 && timeout <= 60000;
99
- expect(isValid).toBe(true);
100
- });
101
-
102
- invalidTimeouts.forEach(timeout => {
103
- const isValid = typeof timeout === 'number' && timeout > 0 && timeout <= 60000;
104
- expect(isValid).toBe(false);
105
- });
106
- });
107
- });
@@ -1,427 +0,0 @@
1
- /**
2
- * Tests for Lit HMR Adapter
3
- *
4
- * Verifies Lit-specific HMR functionality including:
5
- * - Component detection
6
- * - State preservation
7
- * - Custom element re-registration
8
- * - Property and attribute preservation
9
- */
10
-
11
- import { describe, it, expect } from 'vitest';
12
- import { LitHMRAdapter } from '../adapters/lit-adapter.ts';
13
-
14
- // Mock HTMLElement for testing
15
- class MockHTMLElement {
16
- private _attributes: Map<string, string> = new Map();
17
- private _children: MockHTMLElement[] = [];
18
- public scrollTop = 0;
19
- public scrollLeft = 0;
20
- public style: Record<string, string> = {};
21
- public tagName = 'DIV';
22
- public textContent: string | null = null;
23
- public innerHTML = '';
24
- public className = '';
25
-
26
- getAttribute(name: string): string | null {
27
- return this._attributes.get(name) || null;
28
- }
29
-
30
- setAttribute(name: string, value: string): void {
31
- this._attributes.set(name, value);
32
- if (name === 'class') {
33
- this.className = value;
34
- }
35
- }
36
-
37
- removeAttribute(name: string): void {
38
- this._attributes.delete(name);
39
- }
40
-
41
- hasAttribute(name: string): boolean {
42
- return this._attributes.has(name);
43
- }
44
-
45
- querySelector(selector: string): MockHTMLElement | null {
46
- // Simple mock - check if selector matches class or tag
47
- if (selector.startsWith('.')) {
48
- const className = selector.substring(1);
49
- for (const child of this._children) {
50
- if (child.className === className) {
51
- return child;
52
- }
53
- }
54
- }
55
- // Return first child for other selectors
56
- if (this._children.length > 0) {
57
- return this._children[0];
58
- }
59
- return null;
60
- }
61
-
62
- querySelectorAll(selector: string): MockHTMLElement[] {
63
- return this._children;
64
- }
65
-
66
- appendChild(child: MockHTMLElement): MockHTMLElement {
67
- this._children.push(child);
68
- return child;
69
- }
70
-
71
- insertBefore(newChild: MockHTMLElement, referenceChild: MockHTMLElement | null): MockHTMLElement {
72
- if (referenceChild === null || !this._children.includes(referenceChild)) {
73
- this._children.push(newChild);
74
- } else {
75
- const index = this._children.indexOf(referenceChild);
76
- this._children.splice(index, 0, newChild);
77
- }
78
- return newChild;
79
- }
80
-
81
- remove(): void {
82
- this._children = [];
83
- }
84
-
85
- get children(): MockHTMLElement[] {
86
- return this._children;
87
- }
88
-
89
- get firstChild(): MockHTMLElement | null {
90
- return this._children[0] || null;
91
- }
92
-
93
- get attributes(): Array<{ name: string; value: string }> & { length: number } {
94
- const attrs = Array.from(this._attributes.entries()).map(([name, value]) => ({ name, value }));
95
- const result = attrs as Array<{ name: string; value: string }> & { length: number };
96
- return result;
97
- }
98
-
99
- contains(element: unknown): boolean {
100
- return false;
101
- }
102
- }
103
-
104
- // Mock Lit component class
105
- class MockLitElement {
106
- static elementName = 'mock-counter';
107
-
108
- // Lit-specific properties
109
- count = 0;
110
- label = 'Counter';
111
-
112
- // Lit-specific methods
113
- render() {
114
- return `<div>${this.label}: ${this.count}</div>`;
115
- }
116
-
117
- requestUpdate() {
118
- // Mock update
119
- }
120
-
121
- get updateComplete(): Promise<boolean> {
122
- return Promise.resolve(true);
123
- }
124
- }
125
-
126
- // Mock Lit component with decorators
127
- class MockDecoratedLitElement {
128
- static elementName = 'decorated-counter';
129
-
130
- __litElement = true;
131
-
132
- count = 0;
133
-
134
- render() {
135
- return `<div>Count: ${this.count}</div>`;
136
- }
137
-
138
- requestUpdate() {
139
- // Mock update
140
- }
141
-
142
- get updateComplete(): Promise<boolean> {
143
- return Promise.resolve(true);
144
- }
145
- }
146
-
147
- // Mock Lit component module (default export)
148
- const MockLitModule = {
149
- default: MockLitElement,
150
- };
151
-
152
- describe('LitHMRAdapter - name', () => {
153
- it('should have correct name', () => {
154
- const adapter = new LitHMRAdapter();
155
- expect(adapter.name).toBe('lit');
156
- });
157
- });
158
-
159
- describe('LitHMRAdapter - canHandle', () => {
160
- it('should detect Lit components', () => {
161
- const adapter = new LitHMRAdapter();
162
-
163
- // Should handle Lit element class
164
- expect(adapter.canHandle(MockLitElement)).toBe(true);
165
-
166
- // Should handle decorated Lit element
167
- expect(adapter.canHandle(MockDecoratedLitElement)).toBe(true);
168
-
169
- // Should handle module with default export
170
- expect(adapter.canHandle(MockLitModule)).toBe(true);
171
-
172
- // Should not handle non-Lit components
173
- expect(adapter.canHandle(null)).toBe(false);
174
- expect(adapter.canHandle(undefined)).toBe(false);
175
- expect(adapter.canHandle({})).toBe(false);
176
- expect(adapter.canHandle('string')).toBe(false);
177
- expect(adapter.canHandle(123)).toBe(false);
178
- });
179
-
180
- it('should detect Lit by prototype methods', () => {
181
- const adapter = new LitHMRAdapter();
182
-
183
- // Create a class with Lit-like methods
184
- class LitLikeElement {
185
- render() { return ''; }
186
- requestUpdate() {}
187
- get updateComplete() { return Promise.resolve(true); }
188
- }
189
-
190
- expect(adapter.canHandle(LitLikeElement)).toBe(true);
191
- });
192
-
193
- it('should detect Lit by function signature', () => {
194
- const adapter = new LitHMRAdapter();
195
-
196
- // Create a class that looks like a Lit component in its string representation
197
- class LitLikeComponent {
198
- render() {
199
- // This will show up in toString()
200
- return 'html`<div>Hello</div>`';
201
- }
202
- }
203
-
204
- // The adapter should be able to detect Lit patterns
205
- // We just verify the method exists and works
206
- expect(adapter.canHandle).toBeDefined();
207
-
208
- // Test with a class that has LitElement in its code
209
- const hasLitPattern = adapter.canHandle(LitLikeComponent);
210
- // This may or may not detect it depending on toString() output
211
- // but we verify it doesn't throw
212
- expect(typeof hasLitPattern).toBe('boolean');
213
- });
214
- });
215
-
216
- describe('LitHMRAdapter - preserveState', () => {
217
- it('should capture element properties', () => {
218
- const adapter = new LitHMRAdapter();
219
-
220
- // Create a mock island with a Lit element
221
- const island = new MockHTMLElement() as unknown as HTMLElement;
222
- island.setAttribute('data-framework', 'lit');
223
- island.setAttribute('data-src', '/islands/Counter.lit.ts');
224
- island.setAttribute('data-props', '{"initialCount": 5}');
225
- island.setAttribute('data-tag-name', 'mock-counter');
226
-
227
- // Create a mock Lit element
228
- const litElement = new MockHTMLElement() as unknown as HTMLElement & {
229
- count: number;
230
- label: string;
231
- };
232
- (litElement as unknown as Record<string, unknown>).count = 10;
233
- (litElement as unknown as Record<string, unknown>).label = 'Test Counter';
234
- litElement.setAttribute('data-lit-element', 'true');
235
- litElement.setAttribute('theme', 'dark');
236
-
237
- (island as unknown as MockHTMLElement).appendChild(litElement as unknown as MockHTMLElement);
238
-
239
- // Preserve state - will return null due to missing document global
240
- // but should not throw
241
- const state = adapter.preserveState(island);
242
-
243
- // In a test environment without document, state will be null
244
- // This is expected behavior - the adapter handles it gracefully
245
- // In a real browser environment, state would be captured
246
- if (state) {
247
- expect(state.framework).toBe('lit');
248
- expect(state.data).toBeDefined();
249
- }
250
- });
251
-
252
- it('should capture DOM state', () => {
253
- const adapter = new LitHMRAdapter();
254
-
255
- // Create a mock island with form elements
256
- const island = new MockHTMLElement() as unknown as HTMLElement;
257
- island.setAttribute('data-framework', 'lit');
258
- island.setAttribute('data-src', '/islands/Form.lit.ts');
259
- island.setAttribute('data-tag-name', 'mock-form');
260
-
261
- // Note: Full DOM state capture requires a real DOM environment
262
- // This test verifies the method doesn't throw
263
- const state = adapter.preserveState(island);
264
-
265
- // State may be null in test environment without document global
266
- // This is expected and handled gracefully
267
- if (state) {
268
- expect(state.framework).toBe('lit');
269
- }
270
- });
271
-
272
- it('should handle missing elements gracefully', () => {
273
- const adapter = new LitHMRAdapter();
274
-
275
- // Create an empty island
276
- const island = new MockHTMLElement() as unknown as HTMLElement;
277
- island.setAttribute('data-framework', 'lit');
278
- island.setAttribute('data-src', '/islands/Empty.lit.ts');
279
-
280
- // Preserve state should not throw
281
- const state = adapter.preserveState(island);
282
-
283
- // State may be null in test environment
284
- if (state) {
285
- expect(state.framework).toBe('lit');
286
- }
287
- });
288
- });
289
-
290
- describe('LitHMRAdapter - handleError', () => {
291
- it('should not throw', () => {
292
- const adapter = new LitHMRAdapter();
293
-
294
- const island = new MockHTMLElement() as unknown as HTMLElement;
295
- const error = new Error('Test error');
296
-
297
- // handleError requires document global for creating error indicator
298
- // In test environment, it will log but not throw
299
- // This is expected behavior
300
- try {
301
- adapter.handleError(island, error);
302
- } catch (e) {
303
- // Expected in test environment without document
304
- expect(e instanceof ReferenceError).toBe(true);
305
- }
306
- });
307
-
308
- it('should handle different error types', () => {
309
- const adapter = new LitHMRAdapter();
310
-
311
- const island = new MockHTMLElement() as unknown as HTMLElement;
312
-
313
- // Test that different error types are handled
314
- const errors = [
315
- new Error('custom element already defined'),
316
- new Error('property not found'),
317
- new Error('render error'),
318
- ];
319
-
320
- for (const error of errors) {
321
- try {
322
- adapter.handleError(island, error);
323
- } catch (e) {
324
- // Expected in test environment without document
325
- expect(e instanceof ReferenceError).toBe(true);
326
- }
327
- }
328
- });
329
- });
330
-
331
- describe('LitHMRAdapter - restoreState', () => {
332
- it('should restore element properties', () => {
333
- const adapter = new LitHMRAdapter();
334
-
335
- // Create a mock island with a Lit element
336
- const island = new MockHTMLElement() as unknown as HTMLElement;
337
- island.setAttribute('data-tag-name', 'mock-counter');
338
-
339
- const litElement = new MockHTMLElement() as unknown as HTMLElement & {
340
- count: number;
341
- label: string;
342
- };
343
- (litElement as unknown as Record<string, unknown>).count = 0;
344
- (litElement as unknown as Record<string, unknown>).label = '';
345
- (island as unknown as MockHTMLElement).appendChild(litElement as unknown as MockHTMLElement);
346
-
347
- // Create a state snapshot
348
- const state = {
349
- framework: 'lit' as const,
350
- timestamp: Date.now(),
351
- data: {
352
- tagName: 'mock-counter',
353
- elementProperties: {
354
- count: 10,
355
- label: 'Restored Counter',
356
- },
357
- elementAttributes: {
358
- theme: 'dark',
359
- },
360
- },
361
- };
362
-
363
- // Restore state
364
- adapter.restoreState(island, state);
365
-
366
- // Verify properties were restored
367
- expect((litElement as unknown as Record<string, unknown>).count).toBe(10);
368
- expect((litElement as unknown as Record<string, unknown>).label).toBe('Restored Counter');
369
- expect(litElement.getAttribute('theme')).toBe('dark');
370
- });
371
-
372
- it('should handle missing elements gracefully', () => {
373
- const adapter = new LitHMRAdapter();
374
-
375
- const island = new MockHTMLElement() as unknown as HTMLElement;
376
-
377
- const state = {
378
- framework: 'lit' as const,
379
- timestamp: Date.now(),
380
- data: {
381
- tagName: 'missing-element',
382
- elementProperties: { count: 10 },
383
- },
384
- };
385
-
386
- // Should not throw
387
- adapter.restoreState(island, state);
388
- });
389
- });
390
-
391
- describe('LitHMRAdapter - unmount', () => {
392
- it('should clean up element', () => {
393
- const adapter = new LitHMRAdapter();
394
-
395
- const island = new MockHTMLElement() as unknown as HTMLElement;
396
- island.setAttribute('data-tag-name', 'mock-counter');
397
-
398
- const litElement = new MockHTMLElement() as unknown as HTMLElement;
399
- (island as unknown as MockHTMLElement).appendChild(litElement as unknown as MockHTMLElement);
400
-
401
- // Verify element exists
402
- expect((island as unknown as MockHTMLElement).children.length).toBe(1);
403
-
404
- // Unmount - this will call querySelectorAll and remove elements
405
- adapter.unmount(island);
406
-
407
- // In the mock implementation, remove() clears the _children array
408
- // but the parent's children array is not automatically updated
409
- // This is a limitation of the mock - in a real DOM, the element would be removed
410
- // We just verify unmount doesn't throw
411
- });
412
-
413
- it('should handle missing elements gracefully', () => {
414
- const adapter = new LitHMRAdapter();
415
-
416
- const island = new MockHTMLElement() as unknown as HTMLElement;
417
-
418
- // Should not throw
419
- adapter.unmount(island);
420
- });
421
- });
422
-
423
- // Note: Full integration tests for update() method would require:
424
- // - A real Lit runtime
425
- // - Custom element registry
426
- // - DOM environment with custom elements support
427
- // These are better tested in integration tests or E2E tests