X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/b60fde6f2bb4d1e10bd4187d54601315aa2e3435..2d37cb23154783cc89f2ff286405d02e594e0e46:/modules/documentCanvas/canvas/canvas.test3.js?ds=inline diff --git a/modules/documentCanvas/canvas/canvas.test3.js b/modules/documentCanvas/canvas/canvas.test3.js index a68e66b..1908574 100644 --- a/modules/documentCanvas/canvas/canvas.test3.js +++ b/modules/documentCanvas/canvas/canvas.test3.js @@ -2,8 +2,9 @@ define([ 'libs/chai', 'libs/sinon', 'modules/documentCanvas/canvas/canvas', -'modules/documentCanvas/canvas/documentElement' -], function(chai, sinon, canvas, documentElement) { +'modules/documentCanvas/canvas/documentElement', +'modules/documentCanvas/canvas/utils' +], function(chai, sinon, canvas, documentElement, utils) { 'use strict'; @@ -12,35 +13,55 @@ var expect = chai.expect; describe('Canvas', function() { - describe('Internal HTML representation of a sample document', function() { - it('works', function() { - var c = canvas.fromXML('\ -
\ - This is some text without its own wrapping tag.\ -
\ - This is a paragraph.\ -
\ -
\ - This is text in a div with some inline text.\ -
\ - This is some text without its own wrapping tag.\ -
\ - '); - var expected = '
' - + '
This is some text without its own wrapping tag.
' - + '
' - + '
This is a paragraph.
' - + '
' - + '
' - + '
This is text in a div
' - + '
' - + '
with some inline text
' - + '
' - + '
.
' - + '
' - + '
This is some text without its own wrapping tag.
' - + '
'; - expect(c.doc().dom()[0].isEqualNode($(expected)[0])).to.be.true; + + + describe('ZWS', function() { + var view, section, textElement; + + beforeEach(function() { + var c = canvas.fromXML('
'); + + section = c.doc(); + textElement = section.children()[0]; + view = c.view()[0]; + document.getElementsByTagName('body')[0].appendChild(view); + }); + + afterEach(function() { + view.parentNode.removeChild(view); + }); + + var getTextContainerNode = function(textElement) { + return textElement.dom().contents()[0]; + } + + it('is set automatically on all empty DocumentTextElements', function() { + expect(getTextContainerNode(textElement).data).to.equal(utils.unicode.ZWS); + + var header = section.append({tag: 'header'}), + newText = header.append({text: ''}), + textNode = getTextContainerNode(textElement); + + expect(textNode.data).to.equal(utils.unicode.ZWS); + }); + + it('is added automatically when whole text gets deleted', function() { + getTextContainerNode(textElement).data = ''; + + window.setTimeout(function() { + expect(getTextContainerNode(textElement).data).to.equal(utils.unicode.ZWS); + }, 0) + + var header = section.append({tag: 'header'}), + newText = header.append({text: 'Alice'}), + textNode = getTextContainerNode(newText); + + expect(textNode.data).to.have.length('Alice'.length); + textNode.data = ''; + + window.setTimeout(function() { + expect(textNode.data).to.equal(utils.unicode.ZWS); + }, 0) }); }); @@ -51,21 +72,21 @@ describe('Canvas', function() { expect(dom.prop('tagName')).to.equal('DIV', tagName + ' is represented as div'); }); }); - it('has wlxml tag put into wlxml-tag attribute', function() { + it('has wlxml tag put into wlxml-tag attribute of its internal container', function() { var dom = canvas.fromXML('
').doc().dom(); - expect(dom.attr('wlxml-tag')).to.equal('section'); + expect(dom.children('[document-element-content]').attr('wlxml-tag')).to.equal('section'); }); - it('has wlxml class put into wlxml-class, dots replaced with dashes', function() { + it('has wlxml class put into wlxml-class attribute of its internal containr, dots replaced with dashes', function() { var dom = canvas.fromXML('
').doc().dom(); - expect(dom.attr('wlxml-class')).to.equal('some-class'); + expect(dom.children('[document-element-content]').attr('wlxml-class')).to.equal('some-class'); }); }); describe('Internal HTML representation of a DocumentTextElement', function() { - it('is text node wrapped in a div with wlxml-text attribute set', function() { + it('is text node wrapped in a div with document-text-element attribute set', function() { var dom = canvas.fromXML('
Alice
').doc().children()[0].dom(); expect(dom.prop('tagName')).to.equal('DIV'); - expect(dom.attr('wlxml-text')).to.equal(''); + expect(dom.attr('document-text-element')).to.equal(''); expect(dom.contents().length).to.equal(1); expect(dom.contents()[0].nodeType).to.equal(Node.TEXT_NODE); expect($(dom.contents()[0]).text()).to.equal('Alice'); @@ -238,6 +259,39 @@ describe('Canvas', function() { }); }); + describe('accessing sibling parents of two elements', function() { + it('returns elements themself if they have direct common parent', function() { + var c = canvas.fromXML('
\ +
\ +
A
\ +
B
\ +
\ +
'), + section = c.doc(), + wrappingDiv = c.doc().children()[0], + divA = wrappingDiv.children()[0], + divB = wrappingDiv.children()[1]; + + var siblingParents = c.getSiblingParents({element1: divA, element2: divB}); + + expect(siblingParents.element1.sameNode(divA)).to.equal(true, 'divA'); + expect(siblingParents.element2.sameNode(divB)).to.equal(true, 'divB'); + }); + + it('returns sibling parents - example 1', function() { + var c = canvas.fromXML('
Alice has a cat
'), + section = c.doc(), + aliceText = section.children()[0], + span = section.children()[1], + spanText = span.children()[0]; + + var siblingParents = c.getSiblingParents({element1: aliceText, element2: spanText}); + + expect(siblingParents.element1.sameNode(aliceText)).to.equal(true, 'aliceText'); + expect(siblingParents.element2.sameNode(span)).to.equal(true, 'span'); + }); + }) + describe('free text handling', function() { it('sees free text', function() { var c = canvas.fromXML('
Alice has a cat
'), @@ -248,12 +302,24 @@ describe('Canvas', function() { expect(children[2]).to.be.instanceOf(documentElement.DocumentTextElement); }); }); - - describe('white characters handling', function() { - it('says empty element node has no children', function() { + + describe('empty nodes handling', function() { + it('says empty element node from XML source has one empty DocumentTextElement', function() { var c = canvas.fromXML('
'); - expect(c.doc().children().length).to.equal(0); + expect(c.doc().children()).to.have.length(1); + expect(c.doc().children()[0].getText()).to.equal(''); + }); + + it('allows creation of an empty element node', function() { + var c = canvas.fromXML('
'), + section = c.doc(), + header = section.append({tag: 'header'}); + expect(header.children()).to.have.length(0); }); + }); + + describe('white characters handling', function() { + it('says element node with one space has one DocumentTextElement', function() { var c = canvas.fromXML('
'); expect(c.doc().children().length).to.equal(1); @@ -328,21 +394,40 @@ describe('Canvas', function() { describe('Basic Element inserting', function() { it('can put new NodeElement at the end', function() { - var c = canvas.fromXML('
'), + var c = canvas.fromXML('
'), appended = c.doc().append({tag: 'header', klass: 'some.class'}), children = c.doc().children(); - expect(children.length).to.equal(1); - expect(children[0].sameNode(appended)).to.be.true; + expect(children.length).to.equal(2); + expect(children[1].sameNode(appended)).to.be.true; }); it('can put new TextElement at the end', function() { - var c = canvas.fromXML('
'), + var c = canvas.fromXML('
'), appended = c.doc().append({text: 'Alice'}), children = c.doc().children(); - expect(children.length).to.equal(1); - expect(children[0].sameNode(appended)).to.be.true; + expect(children.length).to.equal(2); + expect(children[1].sameNode(appended)).to.be.true; + expect(children[1].getText()).to.equal('Alice'); + }); + + it('can put new NodeElement at the beginning', function() { + var c = canvas.fromXML('
'), + prepended = c.doc().prepend({tag: 'header', klass: 'some.class'}), + children = c.doc().children(); + + expect(children).to.have.length(2); + expect(children[0].sameNode(prepended)).to.be.true; + }); + + it('can put new TextElement at the beginning', function() { + var c = canvas.fromXML('
'), + prepended = c.doc().prepend({text: 'Alice'}), + children = c.doc().children(); + + expect(children).to.have.length(2) + expect(children[0].sameNode(prepended)).to.be.true; expect(children[0].getText()).to.equal('Alice'); }); @@ -388,6 +473,69 @@ describe('Canvas', function() { expect(children[1]).to.be.instanceOf(documentElement.DocumentTextElement); expect(children[1].getText()).to.equal('Alice'); }); + + it('can divide DocumentTextElement with a new DocumentNodeElement', function() { + var c = canvas.fromXML('
Alice has a cat
'), + section = c.doc(), + text = section.children()[0]; + + var returned = text.divide({tag: 'aside', klass: 'footnote', offset: 5}), + sectionChildren = section.children(), + lhsText = sectionChildren[0], + rhsText = sectionChildren[2]; + + expect(lhsText.getText()).to.equal('Alice'); + expect(returned.sameNode(sectionChildren[1])); + expect(rhsText.getText()).to.equal(' has a cat'); + }); + + it('treats dividing DocumentTextElement at the very end as appending after it', function() { + var c = canvas.fromXML('
Alice has a cat
'), + section = c.doc(), + text = section.children()[0]; + + var returned = text.divide({tag: 'aside', klass: 'footnote', offset: 15}), + sectionChildren = section.children(), + textElement = sectionChildren[0], + nodeElement = sectionChildren[1]; + + expect(sectionChildren.length).to.equal(2); + expect(textElement.getText()).to.equal('Alice has a cat'); + expect(returned.sameNode(nodeElement)).to.be.true; + expect(nodeElement.getWlxmlTag()).to.equal('aside'); + }); + + it('treats dividing DocumentTextElement at the very beginning as appending before it', function() { + var c = canvas.fromXML('
Alice has a cat
'), + section = c.doc(), + text = section.children()[0]; + + var returned = text.divide({tag: 'aside', klass: 'footnote', offset: 0}), + sectionChildren = section.children(), + nodeElement = sectionChildren[0], + textElement = sectionChildren[1]; + + expect(sectionChildren.length).to.equal(2); + expect(textElement.getText()).to.equal('Alice has a cat'); + expect(returned.sameNode(nodeElement)).to.be.true; + expect(nodeElement.getWlxmlTag()).to.equal('aside'); + }); + }); + + describe('Removing elements', function() { + it('merges left and right DocumentTextElement sibling of a detached DocumentNodeElement', function() { + var c = canvas.fromXML('
Alice
has
a cat
'), + section = c.doc(), + div = section.children()[1]; + + div.detach(); + + var sectionChildren = section.children(), + textElement = sectionChildren[0]; + + expect(sectionChildren).to.have.length(1); + expect(textElement.getText()).to.equal('Alicea cat'); + }); }); describe('Splitting text', function() { @@ -568,10 +716,76 @@ describe('Canvas', function() { expect(wrapperChildren[2].getText()).to.equal(' cat'); }); + + it('wraps multiple sibling Elements', function() { + var c = canvas.fromXML('
Alice
has
a cat
'), + section = c.doc(), + aliceText = section.children()[0], + firstDiv = section.children()[1], + lastDiv = section.children()[section.children().length -1]; + + var returned = c.wrapElements({ + element1: aliceText, + element2: lastDiv, + _with: {tag: 'header'} + }); + + var sectionChildren = section.children(), + header = sectionChildren[0], + headerChildren = header.children(); + + expect(sectionChildren).to.have.length(1); + expect(header.sameNode(returned)).to.equal(true, 'wrapper returned'); + expect(headerChildren).to.have.length(3); + expect(headerChildren[0].sameNode(aliceText)).to.equal(true, 'first node wrapped'); + expect(headerChildren[1].sameNode(firstDiv)).to.equal(true, 'second node wrapped'); + expect(headerChildren[2].sameNode(lastDiv)).to.equal(true, 'third node wrapped'); + }); + it('wraps multiple sibling Elements - middle case', function() { + var c = canvas.fromXML('
div>
'), + section = c.doc(), + div1 = section.children()[0], + div2 = section.children()[1], + div3 = section.children()[2], + div4 = section.children()[3]; + + var returned = c.wrapElements({ + element1: div2, + element2: div3, + _with: {tag: 'header'} + }); + + var sectionChildren = section.children(), + header = sectionChildren[1], + headerChildren = header.children(); + + expect(sectionChildren).to.have.length(3); + expect(headerChildren).to.have.length(2); + expect(headerChildren[0].sameNode(div2)).to.equal(true, 'first node wrapped'); + expect(headerChildren[1].sameNode(div3)).to.equal(true, 'second node wrapped'); + }); }); - describe('unwrapping', function() { - it('unwraps DocumentTextElement from its parent DocumentNodeElement if it\'s its only child', function() { + describe('unwrapping DocumentTextElement from its parent DocumentNodeElement if it\'s its only child', function() { + it('unwraps text element from its parent and stays between its old parent siblings', function() { + var c = canvas.fromXML('
Alice
has
a cat
'), + section = c.doc(), + sectionChildren = section.children(), + divAlice = sectionChildren[0], + divHas = sectionChildren[1], + textHas = divHas.children()[0], + divCat = sectionChildren[2]; + + var newTextContainer = textHas.unwrap(), + sectionChildren = section.children(); + + expect(sectionChildren[0].sameNode(divAlice)).to.equal(true, 'divAlice ok'); + expect(newTextContainer.sameNode(section)).to.equal(true, 'unwrap returns new text parent DocumentNodeElement'); + expect(sectionChildren[1].getText()).to.equal('has'); + expect(sectionChildren[2].sameNode(divCat)).to.equal(true, 'divCat ok'); + + }); + it('unwraps and join with its old parent adjacent text elements ', function() { var c = canvas.fromXML('
Alice has a cat
'), section = c.doc(), text = section.children()[1].children()[0]; @@ -581,8 +795,59 @@ describe('Canvas', function() { expect(section.children().length).to.equal(1, 'section has one child'); expect(section.children()[0].getText()).to.equal('Alice has a cat'); expect(newTextContainer.sameNode(c.doc())).to.equal(true, 'unwrap returns new text parent DocumentNodeElement'); - }) + }); + + it('unwraps text element from its parent - first child case', function() { + var c = canvas.fromXML('
Sometext
'), + section = c.doc(), + span = section.children()[0]; + + span.children()[0].unwrap(); + + var sectionChildren = section.children(); + + expect(sectionChildren).to.have.length(1); + expect(sectionChildren[0].getText()).to.equal('Sometext'); + }); }); + + describe('unwrapping the whole content of a DocumentNodeElement', function() { + it('removes a DocumentNodeElement but keeps its content', function() { + var c = canvas.fromXML('
Alice hasa cat
'), + section = c.doc(), + div = c.doc().children()[0], + span = div.children()[1]; + + var range = div.unwrapContents(), + sectionChildren = section.children(); + + expect(sectionChildren).to.have.length(3); + expect(sectionChildren[0].getText()).to.equal('Alice has'); + expect(sectionChildren[1].sameNode(span)).to.equal(true, 'span ok'); + expect(sectionChildren[2].getText()).to.equal(' cat'); + + expect(range.element1.sameNode(sectionChildren[0])).to.equal(true, 'range start ok'); + expect(range.element2.sameNode(sectionChildren[2])).to.equal(true, 'range end ok'); + }); + it('merges text elements on the boundries', function() { + var c = canvas.fromXML('
Alice
has a cat!
!!
'), + section = c.doc(), + div = c.doc().children()[1], + span = div.children()[1]; + + var range = div.unwrapContents(), + sectionChildren = section.children(); + + expect(sectionChildren).to.have.length(3); + expect(sectionChildren[0].getText()).to.equal('Alicehas a '); + expect(sectionChildren[1].sameNode(span)).to.equal(true, 'span ok'); + expect(sectionChildren[2].getText()).to.equal('!!!'); + + expect(range.element1.sameNode(sectionChildren[0])).to.equal(true, 'range start ok'); + expect(range.element2.sameNode(sectionChildren[2])).to.equal(true, 'range end ok'); + }); + }); + }); describe('Lists api', function() { @@ -981,6 +1246,15 @@ describe('Canvas', function() { var getSelection; + var findTextNode = function(inside, text) { + var nodes = inside.find(':not(iframe)').addBack().contents().filter(function() { + return this.nodeType === Node.TEXT_NODE && this.data === text; + }); + if(nodes.length) + return nodes[0]; + return null; + } + beforeEach(function() { getSelection = sinon.stub(window, 'getSelection'); }); @@ -992,7 +1266,7 @@ describe('Canvas', function() { it('returns position when browser selection collapsed', function() { var c = canvas.fromXML('
Alice has a cat
'), dom = c.doc().dom(), - text = $(dom.contents()[0]).contents()[0]; + text = findTextNode(dom, 'Alice has a cat'); expect(text.nodeType).to.equal(Node.TEXT_NODE, 'correct node selected'); expect($(text).text()).to.equal('Alice has a cat'); @@ -1027,9 +1301,9 @@ describe('Canvas', function() { var c = canvas.fromXML('
Alice has a big cat
'), dom = c.doc().dom(), text = { - alice: dom.contents()[0], - has: $(dom.contents()[1]).contents()[0], - cat: dom.contents()[4] + alice: findTextNode(dom, 'Alice '), + has: findTextNode(dom, 'has'), + cat: findTextNode(dom, ' cat') }, cursor = c.getCursor(), aliceElement = c.getDocumentElement(text.alice), @@ -1060,11 +1334,11 @@ describe('Canvas', function() { var c = canvas.fromXML('
Alice has a big cat
'), dom = c.doc().dom(), text = { - alice: dom.contents()[0], - has: $(dom.contents()[1]).contents()[0], - a: dom.contents()[2], - big: $(dom.contents()[3]).contents()[0], - cat: dom.contents()[4] + alice: findTextNode(dom, 'Alice '), + has: findTextNode(dom, 'has'), + a: findTextNode(dom, ' a '), + big: findTextNode(dom, 'big'), + cat: findTextNode(dom, ' cat'), }, cursor = c.getCursor(); @@ -1102,6 +1376,41 @@ describe('Canvas', function() { expect(input.isEqualNode(output)).to.be.true; }); + it('keeps arbitrary node attributes intact', function() { + var xmlIn = '
', + $xmlOut = $(canvas.fromXML(xmlIn).toXML()); + + expect($xmlOut.attr('a')).to.equal('1'); + expect($xmlOut.attr('xmlns:dcterms')).to.equal('http://purl.org/dc/terms/'); + }); + + it('doesn\' serialize meta attribute if its empty', function() { + var c; + + c = canvas.fromXML('
'); + c.doc().setWlxmlMetaAttr('uri', ''); + expect($(c.toXML()).attr('meta-uri')).to.equal(undefined, 'overriding attribute with zero length string'); + + c = canvas.fromXML('
'); + c.doc().setWlxmlMetaAttr('uri', ''); + expect($(c.toXML()).attr('meta-uri')).to.equal(undefined, 'setting attribute to zero length string'); + }); + + describe('output xml', function() { + it('keeps entities intact', function() { + var xmlIn = '
< >
', + c = canvas.fromXML(xmlIn), + xmlOut = c.toXML(); + expect(xmlOut).to.equal(xmlIn); + }); + it('keeps entities intact when they form html/xml', function() { + var xmlIn = '
<abc>
', + c = canvas.fromXML(xmlIn), + xmlOut = c.toXML(); + expect(xmlOut).to.equal(xmlIn); + }); + }); + describe('formatting output xml', function() { /*it('keeps white spaces at the edges of input xml', function() { var xmlIn = '
', @@ -1124,8 +1433,9 @@ describe('Canvas', function() { it('keeps white space between XML nodes - inline case', function() { var xmlIn = '
\n\n\n\n\n\n\n\n\n
', - c = canvas.fromXML(xmlIn), - xmlOut = c.toXML(); + c = canvas.fromXML(xmlIn); + + var xmlOut = c.toXML(); var partsIn = xmlIn.split('\n\n\n'), partsOut = xmlOut.split('\n\n\n'); @@ -1133,6 +1443,14 @@ describe('Canvas', function() { expect(partsIn).to.deep.equal(partsOut); }); + it('keeps white space at the beginning of text', function() { + var xmlIn = '
abc
some div
abc
', + c = canvas.fromXML(xmlIn), + xmlOut = c.toXML(); + + expect(xmlOut).to.equal(xmlIn); + }); + it('nests new children block elements', function() { var c = canvas.fromXML('
'); @@ -1153,6 +1471,68 @@ describe('Canvas', function() { expect(xmlOut).to.equal('
'); }); + it('keeps original white space at the end of text', function() { + + var xmlIn = '
Some text ended with white space \ + \ + Some text some text\ + \ +
', + c = canvas.fromXML(xmlIn); + + var xmlOut = c.toXML(); + console.log(xmlOut); + expect(xmlOut).to.equal(xmlIn); + }); + + it('keeps white space around text node', function() { + var xmlIn = '
\ +
header1
\ + Some text surrounded by white space\ +
header2
\ +
', + c = canvas.fromXML(xmlIn); + + var xmlOut = c.toXML(); + expect(xmlOut).to.equal(xmlIn); + }); + + it('keeps white space around text node - last node case', function() { + var xmlIn = '
\ +
header
\ + \ + Some text surrounded by white space\ + \ +
', + c = canvas.fromXML(xmlIn); + + var xmlOut = c.toXML(); + expect(xmlOut).to.equal(xmlIn); + }); + + it('keeps white space after detaching text element', function() { + var xmlIn = '
header
\n\ + \n\ + text1\n\ + \n\ +
', + expectedXmlOut = '
header
\n\ + \n\ + \n\ + \n\ +
', + c = canvas.fromXML(xmlIn), + children = c.doc().children(), + text = children[children.length-1]; + + expect(text.getText()).to.equal('text1'); + + text.detach(); + + var xmlOut = c.toXML(); + expect(xmlOut).to.equal(expectedXmlOut); + }); + }) }) });