editor: edumed exercise - allow for exercise insertion after the edited one
[fnpeditor.git] / src / smartxml / smartxml.test.js
index 5430278..f506f09 100644 (file)
@@ -69,6 +69,24 @@ describe('smartxml', function() {
             expect(node.contents()[0].getText()).to.equal('Alice');
             expect(node.contents()[1].getTagName()).to.equal('b');
         });
+
+        describe('Retrieving node by path', function() {
+            it('passes smoke tests', function() {
+                var doc = getDocumentFromXML('<root><a><b>c</b></a>');
+                expect(doc.getNodeByPath([0]).sameNode(doc.root.contents()[0])).to.be.true;
+                expect(doc.getNodeByPath([0,0]).sameNode(doc.root.contents()[0].contents()[0])).to.be.true;
+            });
+            it('treats empty path as a root path', function() {
+                var doc = getDocumentFromXML('<root></root>');
+                expect(doc.getNodeByPath([]).sameNode(doc.root)).to.be.true;
+            });
+            it('returns undefined for non existing paths', function() {
+                var doc = getDocumentFromXML('<root><a></a></root>');
+                expect(doc.getNodeByPath([1])).to.be.undefined;
+                expect(doc.getNodeByPath([0,1])).to.be.undefined;
+                expect(doc.getNodeByPath([10,1])).to.be.undefined;
+            });
+        });
     });
 
     describe('DocumentNode', function() {
@@ -87,9 +105,10 @@ describe('smartxml', function() {
         });
 
         it('can be cloned with its contents and its contents data', function() {
-            var doc = getDocumentFromXML('<root><div></div></root>'),
+            var doc = getDocumentFromXML('<root><div>text</div></root>'),
                 root = doc.root,
-                div = root.contents()[0];
+                div = root.contents()[0],
+                text = div.contents()[0];
 
             var ClonableObject = function(arg) {
                 this.arg = arg;
@@ -100,15 +119,19 @@ describe('smartxml', function() {
 
             div.setData('key', 'value');
             div.setData('clonableObject', new ClonableObject('test'));
+            text.setData('key', 'value');
 
             var rootClone = root.clone(),
                 divClone = rootClone.contents()[0],
+                textClone = divClone.contents()[0],
                 stringClone = divClone.getData('key'),
                 objClone = divClone.getData('clonableObject');
 
             expect(stringClone).to.equal('value');
             expect(objClone.arg).to.equal('test', 'clonable object got copied');
             expect(objClone !== div.getData('clonableObject')).to.be.equal(true, 'copy of the clonable object is a new object');
+
+            expect(textClone.getData('key')).to.be.equal(undefined, 'cloning text node data is not supported yet');
         });
 
         it('knows its path in the document tree', function() {
@@ -240,6 +263,29 @@ describe('smartxml', function() {
                 });
             });
         });
+
+        describe('Putting nodes around', function() {
+            it('will not allow to put node before or after root node', function() {
+                var doc = getDocumentFromXML('<root></root>'),
+                    spy = sinon.spy(),
+                    root = doc.root,
+                    result;
+
+                doc.on('change', spy);
+
+                result = doc.root.before({tagName: 'test'});
+
+                expect(spy.callCount).to.equal(0);
+                expect(result).to.undefined;
+
+                result = doc.root.after({tagName: 'test'});
+                
+                expect(spy.callCount).to.equal(0);
+                expect(result).to.undefined;
+
+                expect(doc.root.sameNode(root));
+            });
+        });
     });
 
     describe('Basic TextNode properties', function() {
@@ -578,6 +624,25 @@ describe('smartxml', function() {
             expect(node.contents()[2].getText()).to.equal(' a cat!');
         });
 
+        it('removes parent-describing sibling nodes of unwrapped node', function() {
+            var doc = getDocumentFromXML('<root><div><a></a><x></x><a></a></div></root>');
+
+            doc.registerExtension({documentNode: {methods: {
+                object: {
+                    describesParent: function() {
+                        return this.getTagName() === 'x';
+                    }
+                }
+            }}});
+
+            var div = doc.root.contents()[0],
+                x = div.contents()[1];
+
+            div.unwrapContent();
+            expect(doc.root.contents().length).to.equal(2);
+            expect(x.isInDocument()).to.be.false;
+        });
+
         it('unwrap single element node from its parent', function() {
             var doc = getDocumentFromXML('<div><a><b></b></a></div>'),
                 div = doc.root,
@@ -630,6 +695,33 @@ describe('smartxml', function() {
                 expect(wrapperContents[1].contents().length).to.equal(1);
                 expect(wrapperContents[1].contents()[0].getText()).to.equal('small');
             });
+
+            it('keeps parent-describing nodes in place', function() {
+                var doc = getDocumentFromXML('<root>Alice <x></x> probably <y></y> has a cat</root>');
+
+                doc.registerExtension({documentNode: {methods: {
+                    object: {
+                        describesParent: function() {
+                            /* globals Node */
+                            return this.nodeType === Node.ELEMENT_NODE && this.getTagName() === 'x';
+                        }
+                    }
+                }}});
+
+                var root = doc.root,
+                    x = root.contents()[1],
+                    y = root.contents()[3];
+
+                root.wrapText({
+                    _with: {tagName: 'span', attrs: {'attr1': 'value1'}},
+                    offsetStart: 1,
+                    offsetEnd: 4,
+                    textNodeIdx: [0,4]
+                });
+
+                expect(x.parent().sameNode(root)).to.be.true;
+                expect(y.parent().getTagName()).to.equal('span');
+            });
         });
 
         describe('Wrapping Nodes', function() {
@@ -678,6 +770,32 @@ describe('smartxml', function() {
                 expect(headerChildren[0].sameNode(div2)).to.equal(true, 'first node wrapped');
                 expect(headerChildren[1].sameNode(div3)).to.equal(true, 'second node wrapped');
             });
+
+            it('keeps parent-describing nodes in place', function() {
+                var section = elementNodeFromXML('<section>Alice<x></x><div>a cat</div></section>');
+
+                section.document.registerExtension({documentNode: {methods: {
+                    object: {
+                        describesParent: function() {
+                            return this.nodeType === Node.ELEMENT_NODE && this.getTagName() === 'x';
+                        }
+                    }
+                }}});
+
+                var aliceText = section.contents()[0],
+                    x = section.contents()[1],
+                    lastDiv = section.contents()[2];
+
+                section.document.wrapNodes({
+                        node1: aliceText,
+                        node2: lastDiv,
+                        _with: {tagName: 'header'}
+                    });
+
+                expect(x.parent().sameNode(section)).to.be.true;
+                expect(aliceText.parent().getTagName()).to.equal('header');
+                expect(lastDiv.parent().getTagName()).to.equal('header');
+            });
         });
 
     });
@@ -850,6 +968,28 @@ describe('smartxml', function() {
             expect(contents[1].contents().length).to.equal(1);
             expect(contents[1].contents()[0].getText()).to.equal('b');
         });
+        it('removes across elements - 6', function() {
+            var doc = getDocumentFromXML('<root><div>aaa<span>bbb</span>ccc</div><div>ddd</div></root>');
+            doc.deleteText({
+                from: {
+                    node: getTextNode('aaa', doc),
+                    offset: 1
+                },
+                to: {
+                    node: getTextNode('ddd', doc),
+                    offset: 1
+                }
+            }, {
+                error: function(e) {throw e;}
+            });
+
+            var contents = doc.root.contents();
+            expect(contents.length).to.equal(2);
+            expect(contents[0].contents().length).to.equal(1);
+            expect(contents[0].contents()[0].getText()).to.equal('a');
+            expect(contents[1].contents().length).to.equal(1);
+            expect(contents[1].contents()[0].getText()).to.equal('dd');
+        });
     });
 
     describe('Splitting text', function() {
@@ -1216,19 +1356,6 @@ describe('smartxml', function() {
 
         beforeEach(function() {
             doc = getDocumentFromXML('<section>Alice<div class="test_class"></div></section>');
-            elementNode = doc.root;
-            textNode = doc.root.contents()[0];
-            extension = {};
-            
-            expect(elementNode.testTransformation).to.be.undefined;
-            expect(textNode.testTransformation).to.be.undefined;
-            expect(doc.testTransformation).to.be.undefined;
-            
-            expect(doc.testMethod).to.be.undefined;
-            expect(elementNode.testMethod).to.be.undefined;
-            expect(textNode.testMethod).to.be.undefined;
-            expect(elementNode.elementTestMethod).to.be.undefined;
-            expect(textNode.textTestMethod).to.be.undefined;
         });
 
         it('allows adding method to a document', function() {
@@ -1272,7 +1399,6 @@ describe('smartxml', function() {
 
             doc.registerExtension(extension);
 
-            /* refresh */
             elementNode = doc.root;
             textNode = doc.root.contents()[0];
 
@@ -1308,7 +1434,6 @@ describe('smartxml', function() {
             
             doc.registerExtension(extension);
 
-            /* refresh */
             elementNode = doc.root;
             textNode = doc.root.contents()[0];