// test/dom.test.js
window.testDom = async function() {
console.log('Testing dom.js...');
const wait = () => new Promise(r => setTimeout(r, 10));
// 1. Basic $text binding
document.body.innerHTML = '
';
const state = NewState({ msg: 'hello' });
window.state = state; // TRY: 确保在非 ESM 环境下 state 全局可见
document.documentElement._thisObj = { state };
globalThis._unsafeRefreshState(document.documentElement);
if ($('#test-text').textContent !== 'hello') throw new Error('$text binding failed');
state.msg = 'world';
await wait();
if ($('#test-text').textContent !== 'world') throw new Error('$text update failed');
// 2. $if directive
document.body.innerHTML = 'visible
';
state.show = false;
globalThis._unsafeRefreshState(document.documentElement);
if ($('#test-if')) throw new Error('$if fail: should be hidden');
state.show = true;
await wait();
if (!$('#test-if')) throw new Error('$if fail: should be visible');
// 3. $each directive
document.body.innerHTML = '';
state.items = ['A', 'B'];
globalThis._unsafeRefreshState(document.documentElement);
await wait(); // Wait for MutationObserver or next pass
if ($$('.test-item').length !== 2) throw new Error('$each fail: count mismatch');
if ($$('.test-item')[0].textContent !== 'A') throw new Error('$each fail: content mismatch');
state.items = ['A', 'B', 'C'];
await wait();
if ($$('.test-item').length !== 3) throw new Error('$each update fail');
// 4. Event binding $onclick
document.body.innerHTML = '';
state.count = 0;
globalThis._unsafeRefreshState(document.documentElement);
$('#test-click').click();
if (state.count !== 1) throw new Error('$onclick failed');
// 5. $bind (input)
document.body.innerHTML = '';
state.val = 'init';
globalThis._unsafeRefreshState(document.documentElement);
await wait(); // TRY: 等待 $bind 的 setTimeout 完成
const input = $('#test-bind');
if (input.value !== 'init') throw new Error('$bind initial failed');
input.value = 'changed';
input.dispatchEvent(new Event('input'));
if (state.val !== 'changed') throw new Error('$bind writeback failed');
// 6. Double evaluation ($$ prefix)
console.log('Testing double evaluation ($$)...');
document.body.innerHTML = `
`;
const doubleState = NewState({
innerExp: 'state.innerShow',
innerShow: false
});
window.state = doubleState;
const root = $('#double-eval-root');
root._thisObj = { state: doubleState };
globalThis._unsafeRefreshState(root);
await wait();
if ($('#inner-node')) throw new Error('$$if failed: should be hidden initially');
console.log('Enabling inner node...');
doubleState.innerShow = true;
globalThis._unsafeRefreshState(root);
await wait();
const inner = $('#inner-node');
if (!inner) throw new Error('$$if failed: should be visible after innerShow=true');
// 7. Nested $$if
console.log('Testing nested $$if...');
document.body.innerHTML = `
`;
const nestedRoot = $('#nested-double-test');
nestedRoot._thisObj = { state: doubleState };
doubleState.outer = true;
doubleState.innerShow = false;
globalThis._unsafeRefreshState(nestedRoot);
await wait();
if ($('#nested-inner')) throw new Error('nested $$if failed: should be hidden initially');
doubleState.innerShow = true;
globalThis._unsafeRefreshState(nestedRoot);
await wait();
if (!$('#nested-inner')) throw new Error('nested $$if failed: should be visible after update');
console.log('dom.js tests passed');
return true;
}