lupine.web
Version:
lupine.web is a extremely fast, small size and lightweight frontend framework, using React TSX syntax.
88 lines (75 loc) • 3.83 kB
text/typescript
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { renderAttribute, genUniqueId } from './render-attribute';
import { uniqueIdGenerator } from '../lib/unique-id';
describe('renderAttribute', () => {
it('should generate a tag ID if missing and return the same ID subsequently', () => {
const props: any = {};
const id = genUniqueId(props);
assert.equal(typeof id, 'string');
assert.ok(id.length > 0);
assert.equal(props._id, id);
assert.equal(genUniqueId(props), id, 'Should reuse existing _id');
});
it('should filter out internal props like children, key, _result, _html', () => {
const props = { children: [], key: '123', _result: {}, _html: [], name: 'test' };
const result = renderAttribute('div', props, null);
assert.ok(!result.includes('children'));
assert.ok(!result.includes('key='));
assert.ok(result.includes('name="test"'));
});
it('should render inline style object efficiently via camelToHyphens', () => {
const props = { style: { backgroundColor: 'red', fontSize: '12px' } };
const result = renderAttribute('div', props, null);
assert.ok(result.includes('style="background-color:red;font-size:12px;"'));
});
it('should render style as a string directly if not an object', () => {
const props = { style: 'color: blue;' };
const result = renderAttribute('div', props, null);
assert.ok(result.includes('style="color: blue;"'));
});
it('should generate an ID for css and event handlers (onXXX)', () => {
const props1: any = { css: 'body { color: red; }' };
renderAttribute('div', props1, null);
assert.ok(props1._id);
const props2: any = { onClick: () => { } };
renderAttribute('button', props2, null);
assert.ok(props2._id);
});
it('should convert boolean attributes correctly', () => {
const props: any = { defaultChecked: true, readonly: true, disabled: false, selected: 'selected' };
const result = renderAttribute('input', props, null);
assert.ok(result.includes('checked="true"'));
assert.ok(result.includes('readonly="true"'));
assert.ok(!result.includes('disabled='));
assert.ok(result.includes('selected="selected"'));
});
it('should assign a ref ID and inject data-ref marker', () => {
const fakeRef: any = { id: '' };
const props: any = { ref: fakeRef };
const result = renderAttribute('div', props, null);
assert.ok(result.includes('data-ref'), 'Should contain data-ref marker');
assert.ok(fakeRef.id, 'Should inject _id into ref');
assert.equal(fakeRef.id, props._id);
});
it('should append unique marker automatically when css is present', () => {
const props: any = { class: 'my-class', css: 'body { }' };
genUniqueId(props);
const result = renderAttribute('div', props, null);
// Because css is present, props._id should be injected as the first class
assert.ok(result.includes(`class="${props._id} my-class"`));
});
it('should resolve ampersand & markers in classes with referToCssId and uniqueClassName', () => {
const props = { class: 'btn &-active' };
// Just testing string replacement logic for global CSS
const result = renderAttribute('div', props, null, 'unique123', 'global456');
// & resolves to both global and unique if both present
assert.ok(result.includes('class="btn global456-active unique123-active"'));
});
it('should resolve ampersand & markers with only global or only unique prefixes', () => {
let result = renderAttribute('div', { class: '&-hover' }, null, undefined, 'global-only');
assert.ok(result.includes('class="global-only-hover"'));
result = renderAttribute('div', { class: '&-hover' }, null, 'unique-only', undefined);
assert.ok(result.includes('class="unique-only-hover"'));
});
});