UNPKG

substance

Version:

Substance is a JavaScript library for web-based content editing. It provides building blocks for realizing custom text editors and web-based publishing systems.

183 lines (163 loc) 7.06 kB
import { module } from 'substance-test' import { DefaultDOMElement, MemoryDOMElement, platform } from 'substance' if (platform.inBrowser) { DOMElementTests('BrowserDOMElement') } DOMElementTests('MemoryDOMElement') function DOMElementTests(impl) { const test = module('DefaultDOMElement ('+impl+')', { before: () => { if (impl === 'MemoryDOMElement') platform.inBrowser = false }, after: () => { platform._reset() } }) test("Wrapping a native element", (t) => { let doc if (impl === 'BrowserDOMElement') { doc = window.document } else { doc = MemoryDOMElement.createDocument('html') } let nativeEl = doc.createElement('div') let el = DefaultDOMElement.wrap(nativeEl) t.ok(el._isDOMElement, 'native element should be wrapped') let el2 = DefaultDOMElement.wrap(nativeEl) t.ok(el === el2, 'wrapping an element twice should give the same DOMElement instance') t.throws(() => { DefaultDOMElement.wrap(undefined) }, 'Should throw when trying to wrap nil') t.end() }) test("Creating an HTML document", (t) => { const doc = DefaultDOMElement.createDocument('html') t.notNil(doc.find('head'), 'Document should have a <head>') t.notNil(doc.find('body'), '.. and a <body>') t.equal(doc.getContentType(), 'text/html', '.. content type should be correct') t.end() }) test("Creating an XML document", (t) => { const doc = DefaultDOMElement.createDocument('xml') t.equal(doc.getContentType(), 'application/xml', 'Document should have correct content type') t.equal(doc.children.length, 0, '.. and should be empty') t.end() }) test("Parsing a full HTML document", function(t) { const html = '<html><head><title>TEST</title></head><body>TEST</body></html>' const doc = DefaultDOMElement.parseHTML(html) const head = doc.find('head') t.notNil(head, '<head> should be there') const title = head.find('title') t.notNil(title, '<head> should contain <title>') t.equal(title.text(), 'TEST', '.. with correct text') const body = doc.find('body') t.notNil(body, 'document should have a <body> element.') t.equal(body.text(), 'TEST', '.. with correct text.') t.end() }) test("Parsing one HTML element", function(t) { const html = '<p>TEST</p>' const p = DefaultDOMElement.parseSnippet(html, 'html') t.notNil(p, 'HTML should get parsed.') t.equal(p.tagName, 'p', '.. providing one <p> element,') t.equal(p.text(), 'TEST', '.. with correct content.') t.end() }) test("Parsing multiple HTML elements", function(t) { const html = '<p>TEST</p><p>TEST2</p>' const els = DefaultDOMElement.parseSnippet(html, 'html') t.notNil(els, 'HTML should get parsed.') t.equal(els.length, 2, '.. Providing 2 elements') t.equal(els[0].tagName, 'p', '.. the first a <p>') t.equal(els[0].text(), 'TEST', '.. with correct content') t.equal(els[1].tagName, 'p', '.. the second a <p>') t.equal(els[1].text(), 'TEST2', '.. with correct content') t.end() }) test("Parsing annotated HTML text", function(t) { const html = '123<b>456</b>789' const els = DefaultDOMElement.parseSnippet(html, 'html') t.equal(els.length, 3, 'there are three elements') t.equal(els[0].nodeType, 'text', 'first is a text node') t.equal(els[0].text(), '123', '... it has correct content') t.equal(els[1].nodeType, 'element', 'second is an element') t.equal(els[1].tagName, 'b', '... it is a <b>') t.equal(els[1].text(), '456', '... it has correct content') t.equal(els[2].nodeType, 'text', 'third is a text node again') t.equal(els[2].text(), '789', '... it has correct content') t.end() }) test("Parsing an XML document", function(t) { const xml = "<mydoc><myhead><mytitle>TEST</mytitle></myhead><mybody>TEST</mybody></mydoc>" const doc = DefaultDOMElement.parseXML(xml) const head = doc.find('myhead') t.notNil(head, '<myhead> should be there') const title = head.find('mytitle') t.notNil(title, '<head> should contain <title>') t.equal(title.text(), 'TEST', '.. with correct text') const body = doc.find('mybody') t.notNil(body, 'document should have a <body> element') t.equal(body.text(), 'TEST', '.. with correct text') t.end() }) test("Parsing an incomplete HTML document", (t) => { const doc = DefaultDOMElement.parseHTML('<title>Foo</title><p>TEST</p>') const head = doc.find('head') const title = head.find('title') const body = doc.find('body') t.notNil(head, 'document should have a <head>') t.notNil(title, '<head> should contain <title>') t.equal(title.textContent, 'Foo', 'title should be correct') t.equal(body.innerHTML, '<p>TEST</p>', 'body should have contain the remaining content') t.end() }) test("Parsing an HTML document with comments", (t) => { let doc = DefaultDOMElement.parseHTML('<body><!--TEST--></body>') let body = doc.find('body') let comment = body.firstChild t.notNil(comment, 'there should a child element') t.ok(comment.isCommentNode(), '.. which should be a comment') t.equal(comment.textContent, 'TEST', '.. with correct content') // multiple lines doc = DefaultDOMElement.parseHTML('<body><!--\n TEST\n Foo\n Bar--></body>') body = doc.find('body') comment = body.firstChild t.equal(comment.textContent, '\n TEST\n Foo\n Bar', 'multi-line comment should work too') /* NOTE: from looking at the default implementation in htmlparser2 it seems that they would merge subsequent comments but actually this is not the case. So, there is a branch in oncomment() which I do not understand The same with TextNodes. ``` if(lastTag && lastTag.type === ElementType.Comment){ lastTag.data += data } ``` */ // doc = DefaultDOMElement.parseHTML('<body><!--FOO--><!--BAR--></body>') // body = doc.find('body') // t.deepEqual(body.childNodes.map(c=>c.nodeType), ['comment','comment'], 'subsequent comments should not be merged') t.end() }) test("Parsing an XML document with CDATA", (t) => { let foo = DefaultDOMElement.parseSnippet(`<foo><![CDATA[TEST]]></foo>`, 'xml') let cdata = foo.firstChild t.notNil(cdata, 'there should a child element') t.equal(cdata.nodeType, 'cdata', '.. which should be CDATA') t.equal(cdata.textContent, 'TEST', '.. with correct content') t.end() }) test("Parsing void and self-closing elements", (t) => { t.throws(() => { DefaultDOMElement.parseSnippet(`<foo>`, 'xml') }, 'should not allow void elements in XML') t.doesNotThrow(() => { DefaultDOMElement.parseSnippet(`<foo />`, 'xml') }, 'should allow self-closing elements in XML') t.doesNotThrow(() => { DefaultDOMElement.parseSnippet(`<input>`, 'html') DefaultDOMElement.parseSnippet(`<input />`, 'html') }, 'in HTML there are some allowed void elements, such as <input>') t.end() }) }