import { h, render, mount, mountReadyCallback, nextTick } from '@/index'; // Test basic mountReadyCallback execution const basicExecutionLog: string[] = []; const BasicCallbackComponent = mount(() => { mountReadyCallback(() => { basicExecutionLog.push('callback-executed'); }); return () =>
Basic Test
; }); // Test callback execution order with nested components const callbackOrder: string[] = []; const NestedChild = mount(() => { mountReadyCallback(() => { callbackOrder.push('child'); }); return () =>
Child
; }); const NestedParent = mount(() => { mountReadyCallback(() => { callbackOrder.push('parent'); }); return () => (
Parent
); }); // Test cleanup function return const cleanupLog: string[] = []; const CleanupChild = mount(() => { mountReadyCallback(() => { cleanupLog.push('mounted'); return () => { cleanupLog.push('cleanup'); }; }); return () =>
Cleanup Child
; }); const CleanupComponent = mount(renew => { let mounted = true; const toggle = () => { mounted = !mounted; renew(); }; return () => (
{mounted && }
); }); // Test multiple callbacks in single component const multiCallbackLog: string[] = []; const MultiCallbackComponent = mount(() => { mountReadyCallback(() => { multiCallbackLog.push('callback-1'); }); mountReadyCallback(() => { multiCallbackLog.push('callback-2'); }); mountReadyCallback(() => { multiCallbackLog.push('callback-3'); }); return () =>
Multi Callback Test
; }); // Test callback execution before DOM rendering const executionTimingLog: string[] = []; const TimingTestChild = mount(() => { mountReadyCallback(() => { const element = document.querySelector('.timing-child'); executionTimingLog.push(element ? 'dom-exists' : 'dom-not-exists'); }); return () =>
Timing Child
; }); const TimingTestParent = mount(() => { return () => (
); }); // Test with dynamic component mounting const dynamicLog: string[] = []; const DynamicChild = mount<{ id: number }>(() => { mountReadyCallback(() => { dynamicLog.push(`child-${Math.random().toString(36).substr(2, 4)}`); }); return props =>
Child {props.id}
; }); const DynamicParent = mount(renew => { let showSecond = false; const addChild = () => { showSecond = true; renew(); }; return () => (
{showSecond && }
); }); const testWrap = document.getElementById('root') || document.createElement('div'); if (import.meta.vitest) { const { it, expect, beforeEach } = import.meta.vitest; beforeEach(() => { // Clear all logs before each test basicExecutionLog.length = 0; callbackOrder.length = 0; cleanupLog.length = 0; multiCallbackLog.length = 0; executionTimingLog.length = 0; dynamicLog.length = 0; testWrap.innerHTML = ''; }); it('Basic mountReadyCallback should execute after WDom creation', async () => { const container = document.createElement('div'); expect(basicExecutionLog.length).toBe(0); render(, container); await nextTick(); expect(basicExecutionLog).toContain('callback-executed'); expect(basicExecutionLog.length).toBe(1); }); it('Nested components should execute callbacks in creation order', async () => { const container = document.createElement('div'); render(, container); await nextTick(); expect(callbackOrder).toEqual(['parent', 'child']); }); it('Cleanup function should be called on unmount', async () => { const container = document.createElement('div'); render(, container); await nextTick(); expect(cleanupLog).toContain('mounted'); const toggleBtn = container.querySelector( '.toggle-btn' ) as HTMLButtonElement; toggleBtn?.click(); await nextTick(); expect(cleanupLog).toContain('cleanup'); }); it('Multiple callbacks in single component should all execute', async () => { const container = document.createElement('div'); render(, container); await nextTick(); expect(multiCallbackLog).toEqual([ 'callback-1', 'callback-2', 'callback-3', ]); }); it('Callback should execute before DOM rendering', async () => { const container = document.createElement('div'); render(, container); await nextTick(); // mountReadyCallback executes after WDom creation but before DOM rendering // so DOM element should not exist yet during callback execution expect(executionTimingLog[0]).toBe('dom-not-exists'); }); it('Dynamically added components should trigger callbacks', async () => { const container = document.createElement('div'); render(, container); await nextTick(); const initialCount = dynamicLog.length; expect(initialCount).toBe(1); // Only first child const addButton = container.querySelector( '.add-child-btn' ) as HTMLButtonElement; addButton?.click(); await nextTick(); expect(dynamicLog.length).toBe(2); // First + second child }); it('Should handle callback with conditional rendering', async () => { const container = document.createElement('div'); const conditionalLog: string[] = []; const ConditionalChild = mount(() => { mountReadyCallback(() => { conditionalLog.push('child-mounted'); return () => { conditionalLog.push('child-unmounted'); }; }); return () =>
Conditional
; }); const ConditionalParent = mount(renew => { let show = true; const toggle = () => { show = !show; renew(); }; return () => (
{show && }
); }); render(, container); await nextTick(); expect(conditionalLog).toContain('child-mounted'); const toggleBtn = container.querySelector('.toggle') as HTMLButtonElement; toggleBtn?.click(); await nextTick(); expect(conditionalLog).toContain('child-unmounted'); toggleBtn?.click(); await nextTick(); // Should mount again expect(conditionalLog.filter(log => log === 'child-mounted').length).toBe( 2 ); }); }