appblocks
Version:
A lightweight javascript library for building micro apps for the front-end.
251 lines (215 loc) • 8.15 kB
JavaScript
import { AppBlock } from 'src/core.js';
import { createMockAppBlockConfig, createMockTemplate, resetDOM } from 'tests/fixtures/mockData.js';
describe('asHTML filter', () => {
afterEach(() => resetDOM());
test('should render HTML content when using asHTML filter', () => {
const tpl = createMockTemplate('<div>{data.content|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { content: '<strong>Bold</strong> text' }
});
const app = new AppBlock(config);
const strong = app.el.querySelector('strong');
expect(strong).not.toBeNull();
expect(strong.textContent).toBe('Bold');
});
test('should render plain text without asHTML filter', () => {
const tpl = createMockTemplate('<div>{data.content}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { content: '<strong>Bold</strong> text' }
});
const app = new AppBlock(config);
// Should render as escaped text, not HTML
expect(app.el.textContent).toContain('<strong>Bold</strong>');
const strong = app.el.querySelector('strong');
expect(strong).toBeNull();
});
test('should render multiple HTML elements with asHTML', () => {
const tpl = createMockTemplate('<div>{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { html: '<p>Paragraph 1</p><p>Paragraph 2</p><span>Span</span>' }
});
const app = new AppBlock(config);
const paragraphs = app.el.querySelectorAll('p');
expect(paragraphs.length).toBe(2);
expect(paragraphs[0].textContent).toBe('Paragraph 1');
expect(paragraphs[1].textContent).toBe('Paragraph 2');
const span = app.el.querySelector('span');
expect(span).not.toBeNull();
expect(span.textContent).toBe('Span');
});
test('should render HTML with attributes using asHTML', () => {
const tpl = createMockTemplate('<div>{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { html: '<div class="test-class" id="test-id">Content</div>' }
});
const app = new AppBlock(config);
const inserted = app.el.querySelector('.test-class');
expect(inserted).not.toBeNull();
expect(inserted.id).toBe('test-id');
expect(inserted.textContent).toBe('Content');
});
test('should handle nested HTML with asHTML', () => {
const tpl = createMockTemplate('<div>{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: {
html: '<div><p><strong>Nested</strong> <em>HTML</em></p></div>'
}
});
const app = new AppBlock(config);
const strong = app.el.querySelector('strong');
const em = app.el.querySelector('em');
expect(strong).not.toBeNull();
expect(em).not.toBeNull();
expect(strong.textContent).toBe('Nested');
expect(em.textContent).toBe('HTML');
});
test('should handle empty string with asHTML', () => {
const tpl = createMockTemplate('<div id="container">{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { html: '' }
});
const app = new AppBlock(config);
const container = app.el.querySelector('#container');
expect(container.innerHTML.trim()).toBe('');
});
test('should handle plain text with asHTML', () => {
const tpl = createMockTemplate('<div>{data.text|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { text: 'Just plain text' }
});
const app = new AppBlock(config);
expect(app.el.textContent.trim()).toBe('Just plain text');
});
test('should work with asHTML in c-for loops', () => {
const tpl = createMockTemplate(`
<div c-for="item in data.items">
{item.html|asHTML}
</div>
`);
const config = createMockAppBlockConfig({
template: tpl,
data: {
items: [
{ html: '<span class="item1">Item 1</span>' },
{ html: '<span class="item2">Item 2</span>' }
]
}
});
const app = new AppBlock(config);
const item1 = app.el.querySelector('.item1');
const item2 = app.el.querySelector('.item2');
expect(item1).not.toBeNull();
expect(item2).not.toBeNull();
expect(item1.textContent).toBe('Item 1');
expect(item2.textContent).toBe('Item 2');
});
test('should chain filters before asHTML', () => {
const tpl = createMockTemplate('<div>{data.tag|wrapTag|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { tag: 'content' },
filters: {
wrapTag: (comp, v) => `<strong>${v}</strong>`
}
});
const app = new AppBlock(config);
const strong = app.el.querySelector('strong');
expect(strong).not.toBeNull();
expect(strong.textContent).toBe('content');
});
test('should handle asHTML with other filters in chain', () => {
const tpl = createMockTemplate('<div>{data.name|uppercase|toTag|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { name: 'hello' },
filters: {
uppercase: (comp, v) => String(v).toUpperCase(),
toTag: (comp, v) => `<em>${v}</em>`
}
});
const app = new AppBlock(config);
const em = app.el.querySelector('em');
expect(em).not.toBeNull();
expect(em.textContent).toBe('HELLO');
});
test('should update HTML when data changes', () => {
const tpl = createMockTemplate('<div>{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { html: '<span class="original">Original</span>' }
});
const app = new AppBlock(config);
let span = app.el.querySelector('.original');
expect(span).not.toBeNull();
expect(span.textContent).toBe('Original');
// Update data
app.data.html = '<span class="updated">Updated</span>';
app.render();
span = app.el.querySelector('.updated');
expect(span).not.toBeNull();
expect(span.textContent).toBe('Updated');
// Original should be gone
const original = app.el.querySelector('.original');
expect(original).toBeNull();
});
test('should handle self-closing tags with asHTML', () => {
const tpl = createMockTemplate('<div>{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { html: '<img src="test.jpg" alt="Test"><br><hr>' }
});
const app = new AppBlock(config);
const img = app.el.querySelector('img');
const br = app.el.querySelector('br');
const hr = app.el.querySelector('hr');
expect(img).not.toBeNull();
expect(br).not.toBeNull();
expect(hr).not.toBeNull();
expect(img.getAttribute('src')).toBe('test.jpg');
});
test('should handle special characters in HTML with asHTML', () => {
const tpl = createMockTemplate('<div>{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: { html: '<p><script> & special chars</p>' }
});
const app = new AppBlock(config);
const p = app.el.querySelector('p');
expect(p).not.toBeNull();
expect(p.innerHTML).toContain('<script>');
});
test('should handle complex HTML structure with asHTML', () => {
const tpl = createMockTemplate('<div>{data.html|asHTML}</div>');
const config = createMockAppBlockConfig({
template: tpl,
data: {
html: `
<article>
<h1>Title</h1>
<p>Paragraph with <a href="#link">link</a></p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</article>
`
}
});
const app = new AppBlock(config);
const article = app.el.querySelector('article');
const h1 = app.el.querySelector('h1');
const link = app.el.querySelector('a');
const items = app.el.querySelectorAll('li');
expect(article).not.toBeNull();
expect(h1.textContent).toBe('Title');
expect(link.getAttribute('href')).toBe('#link');
expect(items.length).toBe(2);
});
});