@useavalon/avalon 0.1.4 → 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.
- package/package.json +31 -58
- package/src/vite-plugin/plugin.ts +22 -4
- package/src/build/README.md +0 -310
- package/src/client/tests/css-hmr-handler.test.ts +0 -360
- package/src/client/tests/framework-adapter.test.ts +0 -519
- package/src/client/tests/hmr-coordinator.test.ts +0 -176
- package/src/client/tests/hydration-option-parsing.test.ts +0 -107
- package/src/client/tests/lit-adapter.test.ts +0 -427
- package/src/client/tests/preact-adapter.test.ts +0 -353
- package/src/client/tests/qwik-adapter.test.ts +0 -343
- package/src/client/tests/react-adapter.test.ts +0 -317
- package/src/client/tests/solid-adapter.test.ts +0 -396
- package/src/client/tests/svelte-adapter.test.ts +0 -387
- package/src/client/tests/vue-adapter.test.ts +0 -407
- package/src/components/tests/component-analyzer.test.ts +0 -96
- package/src/components/tests/component-detection.test.ts +0 -347
- package/src/components/tests/persistent-islands.test.ts +0 -398
- package/src/core/components/tests/enhanced-framework-detector.test.ts +0 -577
- package/src/core/components/tests/framework-registry.test.ts +0 -465
- package/src/core/integrations/README.md +0 -282
- package/src/core/layout/tests/enhanced-layout-resolver.test.ts +0 -477
- package/src/core/layout/tests/layout-cache-optimization.test.ts +0 -149
- package/src/core/layout/tests/layout-composer.test.ts +0 -486
- package/src/core/layout/tests/layout-data-loader.test.ts +0 -443
- package/src/core/layout/tests/layout-discovery.test.ts +0 -253
- package/src/core/layout/tests/layout-matcher.test.ts +0 -480
- package/src/core/modules/tests/framework-module-resolver.test.ts +0 -263
- package/src/core/modules/tests/module-resolution-integration.test.ts +0 -117
- package/src/islands/discovery/tests/island-discovery.test.ts +0 -881
- package/src/middleware/__tests__/discovery.test.ts +0 -107
- package/src/types/tests/layout-types.test.ts +0 -197
- package/src/vite-plugin/tests/image-optimization.test.ts +0 -54
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Svelte HMR Adapter
|
|
3
|
-
*
|
|
4
|
-
* Verifies Svelte-specific HMR functionality including:
|
|
5
|
-
* - Component detection
|
|
6
|
-
* - State preservation
|
|
7
|
-
* - Svelte HMR runtime integration
|
|
8
|
-
* - Error handling
|
|
9
|
-
*
|
|
10
|
-
* Requirements: 2.4
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { describe, it, expect } from 'vitest';
|
|
14
|
-
import { SvelteHMRAdapter } from '../adapters/svelte-adapter.ts';
|
|
15
|
-
import type { StateSnapshot } from '../framework-adapter.ts';
|
|
16
|
-
|
|
17
|
-
// Mock HTMLElement for testing
|
|
18
|
-
class MockHTMLElement {
|
|
19
|
-
private attributes: Map<string, string> = new Map();
|
|
20
|
-
private _children: MockHTMLElement[] = [];
|
|
21
|
-
public scrollTop = 0;
|
|
22
|
-
public scrollLeft = 0;
|
|
23
|
-
public style: Record<string, string> = {};
|
|
24
|
-
|
|
25
|
-
getAttribute(name: string): string | null {
|
|
26
|
-
return this.attributes.get(name) || null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setAttribute(name: string, value: string): void {
|
|
30
|
-
this.attributes.set(name, value);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
removeAttribute(name: string): void {
|
|
34
|
-
this.attributes.delete(name);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
hasAttribute(name: string): boolean {
|
|
38
|
-
return this.attributes.has(name);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
querySelector(selector: string): MockHTMLElement | null {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
querySelectorAll(selector: string): MockHTMLElement[] {
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
contains(element: unknown): boolean {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
insertBefore(newNode: unknown, referenceNode: unknown): void {
|
|
54
|
-
// Mock implementation
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
get firstChild(): unknown {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
dispatchEvent(event: any): boolean {
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Mock Svelte components for testing
|
|
67
|
-
class MockSvelteComponent {
|
|
68
|
-
constructor(options: any) {
|
|
69
|
-
// Mock constructor
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
$set(props: Record<string, unknown>): void {
|
|
73
|
-
// Mock $set
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
$destroy(): void {
|
|
77
|
-
// Mock $destroy
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
$on(event: string, handler: (...args: unknown[]) => void): () => void {
|
|
81
|
-
return () => {};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
static $render = true; // Svelte SSR marker
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Mock Svelte component with prototype methods
|
|
88
|
-
function MockSvelteComponentFunction() {
|
|
89
|
-
// Mock component
|
|
90
|
-
}
|
|
91
|
-
MockSvelteComponentFunction.prototype.$set = function() {};
|
|
92
|
-
MockSvelteComponentFunction.prototype.$destroy = function() {};
|
|
93
|
-
MockSvelteComponentFunction.prototype.$ = {};
|
|
94
|
-
|
|
95
|
-
// Mock Svelte component with $$render (SSR marker)
|
|
96
|
-
const MockSvelteSSRComponent = {
|
|
97
|
-
$$render: true,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// Mock Svelte component with internal marker
|
|
101
|
-
const MockSvelteInternalComponent = function() {};
|
|
102
|
-
MockSvelteInternalComponent.toString = () => 'function() { $set(); $destroy(); }';
|
|
103
|
-
|
|
104
|
-
// Mock default export pattern
|
|
105
|
-
const MockSvelteDefaultExport = {
|
|
106
|
-
default: MockSvelteComponent,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
describe('SvelteHMRAdapter - initialization', () => {
|
|
110
|
-
it('should create adapter with correct name', () => {
|
|
111
|
-
const adapter = new SvelteHMRAdapter();
|
|
112
|
-
|
|
113
|
-
expect(adapter).toBeDefined();
|
|
114
|
-
expect(adapter.name).toBe('svelte');
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
describe('SvelteHMRAdapter - canHandle', () => {
|
|
119
|
-
it('should handle Svelte component class', () => {
|
|
120
|
-
const adapter = new SvelteHMRAdapter();
|
|
121
|
-
|
|
122
|
-
const result = adapter.canHandle(MockSvelteComponent);
|
|
123
|
-
expect(result).toBe(true);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should handle component with prototype methods', () => {
|
|
127
|
-
const adapter = new SvelteHMRAdapter();
|
|
128
|
-
|
|
129
|
-
const result = adapter.canHandle(MockSvelteComponentFunction);
|
|
130
|
-
expect(result).toBe(true);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should handle SSR component', () => {
|
|
134
|
-
const adapter = new SvelteHMRAdapter();
|
|
135
|
-
|
|
136
|
-
const result = adapter.canHandle(MockSvelteSSRComponent);
|
|
137
|
-
expect(result).toBe(true);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('should handle component with internal markers', () => {
|
|
141
|
-
const adapter = new SvelteHMRAdapter();
|
|
142
|
-
|
|
143
|
-
const result = adapter.canHandle(MockSvelteInternalComponent);
|
|
144
|
-
expect(result).toBe(true);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should handle default export', () => {
|
|
148
|
-
const adapter = new SvelteHMRAdapter();
|
|
149
|
-
|
|
150
|
-
const result = adapter.canHandle(MockSvelteDefaultExport);
|
|
151
|
-
expect(result).toBe(true);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it('should not handle non-Svelte component', () => {
|
|
155
|
-
const adapter = new SvelteHMRAdapter();
|
|
156
|
-
|
|
157
|
-
expect(adapter.canHandle(null)).toBe(false);
|
|
158
|
-
expect(adapter.canHandle(undefined)).toBe(false);
|
|
159
|
-
expect(adapter.canHandle('string')).toBe(false);
|
|
160
|
-
expect(adapter.canHandle(123)).toBe(false);
|
|
161
|
-
expect(adapter.canHandle({})).toBe(false);
|
|
162
|
-
expect(adapter.canHandle([])).toBe(false);
|
|
163
|
-
|
|
164
|
-
// Plain function without Svelte markers
|
|
165
|
-
const plainFunction = function() {};
|
|
166
|
-
expect(adapter.canHandle(plainFunction)).toBe(false);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
describe('SvelteHMRAdapter - preserveState', () => {
|
|
171
|
-
it('should return valid snapshot', () => {
|
|
172
|
-
const adapter = new SvelteHMRAdapter();
|
|
173
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
174
|
-
|
|
175
|
-
// Set up mock island attributes
|
|
176
|
-
mockIsland.setAttribute('data-src', '/islands/Counter.svelte');
|
|
177
|
-
mockIsland.setAttribute('data-props', JSON.stringify({ count: 5 }));
|
|
178
|
-
|
|
179
|
-
const snapshot = adapter.preserveState(mockIsland);
|
|
180
|
-
|
|
181
|
-
// In test environment without DOM, preserveState returns null
|
|
182
|
-
// This is expected behavior - the adapter gracefully handles missing DOM
|
|
183
|
-
if (snapshot) {
|
|
184
|
-
expect(snapshot.framework).toBe('svelte');
|
|
185
|
-
expect(typeof snapshot.timestamp).toBe('number');
|
|
186
|
-
expect(snapshot.data).toBeDefined();
|
|
187
|
-
} else {
|
|
188
|
-
// Graceful degradation when DOM is not available
|
|
189
|
-
expect(snapshot).toBeNull();
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('should capture component name', () => {
|
|
194
|
-
const adapter = new SvelteHMRAdapter();
|
|
195
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
196
|
-
|
|
197
|
-
mockIsland.setAttribute('data-src', '/islands/Button.svelte');
|
|
198
|
-
mockIsland.setAttribute('data-props', '{}');
|
|
199
|
-
|
|
200
|
-
const snapshot = adapter.preserveState(mockIsland);
|
|
201
|
-
|
|
202
|
-
// In test environment without DOM, preserveState returns null
|
|
203
|
-
if (snapshot) {
|
|
204
|
-
expect(snapshot.data.componentName).toBe('Button');
|
|
205
|
-
} else {
|
|
206
|
-
// Expected in test environment
|
|
207
|
-
expect(snapshot).toBeNull();
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('should capture props', () => {
|
|
212
|
-
const adapter = new SvelteHMRAdapter();
|
|
213
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
214
|
-
|
|
215
|
-
const props = { count: 10, name: 'test' };
|
|
216
|
-
mockIsland.setAttribute('data-src', '/islands/Counter.svelte');
|
|
217
|
-
mockIsland.setAttribute('data-props', JSON.stringify(props));
|
|
218
|
-
|
|
219
|
-
const snapshot = adapter.preserveState(mockIsland);
|
|
220
|
-
|
|
221
|
-
// In test environment without DOM, preserveState returns null
|
|
222
|
-
if (snapshot) {
|
|
223
|
-
expect(snapshot.data.capturedProps).toBeDefined();
|
|
224
|
-
expect(snapshot.data.capturedProps).toEqual(props);
|
|
225
|
-
} else {
|
|
226
|
-
// Expected in test environment
|
|
227
|
-
expect(snapshot).toBeNull();
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
it('should handle missing props', () => {
|
|
232
|
-
const adapter = new SvelteHMRAdapter();
|
|
233
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
234
|
-
|
|
235
|
-
mockIsland.setAttribute('data-src', '/islands/Counter.svelte');
|
|
236
|
-
// No data-props attribute
|
|
237
|
-
|
|
238
|
-
const snapshot = adapter.preserveState(mockIsland);
|
|
239
|
-
|
|
240
|
-
// In test environment without DOM, preserveState returns null
|
|
241
|
-
if (snapshot) {
|
|
242
|
-
expect(snapshot.data.capturedProps).toBeDefined();
|
|
243
|
-
expect(Object.keys(snapshot.data.capturedProps || {}).length).toBe(0);
|
|
244
|
-
} else {
|
|
245
|
-
// Expected in test environment
|
|
246
|
-
expect(snapshot).toBeNull();
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('should handle invalid JSON props', () => {
|
|
251
|
-
const adapter = new SvelteHMRAdapter();
|
|
252
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
253
|
-
|
|
254
|
-
mockIsland.setAttribute('data-src', '/islands/Counter.svelte');
|
|
255
|
-
mockIsland.setAttribute('data-props', 'invalid json');
|
|
256
|
-
|
|
257
|
-
const snapshot = adapter.preserveState(mockIsland);
|
|
258
|
-
|
|
259
|
-
// Should return null on error
|
|
260
|
-
expect(snapshot).toBeNull();
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
describe('SvelteHMRAdapter - restoreState', () => {
|
|
265
|
-
it('should call base implementation', () => {
|
|
266
|
-
const adapter = new SvelteHMRAdapter();
|
|
267
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
268
|
-
|
|
269
|
-
const snapshot: StateSnapshot = {
|
|
270
|
-
framework: 'svelte',
|
|
271
|
-
timestamp: Date.now(),
|
|
272
|
-
data: {},
|
|
273
|
-
dom: {
|
|
274
|
-
scrollPosition: { x: 50, y: 100 },
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
// Should not throw
|
|
279
|
-
adapter.restoreState(mockIsland, snapshot);
|
|
280
|
-
|
|
281
|
-
// Verify DOM state was restored
|
|
282
|
-
expect(mockIsland.scrollLeft).toBe(50);
|
|
283
|
-
expect(mockIsland.scrollTop).toBe(100);
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
describe('SvelteHMRAdapter - handleError', () => {
|
|
288
|
-
it('should add Svelte-specific error info', () => {
|
|
289
|
-
const adapter = new SvelteHMRAdapter();
|
|
290
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
291
|
-
|
|
292
|
-
const error = new Error('Invalid reactive statement');
|
|
293
|
-
|
|
294
|
-
// In test environment without DOM, handleError may fail
|
|
295
|
-
// This is expected - the adapter requires DOM APIs
|
|
296
|
-
try {
|
|
297
|
-
adapter.handleError(mockIsland, error);
|
|
298
|
-
|
|
299
|
-
// If it succeeds, verify error attributes were set
|
|
300
|
-
expect(mockIsland.getAttribute('data-hmr-error')).toBe('true');
|
|
301
|
-
expect(mockIsland.getAttribute('data-hmr-error-message')).toBe('Invalid reactive statement');
|
|
302
|
-
} catch (e) {
|
|
303
|
-
// Expected in test environment without DOM
|
|
304
|
-
// Accept any error - the important thing is it doesn't crash silently
|
|
305
|
-
expect(e).toBeDefined();
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
it('should provide reactive hint', () => {
|
|
310
|
-
const adapter = new SvelteHMRAdapter();
|
|
311
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
312
|
-
|
|
313
|
-
const error = new Error('$: must be at component top level');
|
|
314
|
-
|
|
315
|
-
// The adapter should recognize reactive-related errors and provide helpful hints
|
|
316
|
-
// This is tested indirectly through the error message
|
|
317
|
-
try {
|
|
318
|
-
adapter.handleError(mockIsland, error);
|
|
319
|
-
} catch (e) {
|
|
320
|
-
// Expected in test environment
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// The actual hint is added to the error indicator element
|
|
324
|
-
// which requires full DOM support to test properly
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
it('should provide store hint', () => {
|
|
328
|
-
const adapter = new SvelteHMRAdapter();
|
|
329
|
-
const mockIsland = new MockHTMLElement() as unknown as HTMLElement;
|
|
330
|
-
|
|
331
|
-
const error = new Error('store subscription failed');
|
|
332
|
-
|
|
333
|
-
// The adapter should recognize store-related errors and provide helpful hints
|
|
334
|
-
try {
|
|
335
|
-
adapter.handleError(mockIsland, error);
|
|
336
|
-
} catch (e) {
|
|
337
|
-
// Expected in test environment
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
describe('SvelteHMRAdapter - extractComponentName', () => {
|
|
343
|
-
it('should extract from various paths', () => {
|
|
344
|
-
const adapter = new SvelteHMRAdapter();
|
|
345
|
-
|
|
346
|
-
// Access private method through type assertion for testing
|
|
347
|
-
const extractName = (adapter as any).extractComponentName.bind(adapter);
|
|
348
|
-
|
|
349
|
-
expect(extractName('/islands/Counter.svelte')).toBe('Counter');
|
|
350
|
-
expect(extractName('/islands/Button.svelte')).toBe('Button');
|
|
351
|
-
expect(extractName('/src/components/Card.svelte')).toBe('Card');
|
|
352
|
-
expect(extractName('/nested/path/Component.svelte')).toBe('Component');
|
|
353
|
-
expect(extractName('SimpleComponent.svelte')).toBe('SimpleComponent');
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
describe('SvelteHMRAdapter - generateComponentId', () => {
|
|
358
|
-
it('should create valid ID', () => {
|
|
359
|
-
const adapter = new SvelteHMRAdapter();
|
|
360
|
-
|
|
361
|
-
// Access private method through type assertion for testing
|
|
362
|
-
const generateId = (adapter as any).generateComponentId.bind(adapter);
|
|
363
|
-
|
|
364
|
-
const id1 = generateId('/islands/Counter.svelte');
|
|
365
|
-
const id2 = generateId('/islands/Button.svelte');
|
|
366
|
-
const id3 = generateId('/src/components/Card.svelte');
|
|
367
|
-
|
|
368
|
-
// IDs should be valid (no special characters)
|
|
369
|
-
expect(id1.match(/^[a-zA-Z0-9_]+$/) !== null).toBe(true);
|
|
370
|
-
expect(id2.match(/^[a-zA-Z0-9_]+$/) !== null).toBe(true);
|
|
371
|
-
expect(id3.match(/^[a-zA-Z0-9_]+$/) !== null).toBe(true);
|
|
372
|
-
|
|
373
|
-
// Same path should generate same ID
|
|
374
|
-
expect(generateId('/islands/Counter.svelte')).toBe(id1);
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
describe('SvelteHMRAdapter - singleton instance', () => {
|
|
379
|
-
it('should export singleton', async () => {
|
|
380
|
-
// Import the singleton
|
|
381
|
-
const { svelteAdapter } = await import('../adapters/svelte-adapter.ts');
|
|
382
|
-
|
|
383
|
-
expect(svelteAdapter).toBeDefined();
|
|
384
|
-
expect(svelteAdapter.name).toBe('svelte');
|
|
385
|
-
expect(svelteAdapter instanceof SvelteHMRAdapter).toBe(true);
|
|
386
|
-
});
|
|
387
|
-
});
|