X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/530d5b117e9513fa9282015d3eb231088275c615..1d56a243018175d9f384e995e1cf4531fcf0c648:/modules/documentCanvas/canvas/canvas.test3.js diff --git a/modules/documentCanvas/canvas/canvas.test3.js b/modules/documentCanvas/canvas/canvas.test3.js index 6e120dd..fc390ec 100644 --- a/modules/documentCanvas/canvas/canvas.test3.js +++ b/modules/documentCanvas/canvas/canvas.test3.js @@ -12,30 +12,6 @@ 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('Internal HTML representation of a DocumentNodeElement', function() { it('is always a div tag', function() { ['section', 'header', 'span', 'aside', 'figure'].forEach(function(tagName) { @@ -43,20 +19,24 @@ 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 just a TextNode', 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[0].nodeType === Node.TEXT_NODE); + expect(dom.prop('tagName')).to.equal('DIV'); + 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'); }); }); @@ -71,6 +51,13 @@ describe('Canvas', function() { expect(c.doc().getWlxmlTag()).to.equal('section'); }); + describe('root element', function() { + it('has no parent', function() { + var c = canvas.fromXML('
'); + expect(c.doc().parent()).to.be.null; + }); + }); + describe('DocumentTextElement', function() { it('can have its content set', function() { var c = canvas.fromXML('
Alice
'), @@ -99,14 +86,43 @@ describe('Canvas', function() { }); it('knows WLXML class of a WLXML tag it renders', function(){ - var c = canvas.fromXML('
'), + var c = canvas.fromXML('
'), section = c.doc(); - expect(section.getWlxmlClass()).to.equal('some.class'); - section.setWlxmlClass('some.other.class'); - expect(section.getWlxmlClass()).to.equal('some.other.class'); + expect(section.getWlxmlClass()).to.equal('some.class.A'); + section.setWlxmlClass('some.class.B'); + expect(section.getWlxmlClass()).to.equal('some.class.B'); section.setWlxmlClass(null); expect(section.getWlxmlClass()).to.be.undefined; }); + + + + describe('element has meta attributes', function() { + it('can change its meta attributes', function() { + var c = canvas.fromXML('
'), + span = c.doc().children()[0]; + + expect(span.getWlxmlMetaAttr('uri')).to.equal('someuri'); + span.setWlxmlMetaAttr('uri', 'otheruri'); + expect(span.getWlxmlMetaAttr('uri')).to.equal('otheruri'); + }); + + it('changes its meta attributes with class change', function() { + var c = canvas.fromXML('
'), + span = c.doc().children()[0]; + + expect(span.getWlxmlMetaAttr('uri')).to.equal('someuri'); + span.setWlxmlClass('author'); + expect(span.getWlxmlMetaAttr('uri')).to.be.undefined; + }); + + it('keeps meta attribute value on class change if a new class has this attribute', function() { + var c = canvas.fromXML('
'), + span = c.doc().children()[0]; + span.setWlxmlClass('uri.some.subclass'); + expect(span.getWlxmlMetaAttr('uri')).to.equal('someuri'); + }); + }); }); it('returns DocumentNodeElement instance from HTMLElement', function() { @@ -120,7 +136,7 @@ describe('Canvas', function() { it('returns DocumentTextElement instance from Text Node', function() { var c = canvas.fromXML('
Alice
'), aliceElement = c.doc().children()[0], - textNode = aliceElement.dom()[0], + textNode = aliceElement.dom().contents()[0], element = c.getDocumentElement(textNode); expect(textNode.nodeType).to.equal(Node.TEXT_NODE, 'text node selected'); @@ -248,6 +264,32 @@ describe('Canvas', function() { expect(c.doc().children()[2].getText()).to.equal(' cat'); }); }); + + describe('getting vertically first text element', function() { + it('returns the first child if it\'s text element, ignores metadata', function() { + var c = canvas.fromXML('
authorAlice
has
a cat
'), + first = c.doc().getVerticallyFirstTextElement(); + + expect(first.sameNode(c.doc().children()[1])).to.be.true; + }); + + it('looks recursively inside node elements if they precede text element', function() { + var c = canvas.fromXML('\ +
\ +
\ +
\ + Alice\ +
\ +
\ + Some text\ +
'), + textAlice = c.doc().children()[0].children()[0].children()[0], + first = c.doc().getVerticallyFirstTextElement(); + + expect(textAlice).to.be.instanceOf(documentElement.DocumentTextElement); + expect(first.sameNode(textAlice)).to.be.true; + }); + }); }); describe('manipulation api', function() { @@ -259,7 +301,7 @@ describe('Canvas', function() { children = c.doc().children(); expect(children.length).to.equal(1); - expect(children[0].sameNode(appended)); + expect(children[0].sameNode(appended)).to.be.true; }); it('can put new TextElement at the end', function() { @@ -268,7 +310,7 @@ describe('Canvas', function() { children = c.doc().children(); expect(children.length).to.equal(1); - expect(children[0].sameNode(appended)); + expect(children[0].sameNode(appended)).to.be.true; expect(children[0].getText()).to.equal('Alice'); }); @@ -278,7 +320,7 @@ describe('Canvas', function() { added = div.after({tag: 'header', klass: 'some.class'}), children = c.doc().children(); expect(children.length).to.equal(2); - expect(children[1].sameNode(added)); + expect(children[1].sameNode(added)).to.be.true; }); it('can put new Nodeelement before another element', function() { @@ -287,7 +329,7 @@ describe('Canvas', function() { added = div.before({tag: 'header', klass: 'some.class'}), children = c.doc().children(); expect(children.length).to.equal(2); - expect(children[0].sameNode(added)); + expect(children[0].sameNode(added)).to.be.true; }); it('can put new DocumentNodeElement after DocumentTextElement', function() { @@ -314,6 +356,53 @@ 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('Splitting text', function() { @@ -323,7 +412,7 @@ describe('Canvas', function() { section = c.doc(), text = section.children()[0].children()[0]; - text.split({offset: 5}); + var returnedValue = text.split({offset: 5}); expect(section.children().length).to.equal(2, 'section has two children'); var header1 = section.children()[0]; @@ -335,6 +424,9 @@ describe('Canvas', function() { expect(header2.getWlxmlTag()).to.equal('header', 'second section child represents wlxml header'); expect(header2.children().length).to.equal(1, 'second header has one text child'); expect(header2.children()[0].getText()).to.equal('header', 'second header has correct content'); + + expect(returnedValue.first.sameNode(header1)).to.equal(true, 'first node returnde'); + expect(returnedValue.second.sameNode(header2)).to.equal(true, 'second node returned'); }); it('leaves empty copy of DocumentNodeElement if splitting at the very beginning', function() { @@ -495,14 +587,15 @@ describe('Canvas', function() { describe('unwrapping', function() { it('unwraps DocumentTextElement from its parent DocumentNodeElement if it\'s its only child', function() { - var c = canvas.fromXML('
Alice has a cat
'), + var c = canvas.fromXML('
Alice has a cat
'), section = c.doc(), - text = section.children()[0].children()[0]; + text = section.children()[1].children()[0]; - text.unwrap(); + var newTextContainer = text.unwrap(); - expect(section.children().length).to.equal(1); + 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'); }) }); }); @@ -903,6 +996,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'); }); @@ -914,8 +1016,9 @@ 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]; + 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'); getSelection.returns({ @@ -931,15 +1034,26 @@ describe('Canvas', function() { expect(cursor.isSelecting()).to.equal(false, 'cursor is not selecting anything'); expect(position.element.getText()).to.equal('Alice has a cat'); expect(position.offset).to.equal(5); + expect(position.offsetAtEnd).to.equal(false, 'offset is not at end'); + + getSelection.returns({ + anchorNode: text, + focusNode: text, + anchorOffset: 15, + focusOffset: 15, + isCollapsed: true + }); + + expect(cursor.getPosition().offsetAtEnd).to.equal(true, 'offset at end'); }); it('returns boundries of selection when browser selection not collapsed', 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), @@ -970,11 +1084,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(); @@ -998,6 +1112,178 @@ describe('Canvas', function() { }) }); + + describe('Serializing document to WLXML', function() { + it('keeps document intact when no changes have been made', function() { + var xmlIn = '
Alice
has
a cat!
', + c = canvas.fromXML(xmlIn), + xmlOut = c.toXML(); + + var parser = new DOMParser(), + input = parser.parseFromString(xmlIn, "application/xml").childNodes[0], + output = parser.parseFromString(xmlOut, "application/xml").childNodes[0]; + + 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 = '
', + c = canvas.fromXML(xmlIn), + xmlOut = c.toXML(); + + expect(xmlOut.substr(4)).to.equal(' <', 'start'); + expect(xmlOut.substr(-2)).to.equal('> ', 'end'); + });*/ + it('keeps white space between XML nodes', function() { + var xmlIn = '
\n\n\n
\n\n\n
\n\n\n
', + c = canvas.fromXML(xmlIn), + xmlOut = c.toXML(); + + var partsIn = xmlIn.split('\n\n\n'), + partsOut = xmlOut.split('\n\n\n'); + + expect(partsIn).to.deep.equal(partsOut); + }); + + 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(); + + var partsIn = xmlIn.split('\n\n\n'), + partsOut = xmlOut.split('\n\n\n'); + + 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('
'); + + c.doc().append({tag: 'header'}); + + var xmlOut = c.toXML(); + expect(xmlOut.split('\n ')[0]).to.equal('
', 'nesting start ok'); + expect(xmlOut.split('\n').slice(-1)[0]).to.equal('
', 'nesting end ok'); + + }); + + it('doesn\'t nest new children inline elements', function() { + var c = canvas.fromXML('
'); + + c.doc().append({tag: 'span'}); + + var xmlOut = c.toXML(); + 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); + }); + + }) + }) });