UNPKG

als-document

Version:

A powerful HTML parser & DOM manipulation library for both backend and frontend.

411 lines (327 loc) 15.8 kB
const { describe, it, beforeEach } = require('node:test') const assert = require('node:assert') const { Node, Root, TextNode, Document } = require('../index') describe('Constructor and Basic Properties', () => { it('Creates an element', () => { const node = new Node('div'); assert(node instanceof Node, "Element was not created correctly"); }); it('Checks the setting of element properties: tagName, attributes, parent, etc.', () => { const rootNode = new Node('ROOT'); const divNode = new Node('div', { class: 'container' }, rootNode); assert(divNode.tagName === 'DIV', "Tag name is correct"); assert(divNode.attributes.class === 'container', "Attributes are correct"); assert(divNode.parent === rootNode, "Parent node is correct"); }); it('Adds a new element to the parent\'s childNodes', () => { const rootNode = new Node('ROOT'); const childNode = new Node('child', {}, rootNode); assert(rootNode.childNodes.includes(childNode), "New element was added to parent's childNodes"); }); }); describe('DOM Search and Navigation', () => { it('Gets the previous and next element', () => { const rootNode = new Node('ROOT'); const div1 = new Node('div', {}, rootNode); const div2 = new Node('div', {}, rootNode); assert(div2.previousElementSibling === div1, "Previous sibling is correct"); assert(div2.nextElementSibling === null, "Next sibling is correct"); }); it('Gets the list of ancestors', () => { const rootNode = new Node('ROOT'); const firstLevel = new Node('first', {}, rootNode); const secondLevel = new Node('second', {}, firstLevel); const thirdLevel = new Node('third', {}, secondLevel); const ancestors = thirdLevel.ancestors; assert(ancestors.length === 2, "The number of ancestors is correct"); assert(ancestors[0] === firstLevel, "First ancestor is correct"); assert(ancestors[1] === secondLevel, "Second ancestor is correct"); }); it('Searches for elements using different methods', () => { const rootNode = new Node('ROOT'); const div1 = new Node('div', { class: 'test', id: 'first' }, rootNode); const div2 = new Node('div', { class: 'test' }, rootNode); const p = new Node('p', {}, rootNode); const divs = rootNode.getElementsByTagName('div'); assert(divs.length === 2, "getElementsByTagName did find correct number of divs"); const testClassNodes = rootNode.getElementsByClassName('test'); assert(testClassNodes.length === 2, "getElementsByClassName did find correct number of .test elements"); const firstDiv = rootNode.getElementById('first'); assert(firstDiv === div1, "getElementById did find the correct element"); const firstQuery = rootNode.querySelector('.test'); assert(firstQuery === div1, "querySelector did return the first matching element"); const allQuery = rootNode.querySelectorAll('.test'); assert(allQuery.length === 2 && allQuery[0] === div1 && allQuery[1] === div2, "querySelectorAll did not find all matching elements"); }); }); describe('Attribute Operations', () => { it('Gets, sets, and removes attributes', () => { const attrNode = new Node('div'); attrNode.setAttribute('data-test', 'testValue'); assert(attrNode.getAttribute('data-test') === 'testValue', "getAttribute/setAttribute is correct"); attrNode.removeAttribute('data-test'); assert(!attrNode.getAttribute('data-test'), "removeAttribute is correct"); }); it('Handles classList', () => { const nodeWithClasses = new Node('div', { class: 'class1 class2' }); // Assertion to check if classList contains the right classes assert(nodeWithClasses.classList.contains('class1'), "The classList contain 'class1'"); assert(nodeWithClasses.classList.contains('class2'), "The classList contain 'class2'"); // Modifying classList and checking nodeWithClasses.classList.add('class3'); assert(nodeWithClasses.classList.contains('class3'), "The classList contain 'class3' after addition"); nodeWithClasses.classList.remove('class1'); assert(!nodeWithClasses.classList.contains('class1'), "The classList doesn't contains 'class1' after removal"); }); it('Handles style', () => { const nodeWithStyle = new Node('div', { style: 'color: red; font-size: 16px;' }); // Assertions to check if style is correctly set assert(nodeWithStyle.style.color === 'red', "The style property color is correctly set or retrieved"); assert(nodeWithStyle.style.fontSize === '16px', "The style property fontSize is correctly set or retrieved"); }); }); describe('Content Manipulation', () => { it('Adds and removes child elements', () => { const rootNode = new Node('ROOT'); const childNode = new Node('child'); rootNode.appendChild(childNode); assert(rootNode.childNodes.includes(childNode), "Child node was added"); childNode.remove(); assert(!rootNode.childNodes.includes(childNode), "Child node was removed"); }); it('Inserts content adjacent to an element', () => { const rootNode = new Node('div'); const childNode = new Node('p', {}, rootNode); childNode.insertAdjacentElement('beforebegin', new Node('span')); assert(rootNode.childNodes[0].tagName === 'SPAN'); childNode.insertAdjacentElement('afterend', new Node('a')); assert(rootNode.childNodes[2].tagName === 'A'); childNode.insertAdjacentHTML('beforebegin', '<strong></strong>'); assert(rootNode.childNodes[1].tagName === 'STRONG'); childNode.insertAdjacentText('afterend', 'Some text'); assert(typeof rootNode.childNodes[3].nodeValue === 'string'); assert(rootNode.childNodes[3].nodeValue === 'Some text'); }); // it('Gets and sets innerHTML and outerHTML', () => { // const rootNode = new Node('div'); // new Node('p', {id: 'test'}, rootNode); // assert(rootNode.innerHTML === '<p id="test"></p>'); // const newNode = new Node('span'); // newNode.innerHTML = '<a href="#">Link</a>'; // assert(newNode.childNodes[0].tagName === 'a'); // newNode.childNodes[0].outerHTML = '<div><strong>New content</strong></div>'; // assert(newNode.childNodes[0].childNodes[0].tagName === 'strong'); // }); // it('Works with text content', () => { // const rootNode = new Node('div'); // new Node('p', {}, rootNode).textContent = 'Hello World'; // assert(rootNode.textContent === 'Hello World'); // rootNode.textContent = 'Changed Text'; // assert(rootNode.textContent === 'Changed Text'); // assert(rootNode.childNodes.leng === 1); // assert(rootNode.childNodes[0] === 'Changed Text'); // }); }); describe('Other Methods and Properties', () => { it('Gets the list of child elements', () => { const rootNode = new Node('div'); // Добавление дочерних элементов new Node('p', {}, rootNode); new Node('span', {}, rootNode); new Node('a', {}, rootNode); rootNode.appendChild('Some text'); // Добавляем текстовый узел // Проверяем, что у корневого элемента теперь 4 дочерних узла (3 элемента + 1 текстовый узел) assert(rootNode.childNodes.length === 4); // Проверяем свойство children assert(rootNode.children.length === 3); assert(rootNode.children[0].tagName.toLowerCase() === 'p'); assert(rootNode.children[1].tagName.toLowerCase() === 'span'); assert(rootNode.children[2].tagName.toLowerCase() === 'a'); }); it('Gets the parent element', () => { const rootNode = new Node('ROOT'); const childNode = new Node('child', {}, rootNode); assert(childNode.parentNode === rootNode, "Parent node is correct"); }); }); describe('Method and properties 2', () => { let node beforeEach(() => {node = new Node('div')}) it('set id', () => { assert(node.getAttribute('id') === null) assert(node.id === null) node.id = 'test' assert(node.getAttribute('id') === 'test') assert(node.id === 'test') }) it('get className', () => { assert(node.classList.constructor.name === 'NodeClassList') }) it('get outerHTML', () => { assert(node.outerHTML === '<div></div>') }) it('set innerHTML', () => { assert(node.innerHTML === '') node.innerHTML = 'some test' assert(node.innerHTML === 'some test') }) it('set outerHTML error no parent', () => { assert.throws(() => {node.outerHTML = '<div>some test</div>'}) // element has no parent node }) it('set outerHTML', () => { const parent = new Node('div') parent.insert(1,node) assert(parent.children[0].outerHTML === '<div></div>') const html = '<div>some test</div>' node.outerHTML = html assert(parent.children[0].outerHTML === html) }) describe('set textContent', () => { it('sets and gets textContent correctly', () => { const node = new Node('div'); node.textContent = 'Hello World'; assert.strictEqual(node.textContent, 'Hello World', 'textContent should be "Hello World"'); }); }); describe('get innerHTML', () => { it('gets correct innerHTML', () => { const parent = new Node('div'); const child = new Node('span'); parent.appendChild(child); assert.strictEqual(parent.innerHTML, '<span></span>', 'innerHTML should include child node markup'); }); }); describe('insertAdjacentHTML', () => { it('inserts HTML correctly before begin', () => { const node = new Node('div'); node.insertAdjacentHTML('afterbegin', '<span>test</span>'); assert(node.innerHTML === '<span>test</span>', 'Should insert <span>test</span> before the node'); }); }); describe('insertAdjacentText', () => { it('inserts text correctly after end', () => { const node = new Node('div'); const parent = new Node('div'); parent.appendChild(node); node.insertAdjacentText('afterend', 'Hello'); assert.strictEqual(parent.childNodes[1].nodeValue, 'Hello', 'Should insert "Hello" after the node'); }); }); describe('appendChild', () => { it('appends a child node correctly', () => { const parentNode = new Node('div'); const childNode = new Node('span'); parentNode.appendChild(childNode); assert(parentNode.childNodes.includes(childNode), 'Child node should be in parent\'s childNodes array'); }); }); describe('get textContent', () => { it('returns correct text content', () => { const node = new Node('div'); const child1 = new TextNode('Hello'); const child2 = new TextNode('World'); node.appendChild(child1); node.appendChild(child2); assert.strictEqual(node.textContent, 'HelloWorld', 'textContent should be "HelloWorld"'); }); }); describe('insertAdjacentElement', () => { it('inserts an element adjacent to another', () => { const root = new Root(); const refNode = new Node('div'); const newNode = new Node('span'); root.appendChild(refNode); refNode.insertAdjacentElement('afterend', newNode); assert.strictEqual(root.childNodes[1], newNode, 'New node should be inserted after the reference node'); }); }); }) describe('query', () => { describe('$$', () => { it('returns all elements matching the selector', () => { const root = new Root(); const child1 = new Node('div', { class: 'test' }); const child2 = new Node('div', { class: 'test' }); root.appendChild(child1); root.appendChild(child2); assert.strictEqual(root.$$('.test').length, 2, 'Should find two elements with class "test"'); }); }); describe('$', () => { it('returns the first element matching the selector', () => { const root = new Root(); const child1 = new Node('div', { class: 'test' }); const child2 = new Node('div', { class: 'test' }); root.appendChild(child1); root.appendChild(child2); assert.strictEqual(root.$('.test'), child1, 'Should return the first element with class "test"'); }); }); describe('querySelectorAll', () => { it('finds all elements matching a complex query', () => { const root = new Root(); const child1 = new Node('div', { id: 'unique' }); const child2 = new Node('div', { class: 'test' }); root.appendChild(child1); root.appendChild(child2); assert.strictEqual(root.querySelectorAll('div').length, 2, 'Should find two div elements'); }); }); describe('querySelector', () => { it('finds the first element matching a complex query', () => { const root = new Root(); const child1 = new Node('div', { id: 'unique' }); const child2 = new Node('div', { class: 'test' }); root.appendChild(child1); root.appendChild(child2); assert.strictEqual(root.querySelector('#unique'), child1, 'Should find the first div with id "unique"'); }); }); describe('getElementsByClassName', () => { it('finds elements by class name', () => { const root = new Root(); const child1 = new Node('div', { class: 'test' }); const child2 = new Node('div', { class: 'test' }); root.appendChild(child1); root.appendChild(child2); assert.strictEqual(root.getElementsByClassName('test').length, 2, 'Should find two elements with class "test"'); }); }); describe('getElementsByTagName', () => { it('finds elements by tag name', () => { const root = new Root(); const child1 = new Node('div'); const child2 = new Node('span'); root.appendChild(child1); root.appendChild(child2); assert.strictEqual(root.getElementsByTagName('div').length, 1, 'Should find one div element'); }); }); describe('getElementById', () => { it('finds an element by ID', () => { const root = new Root(); const child = new Node('div', { id: 'unique' }); root.appendChild(child); assert.strictEqual(root.getElementById('unique'), child, 'Should find the element with id "unique"'); }); }); }) describe('Document element', () => { it('get body', () => { const document = new Document(); assert(document.body !== undefined); assert(document.body instanceof Node); }); it('get head', () => { const document = new Document(); assert(document.head !== undefined); assert(document.head instanceof Node); }); it('get and set title', () => { const root = new Document(); root.title = 'Original Title'; assert.strictEqual(root.title, 'Original Title', 'Should get the title'); root.title = 'New Title'; assert.strictEqual(root.title, 'New Title', 'Should set the new title'); }); })