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 = '
Nested

Content

'; 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 beforeElementText 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 = `

Title

Subtitle

Paragraph 1

Paragraph 2

`; 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 = ''; 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 = '
ABC
'; 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 = `
Content
`; 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); }); }); });