import { describe, it, expect, beforeEach, vi } from 'vitest';
import { HTMLService } from '../../Services/HTMLService';
describe('HTMLService', () => {
let service: HTMLService;
beforeEach(() => {
service = new HTMLService();
});
describe('clearElement', () => {
it('should call empty() on the element', () => {
const mockElement = {
empty: vi.fn()
} as unknown as HTMLElement;
service.clearElement(mockElement);
expect(mockElement.empty).toHaveBeenCalledOnce();
});
it('should handle multiple calls to the same element', () => {
const mockElement = {
empty: vi.fn()
} as unknown as HTMLElement;
service.clearElement(mockElement);
service.clearElement(mockElement);
expect(mockElement.empty).toHaveBeenCalledTimes(2);
});
});
describe('parseHTMLString', () => {
it('should parse a simple HTML string into a DocumentFragment', () => {
const htmlString = '
Hello World
';
const fragment = service.parseHTMLString(htmlString);
expect(fragment).toBeInstanceOf(DocumentFragment);
expect(fragment.childNodes.length).toBe(1);
expect(fragment.firstChild).toBeInstanceOf(HTMLDivElement);
expect((fragment.firstChild as HTMLElement).textContent).toBe('Hello World');
});
it('should parse multiple sibling elements', () => {
const htmlString = 'First
Second Third
';
const fragment = service.parseHTMLString(htmlString);
expect(fragment.childNodes.length).toBe(3);
expect(fragment.childNodes[0].nodeName).toBe('DIV');
expect(fragment.childNodes[1].nodeName).toBe('SPAN');
expect(fragment.childNodes[2].nodeName).toBe('P');
});
it('should parse nested HTML structures', () => {
const htmlString = '';
const fragment = service.parseHTMLString(htmlString);
expect(fragment.childNodes.length).toBe(1);
const divElement = fragment.firstChild as HTMLElement;
expect(divElement.nodeName).toBe('DIV');
expect(divElement.childNodes.length).toBe(2);
expect(divElement.childNodes[0].nodeName).toBe('SPAN');
expect(divElement.childNodes[1].nodeName).toBe('P');
});
it('should parse HTML with attributes', () => {
const htmlString = 'Content
';
const fragment = service.parseHTMLString(htmlString);
const divElement = fragment.firstChild as HTMLElement;
expect(divElement.getAttribute('class')).toBe('test-class');
expect(divElement.getAttribute('id')).toBe('test-id');
expect(divElement.getAttribute('data-value')).toBe('123');
});
it('should handle empty string', () => {
const fragment = service.parseHTMLString('');
expect(fragment).toBeInstanceOf(DocumentFragment);
expect(fragment.childNodes.length).toBe(0);
});
it('should handle text content without HTML tags', () => {
const htmlString = 'Plain text content';
const fragment = service.parseHTMLString(htmlString);
expect(fragment.childNodes.length).toBe(1);
expect(fragment.firstChild?.nodeType).toBe(Node.TEXT_NODE);
expect(fragment.textContent).toBe('Plain text content');
});
it('should handle mixed text and HTML elements', () => {
const htmlString = 'Text beforeElement Text after';
const fragment = service.parseHTMLString(htmlString);
expect(fragment.childNodes.length).toBe(3);
expect(fragment.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
expect(fragment.childNodes[1].nodeType).toBe(Node.ELEMENT_NODE);
expect(fragment.childNodes[2].nodeType).toBe(Node.TEXT_NODE);
});
it('should handle special characters in HTML', () => {
const htmlString = '<script>alert("test")</script>
';
const fragment = service.parseHTMLString(htmlString);
const divElement = fragment.firstChild as HTMLElement;
expect(divElement.textContent).toBe('');
});
it('should parse complex HTML structures', () => {
const htmlString = `
`;
const fragment = service.parseHTMLString(htmlString);
expect(fragment.childNodes.length).toBeGreaterThan(0);
const article = Array.from(fragment.childNodes).find(
node => node.nodeName === 'ARTICLE'
) as HTMLElement;
expect(article).toBeDefined();
expect(article.querySelector('h1')?.textContent?.trim()).toBe('Title');
expect(article.querySelector('.subtitle')?.textContent?.trim()).toBe('Subtitle');
});
});
describe('setHTMLContent', () => {
it('should clear the container and set new HTML content', () => {
const container = document.createElement('div');
container.innerHTML = 'Old Content ';
const htmlString = 'New Content
';
service.setHTMLContent(container, htmlString);
expect(container.childNodes.length).toBe(1);
expect(container.firstChild?.nodeName).toBe('DIV');
expect((container.firstChild as HTMLElement).textContent).toBe('New Content');
});
it('should handle setting empty content', () => {
const container = document.createElement('div');
container.innerHTML = 'Old Content ';
service.setHTMLContent(container, '');
expect(container.childNodes.length).toBe(0);
expect(container.innerHTML).toBe('');
});
it('should set multiple elements', () => {
const container = document.createElement('div');
const htmlString = 'First
Second
Third
';
service.setHTMLContent(container, htmlString);
expect(container.childNodes.length).toBe(3);
expect(container.querySelectorAll('p').length).toBe(3);
});
it('should preserve attributes when setting content', () => {
const container = document.createElement('div');
const htmlString = 'Click me ';
service.setHTMLContent(container, htmlString);
const button = container.querySelector('button');
expect(button?.getAttribute('class')).toBe('btn');
expect(button?.getAttribute('data-action')).toBe('submit');
expect(button?.textContent).toBe('Click me');
});
it('should handle nested structures', () => {
const container = document.createElement('div');
const htmlString = '';
service.setHTMLContent(container, htmlString);
expect(container.querySelector('ul')).toBeDefined();
expect(container.querySelectorAll('li').length).toBe(2);
});
it('should completely replace existing content', () => {
const container = document.createElement('div');
container.innerHTML = 'A B C
';
service.setHTMLContent(container, 'New
');
expect(container.childNodes.length).toBe(1);
expect(container.querySelector('span')).toBeNull();
expect(container.querySelector('p')).toBeDefined();
});
});
describe('parseHTMLToContainer', () => {
it('should return an HTMLDivElement', () => {
const htmlString = 'Content ';
const container = service.parseHTMLToContainer(htmlString);
expect(container).toBeInstanceOf(HTMLDivElement);
expect(container.nodeName).toBe('DIV');
});
it('should contain parsed HTML as children', () => {
const htmlString = 'Paragraph
';
const container = service.parseHTMLToContainer(htmlString);
expect(container.childNodes.length).toBe(1);
expect(container.firstChild?.nodeName).toBe('P');
expect((container.firstChild as HTMLElement).textContent).toBe('Paragraph');
});
it('should handle multiple child elements', () => {
const htmlString = 'First
Second
';
const container = service.parseHTMLToContainer(htmlString);
expect(container.childNodes.length).toBe(2);
expect(container.querySelectorAll('div').length).toBe(2);
});
it('should allow traversal of parsed content', () => {
const htmlString = 'Text
';
const container = service.parseHTMLToContainer(htmlString);
const parent = container.querySelector('.parent');
const child = container.querySelector('.child');
expect(parent).toBeDefined();
expect(child).toBeDefined();
expect(child?.textContent).toBe('Text');
});
it('should handle empty string', () => {
const container = service.parseHTMLToContainer('');
expect(container).toBeInstanceOf(HTMLDivElement);
expect(container.childNodes.length).toBe(0);
});
it('should handle text content', () => {
const htmlString = 'Plain text';
const container = service.parseHTMLToContainer(htmlString);
expect(container.textContent).toBe('Plain text');
expect(container.childNodes.length).toBe(1);
expect(container.firstChild?.nodeType).toBe(Node.TEXT_NODE);
});
it('should allow querying with dataset attributes', () => {
const htmlString = 'Tag ';
const container = service.parseHTMLToContainer(htmlString);
const element = container.querySelector('.search-trigger') as HTMLElement;
expect(element).toBeDefined();
expect(element.dataset.trigger).toBe('#');
expect(element.dataset.content).toBe('tag');
});
it('should handle complex nested structures', () => {
const htmlString = `
`;
const container = service.parseHTMLToContainer(htmlString);
const outer = container.querySelector('.outer');
const inner = container.querySelector('.inner');
const span = container.querySelector('span');
expect(outer).toBeDefined();
expect(inner).toBeDefined();
expect(span).toBeDefined();
expect((span as HTMLElement).dataset.value).toBe('123');
});
it('should be detached from the document', () => {
const htmlString = 'Content
';
const container = service.parseHTMLToContainer(htmlString);
// The container should not be part of the document
expect(container.parentNode).toBeNull();
expect(document.contains(container)).toBe(false);
});
});
});