import { describe, it, expect, beforeAll, afterEach } from 'vitest'
import TemplateFactory from '../../../src/bootstrap/util/template-factory'
import { clearFixture, getFixture } from '../../helpers/fixture'
describe('TemplateFactory', () => {
let fixtureEl: HTMLElement
beforeAll(() => {
fixtureEl = getFixture()
})
afterEach(() => {
clearFixture()
})
describe('NAME', () => {
it('should return plugin NAME', () => {
expect(TemplateFactory.NAME).toBe('TemplateFactory')
})
})
describe('Default', () => {
it('should return plugin default config', () => {
expect(typeof TemplateFactory.Default).toBe('object')
})
})
describe('toHtml', () => {
describe('Sanitization', () => {
it('should sanitize template by default', () => {
const factory = new TemplateFactory({
sanitize: true,
template: '
',
})
expect(factory.toHtml().innerHTML).not.toContain('href="javascript:alert(7)')
})
it('should not sanitize template if disabled', () => {
const factory = new TemplateFactory({
sanitize: false,
template: '',
})
expect(factory.toHtml().innerHTML).toContain('href="javascript:alert(7)')
})
it('should sanitize html content', () => {
const factory = new TemplateFactory({
sanitize: true,
html: true,
template: '',
content: { '#foo': 'Click me' },
})
expect(factory.toHtml().innerHTML).not.toContain('href="javascript:alert(7)')
})
it('should not sanitize content when disabled', () => {
const factory = new TemplateFactory({
sanitize: false,
html: true,
template: '',
content: { '#foo': 'Click me' },
})
expect(factory.toHtml().innerHTML).toContain('href="javascript:alert(7)')
})
})
describe('Extra Class', () => {
it('should add extra class', () => {
const factory = new TemplateFactory({ extraClass: 'testClass' })
expect(factory.toHtml().classList.contains('testClass')).toBe(true)
})
it('should add multiple extra classes', () => {
const factory = new TemplateFactory({ extraClass: 'testClass testClass2' })
const el = factory.toHtml()
expect(el.classList.contains('testClass')).toBe(true)
expect(el.classList.contains('testClass2')).toBe(true)
})
it('should resolve class from function', () => {
const factory = new TemplateFactory({
extraClass() {
return 'testClass'
},
})
expect(factory.toHtml().classList.contains('testClass')).toBe(true)
})
})
})
describe('Content', () => {
it('should add simple text content', () => {
const template = ''
const factory = new TemplateFactory({
template,
content: { '.foo': 'bar', '.foo2': 'bar2' },
})
const html = factory.toHtml()
expect(html.querySelector('.foo')!.textContent).toBe('bar')
expect(html.querySelector('.foo2')!.textContent).toBe('bar2')
})
it('should not fill template if selector does not exist', () => {
const factory = new TemplateFactory({
sanitize: true,
html: true,
template: '',
content: { '#bar': 'test' },
})
expect(factory.toHtml().outerHTML).toBe('')
})
it('should remove template selector if content is null', () => {
const factory = new TemplateFactory({
sanitize: true,
html: true,
template: '',
content: { '#foo': null },
})
expect(factory.toHtml().outerHTML).toBe('')
})
it('should resolve content from function', () => {
const factory = new TemplateFactory({
sanitize: true,
html: true,
template: '',
content: { '#foo': () => null },
})
expect(factory.toHtml().outerHTML).toBe('')
})
it('should use textContent when html is false and content is element', () => {
fixtureEl.innerHTML = 'foobar
'
const contentElement = fixtureEl.querySelector('div')!
const factory = new TemplateFactory({
html: false,
template: '',
content: { '#foo': contentElement },
})
const fooEl = factory.toHtml().querySelector('#foo')!
expect(fooEl.innerHTML).not.toBe(contentElement.innerHTML)
expect(fooEl.textContent).toBe(contentElement.textContent)
expect(fooEl.textContent).toBe('foobar')
})
it('should use outerHTML when html is true and content is element', () => {
fixtureEl.innerHTML = 'foobar
'
const contentElement = fixtureEl.querySelector('div')!
const factory = new TemplateFactory({
html: true,
template: '',
content: { '#foo': contentElement },
})
const fooEl = factory.toHtml().querySelector('#foo')!
expect(fooEl.innerHTML).toBe(contentElement.outerHTML)
})
})
describe('getContent', () => {
it('should get content as array', () => {
const factory = new TemplateFactory({
content: { '.foo': 'bar', '.foo2': 'bar2' },
})
expect(factory.getContent()).toEqual(['bar', 'bar2'])
})
it('should filter empties', () => {
const factory = new TemplateFactory({
content: {
'.foo': 'bar',
'.foo2': '',
'.foo3': null,
'.foo4': () => 2,
'.foo5': () => null,
},
})
expect(factory.getContent()).toEqual(['bar', 2])
})
})
describe('hasContent', () => {
it('should return true if it has content', () => {
const factory = new TemplateFactory({
content: { '.foo': 'bar', '.foo2': 'bar2', '.foo3': '' },
})
expect(factory.hasContent()).toBe(true)
})
it('should return false if all content is empty', () => {
const factory = new TemplateFactory({
content: { '.foo2': '', '.foo3': null, '.foo4': () => null },
})
expect(factory.hasContent()).toBe(false)
})
})
describe('changeContent', () => {
it('should change content', () => {
const template = ''
const factory = new TemplateFactory({
template,
content: { '.foo': 'bar', '.foo2': 'bar2' },
})
const text = (sel: string) => factory.toHtml().querySelector(sel)!.textContent
expect(text('.foo')).toBe('bar')
expect(text('.foo2')).toBe('bar2')
factory.changeContent({ '.foo': 'test', '.foo2': 'test2' })
expect(text('.foo')).toBe('test')
expect(text('.foo2')).toBe('test2')
})
it('should change only specified content', () => {
const template = ''
const factory = new TemplateFactory({
template,
content: { '.foo': 'bar', '.foo2': 'bar2' },
})
const text = (sel: string) => factory.toHtml().querySelector(sel)!.textContent
factory.changeContent({ '.foo': 'test' })
expect(text('.foo')).toBe('test')
expect(text('.foo2')).toBe('bar2')
})
})
})