test: update and add tests for all updated subsystems
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import { reactive, h, html, render, Router, Link } from '../webui/static/reactive-dom.js';
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` ✓ ${name}`);
|
||||
passed++;
|
||||
} catch (e) {
|
||||
console.error(` ✗ ${name}: ${e.message}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
function assert(cond, msg) {
|
||||
if (!cond) throw new Error(msg || 'Assertion failed');
|
||||
}
|
||||
|
||||
console.log('Testing reactive-dom.js\n');
|
||||
|
||||
// === Reactive ===
|
||||
test('reactive() returns proxy', () => {
|
||||
const s = reactive({ x: 1 });
|
||||
assert(s.x === 1);
|
||||
});
|
||||
|
||||
test('reactive() mutation triggers render callback', () => {
|
||||
const s = reactive({ x: 1 });
|
||||
let fired = false;
|
||||
// We can't easily test the render callback without a DOM, but we can check the proxy works
|
||||
s.x = 2;
|
||||
assert(s.x === 2);
|
||||
});
|
||||
|
||||
// === h() ===
|
||||
test('h() creates element VNode', () => {
|
||||
const v = h('div', { class: 'foo' });
|
||||
assert(v.tag === 'div' && v.props.class === 'foo');
|
||||
});
|
||||
|
||||
test('h() flattens children array', () => {
|
||||
const v = h('div', null, h('span', null, 'hi'));
|
||||
assert(v.ch.length === 1 && v.ch[0].tag === 'span');
|
||||
});
|
||||
|
||||
test('h() converts strings to text nodes', () => {
|
||||
const v = h('div', null, 'hello', 42);
|
||||
assert(v.ch.length === 2 && v.ch[0].tag === '#text' && v.ch[0].text === 'hello');
|
||||
assert(v.ch[1].text === '42');
|
||||
});
|
||||
|
||||
test('h() drops null/boolean children', () => {
|
||||
const v = h('div', null, null, undefined, true, false, 'x');
|
||||
assert(v.ch.length === 1 && v.ch[0].text === 'x');
|
||||
});
|
||||
|
||||
// === html() ===
|
||||
test('html() parses static element', () => {
|
||||
const nodes = html`<div>hello</div>`;
|
||||
assert(nodes[0].tag === 'div' && nodes[0].ch[0].text === 'hello');
|
||||
});
|
||||
|
||||
test('html() interpolates text into element children', () => {
|
||||
const name = 'World';
|
||||
const nodes = html`<div>Hello ${name}</div>`;
|
||||
assert(nodes[0].tag === 'div');
|
||||
// Should have: text "Hello ", then text "World"
|
||||
assert(nodes[0].ch[0].text && nodes[0].ch[0].text === 'Hello ');
|
||||
assert(nodes[0].ch[1].tag === '#text' && nodes[0].ch[1].text === 'World');
|
||||
});
|
||||
|
||||
test('html() interpolates class attribute value', () => {
|
||||
const cls = 'active';
|
||||
const nodes = html`<div class="${cls}">x</div>`;
|
||||
assert(nodes[0].tag === 'div' && nodes[0].props.class === 'active');
|
||||
});
|
||||
|
||||
test('html() interpolates on:click attribute value', () => {
|
||||
const handler = function click() {};
|
||||
const nodes = html`<button on:click="${handler}">Go</button>`;
|
||||
assert(nodes[0].tag === 'button' && typeof nodes[0].props['on:click'] === 'function');
|
||||
});
|
||||
|
||||
test('html() handles multiple interpolations', () => {
|
||||
const a = 'first', b = 'second';
|
||||
const nodes = html`<div><span>${a}</span> <span>${b}</span></div>`;
|
||||
assert(nodes[0].tag === 'div');
|
||||
assert(nodes[0].ch[0].tag === 'span' && nodes[0].ch[0].ch[0].text === 'first');
|
||||
});
|
||||
|
||||
test('html() interpolates VNode into element children', () => {
|
||||
const nodes = html`<ul>${html`<li>item</li>`[0]}</ul>`;
|
||||
assert(nodes[0].tag === 'ul' && nodes[0].ch[0].tag === 'li');
|
||||
});
|
||||
|
||||
// === Router ===
|
||||
test('Router initializes with current hash', () => {
|
||||
globalThis.location = { hash: '' };
|
||||
globalThis.window = { addEventListener: () => {} };
|
||||
const router = Router({ '/home': () => {} });
|
||||
assert(router.state.path === '/');
|
||||
});
|
||||
|
||||
// === Link ===
|
||||
test('Link creates anchor with hash href', () => {
|
||||
const link = Link({ path: '/dashboard' });
|
||||
assert(link.tag === 'a' && link.props.href === '#/dashboard');
|
||||
});
|
||||
|
||||
// === DOM functions (basic, no actual DOM) ===
|
||||
test('createDom produces document.createElement call', () => {
|
||||
const v = h('div', { class: 'foo' }, 'hi', h('span', null, 'nested'));
|
||||
// Can't test actual DOM without jsdom, but we can verify the VNode structure
|
||||
assert(v.tag === 'div' && v.ch.length === 2);
|
||||
});
|
||||
|
||||
console.log(`\n${passed} passed, ${failed} failed`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
Reference in New Issue
Block a user