UNPKG

lupine.web

Version:

lupine.web is a extremely fast, small size and lightweight frontend framework, using React TSX syntax.

96 lines (77 loc) 3.65 kB
import './export-lupine'; import { describe, it, mock, beforeEach, afterEach } from 'node:test'; import assert from 'node:assert/strict'; import { ComponentStateStore, evaluateComponentWithStore, getCurrentStore, useState } from './use-state'; import { domUniqueId } from './render-attribute'; describe('use-state Core Engine', () => { beforeEach(() => { mock.method(Date, 'now', () => 1775190809080); domUniqueId(true); // wipe cleanly }); afterEach(() => { mock.restoreAll(); }); describe('evaluateComponentWithStore', () => { it('should successfully evaluate a synchronous component and return VNode', async () => { const SyncComp = (props: { text: string }) => { return { type: 'div', props: { children: [props.text] } }; }; const store = new ComponentStateStore(SyncComp, { text: 'Sync World' }); const result = await evaluateComponentWithStore(store); assert.equal(result.type, 'div'); assert.deepEqual(result.props.children, ['Sync World']); }); it('should successfully evaluate an asynchronous component and return VNode', async () => { const AsyncComp = async (props: { text: string }) => { await new Promise(r => setTimeout(r, 1)); // simulate async return { type: 'span', props: { children: [props.text] } }; }; const store = new ComponentStateStore(AsyncComp, { text: 'Async World' }); const result = await evaluateComponentWithStore(store); assert.equal(result.type, 'span'); assert.deepEqual(result.props.children, ['Async World']); }); it('should set and clear the global currentStore during execution', async () => { let storeInsideComp: any = undefined; const TestComp = () => { storeInsideComp = getCurrentStore(); return { type: 'div', props: {} }; }; assert.equal(getCurrentStore(), null); // Before const store = new ComponentStateStore(TestComp, {}); await evaluateComponentWithStore(store); assert.equal(storeInsideComp, store); // Inside component: pointer should be active assert.equal(getCurrentStore(), null); // After evaluation: pointer must be cleared }); it('should inject ref wrapper onto VNode if a hook is used', async () => { const HookComp = () => { useState(0); // This sets store.hookIndex > 0 return { type: 'section', props: { 'data-id': 'hooked' } }; }; const store = new ComponentStateStore(HookComp, {}); const result = await evaluateComponentWithStore(store); // The returned VNode should now have a ref object generated by buildStateRef assert.ok(result.props.ref, 'Ref should be injected because a hook was used'); assert.equal(typeof result.props.ref.onLoad, 'function'); assert.equal(typeof result.props.ref.refresh, 'function'); }); it('should inject ref wrapper onto VNode if user already passed a ref', async () => { const userRef = { current: null, referToCssId: 'test-global-css' }; const RefComp = () => { // No hook used here, but user passes an existing ref return { type: 'div', props: { ref: userRef } }; }; const store = new ComponentStateStore(RefComp, {}); const result = await evaluateComponentWithStore(store); assert.ok(result.props.ref); assert.equal(result.props.ref, userRef, 'It should merge into the original user ref object'); assert.equal(result.props.ref.referToCssId, 'test-global-css'); assert.equal(typeof result.props.ref.onLoad, 'function', 'Wrapper added successfully'); }); }); });