X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/65c64d3696e38bda0e2259d48c8d02978da7a3d8..44630cb8d3f935066fa308fad8a23108c79cdae0:/src/smartxml/smartxml.test.js
diff --git a/src/smartxml/smartxml.test.js b/src/smartxml/smartxml.test.js
index db9777f..cf7ef2a 100644
--- a/src/smartxml/smartxml.test.js
+++ b/src/smartxml/smartxml.test.js
@@ -40,6 +40,59 @@ describe('smartxml', function() {
doc.loadXML('');
expect(doc.root.getTagName()).to.equal('header');
});
+
+ it('knows if it contains an ElementNode in its tree', function() {
+ var doc = getDocumentFromXML('text'),
+ root = doc.root,
+ a = root.contents()[0],
+ text = root.contents()[1];
+
+ expect(doc.containsNode(root)).to.equal(true, 'contains its root');
+ expect(doc.containsNode(a)).to.equal(true, 'contains Element Node');
+ expect(doc.containsNode(text)).to.equal(true, 'contains Text Node');
+ });
+
+ it('creates text nodes', function() {
+ var doc = getDocumentFromXML('
'),
+ emptyTextNode = doc.createDocumentNode({text:''}),
+ nonEmptyTextNode = doc.createDocumentNode({text: 'alice'});
+ expect(emptyTextNode.getText()).to.equal('', 'empty ok');
+ expect(nonEmptyTextNode.getText()).to.equal('alice', 'non empty ok');
+ });
+ });
+
+ describe('DocumentNode', function() {
+ it('can be cloned', function() {
+ var doc = getDocumentFromXML('Alice
'),
+ text = doc.root.contents()[0],
+ clone, suffix;
+
+ [doc.root, text].forEach(function(node) {
+ suffix = ' (' + (node.nodeType === Node.TEXT_NODE ? 'text' : 'element') + ')';
+ clone = node.clone();
+ expect(doc.containsNode(clone)).to.equal(false, 'clone is not contained in a document' + suffix);
+ expect(node.sameNode(clone)).to.equal(false, 'clone is not same node as its originator' + suffix);
+ expect(node.nativeNode.isEqualNode(clone.nativeNode)).to.equal(true, 'clone is identical as its originator' + suffix);
+ });
+ });
+
+ it('knows its path in the document tree', function() {
+ var doc = getDocumentFromXML('text'),
+ root = doc.root,
+ a = root.contents()[0],
+ b = a.contents()[0],
+ text = b.contents()[1];
+
+ expect(root.getPath()).to.eql([], 'path of the root element is empty');
+ expect(a.getPath()).to.eql([0]);
+ expect(b.getPath()).to.eql([0, 0]);
+ expect(text.getPath()).to.eql([0,0,1]);
+
+ /* Paths relative to a given ancestor */
+ expect(text.getPath(root)).to.eql([0,0,1]);
+ expect(text.getPath(a)).to.eql([0,1]);
+ expect(text.getPath(b)).to.eql([1]);
+ });
});
describe('Basic ElementNode properties', function() {
@@ -251,6 +304,38 @@ describe('smartxml', function() {
describe('Manipulations', function() {
+ describe('replacing node with another one', function() {
+ it('replaces node with another one', function() {
+ var doc = getDocumentFromXML(''),
+ a = doc.root.contents()[0];
+
+ var c = a.replaceWith({tagName: 'b', attrs: {b:'1'}});
+
+ expect(doc.root.contents()[0].sameNode(c));
+ expect(c.getTagName()).to.equal('b');
+ expect(c.getAttr('b')).to.equal('1');
+ });
+ it('can replace document root', function() {
+ var doc = getDocumentFromXML('');
+
+ var header = doc.root.replaceWith({tagName: 'header'});
+
+ expect(doc.root.sameNode(header)).to.be.true;
+ expect(doc.containsNode(header)).to.be.true;
+ });
+ });
+
+ it('merges adjacent text nodes resulting from detaching an element node in between', function() {
+ var doc = getDocumentFromXML('Alice hasa cat
'),
+ span = doc.root.contents()[1];
+
+ span.detach();
+
+ var rootContents = doc.root.contents();
+ expect(rootContents).to.have.length(1, 'one child left');
+ expect(rootContents[0].getText()).to.equal('Alice a cat');
+ });
+
it('appends element node to another element node', function() {
var node1 = elementNodeFromParams({tag: 'div'}),
node2 = elementNodeFromParams({tag: 'a'}),
@@ -291,6 +376,32 @@ describe('smartxml', function() {
expect(node.contents()[2].getText()).to.equal(' a cat!');
});
+ it('unwrap single element node from its parent', function() {
+ var doc = getDocumentFromXML(''),
+ div = doc.root,
+ a = div.contents()[0],
+ b = a.contents()[0];
+
+ var parent = b.unwrap();
+
+ expect(parent.sameNode(div)).to.equal(true, 'returns new parent');
+ expect(div.contents()).to.have.length(1, 'root contains only one node');
+ expect(div.contents()[0].sameNode(b)).to.equal(true, 'node got unwrapped');
+ });
+
+ it('unwrap single text node from its parent', function() {
+ var doc = getDocumentFromXML('Some text!
'),
+ div = doc.root,
+ span = div.contents()[1],
+ text = span.contents()[0];
+
+ var parent = text.unwrap();
+
+ expect(parent.sameNode(div)).to.equal(true, 'returns new parent');
+ expect(div.contents()).to.have.length(1, 'root contains only one node');
+ expect(div.contents()[0].getText()).to.equal('Some text!');
+ });
+
describe('Wrapping text', function() {
it('wraps text spanning multiple sibling TextNodes', function() {
var section = elementNodeFromXML(''),
@@ -332,11 +443,11 @@ describe('smartxml', function() {
_with: {tagName: 'header'}
});
- var sectionContents = section.contents(),
- header = sectionContents[0],
+ var sectionContentss = section.contents(),
+ header = sectionContentss[0],
headerContents = header.contents();
- expect(sectionContents).to.have.length(1);
+ expect(sectionContentss).to.have.length(1);
expect(header.sameNode(returned)).to.equal(true, 'wrapper returned');
expect(header.parent().sameNode(section)).to.be.true;
expect(headerContents).to.have.length(3);
@@ -356,11 +467,11 @@ describe('smartxml', function() {
_with: {tagName: 'header'}
});
- var sectionContents = section.contents(),
- header = sectionContents[1],
+ var sectionContentss = section.contents(),
+ header = sectionContentss[1],
headerChildren = header.contents();
- expect(sectionContents).to.have.length(3);
+ expect(sectionContentss).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');
@@ -369,6 +480,85 @@ describe('smartxml', function() {
});
+ describe('Splitting text', function() {
+
+ it('splits TextNode\'s parent into two ElementNodes', function() {
+ var doc = getDocumentFromXML(''),
+ section = doc.root,
+ text = section.contents()[0].contents()[0];
+
+ var returnedValue = text.split({offset: 5});
+ expect(section.contents().length).to.equal(2, 'section has two children');
+
+ var header1 = section.contents()[0];
+ var header2 = section.contents()[1];
+
+ expect(header1.getTagName()).to.equal('header', 'first section child ok');
+ expect(header1.contents().length).to.equal(1, 'first header has one child');
+ expect(header1.contents()[0].getText()).to.equal('Some ', 'first header has correct content');
+ expect(header2.getTagName()).to.equal('header', 'second section child ok');
+ expect(header2.contents().length).to.equal(1, 'second header has one child');
+ expect(header2.contents()[0].getText()).to.equal('header', 'second header has correct content');
+
+ expect(returnedValue.first.sameNode(header1)).to.equal(true, 'first node returned');
+ expect(returnedValue.second.sameNode(header2)).to.equal(true, 'second node returned');
+ });
+
+ it('leaves empty copy of ElementNode if splitting at the very beginning', function() {
+ var doc = getDocumentFromXML(''),
+ section = doc.root,
+ text = section.contents()[0].contents()[0];
+
+ text.split({offset: 0});
+
+ var header1 = section.contents()[0];
+ var header2 = section.contents()[1];
+
+ expect(header1.contents().length).to.equal(0);
+ expect(header2.contents()[0].getText()).to.equal('Some header');
+ });
+
+ it('leaves empty copy of ElementNode if splitting at the very end', function() {
+ var doc = getDocumentFromXML(''),
+ section = doc.root,
+ text = section.contents()[0].contents()[0];
+
+ text.split({offset: 11});
+
+ var header1 = section.contents()[0];
+ var header2 = section.contents()[1];
+
+ expect(header1.contents()[0].getText()).to.equal('Some header');
+ expect(header2.contents().length).to.equal(0);
+ });
+
+ it('keeps TextNodes\'s parent\'s children elements intact', function() {
+ var doc = getDocumentFromXML(''),
+ section = doc.root,
+ header = section.contents()[0],
+ textAnd = header.contents()[2];
+
+ textAnd.split({offset: 2});
+
+ var sectionContents = section.contents();
+ expect(sectionContents.length).to.equal(2, 'Section has two children');
+ expect(sectionContents[0].getTagName()).to.equal('header', 'First section node is a header');
+ expect(sectionContents[1].getTagName()).to.equal('header', 'Second section node is a header');
+
+ var firstHeaderContents = sectionContents[0].contents();
+ expect(firstHeaderContents.length).to.equal(3, 'First header has three children');
+ expect(firstHeaderContents[0].getText()).to.equal('A ', 'First header starts with a text');
+ expect(firstHeaderContents[1].getTagName()).to.equal('span', 'First header has span in the middle');
+ expect(firstHeaderContents[2].getText()).to.equal(' a', 'First header ends with text');
+
+ var secondHeaderContents = sectionContents[1].contents();
+ expect(secondHeaderContents.length).to.equal(3, 'Second header has three children');
+ expect(secondHeaderContents[0].getText()).to.equal('nd ', 'Second header starts with text');
+ expect(secondHeaderContents[1].getTagName()).to.equal('span', 'Second header has span in the middle');
+ expect(secondHeaderContents[2].getText()).to.equal(' header', 'Second header ends with text');
+ });
+ });
+
describe('Events', function() {
it('emits nodeDetached event on node detach', function() {
var node = elementNodeFromXML(''),
@@ -484,6 +674,26 @@ describe('smartxml', function() {
expect(event.type).to.equal('nodeMoved');
expect(event.meta.node.sameNode(inserted)).to.be.true;
});
+
+ it('emits nodeDetached and nodeAdded when replacing root node with another', function() {
+ var doc = getDocumentFromXML(''),
+ oldRoot = doc.root,
+ spy = sinon.spy();
+
+ doc.on('change', spy);
+
+ doc.root.replaceWith({tagName: 'b'});
+
+ expect(spy.callCount).to.equal(2);
+
+ var event1 = spy.args[0][0],
+ event2 = spy.args[1][0];
+
+ expect(event1.type).to.equal('nodeDetached');
+ expect(event1.meta.node.sameNode(oldRoot)).to.equal(true, 'root node in nodeDetached event metadata');
+ expect(event2.type).to.equal('nodeAdded');
+ expect(event2.meta.node.sameNode(doc.root)).to.equal(true, 'new root node in nodelAdded event meta');
+ });
});
describe('Traversing', function() {