+
+    describe('Cursor', 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');
+        });
+
+        afterEach(function() {
+            getSelection.restore();
+        });
+
+        it('returns position when browser selection collapsed', function() {
+            var c = canvas.fromXML('<section>Alice has a cat</section>'),
+                dom = c.doc().dom(),
+                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({
+                anchorNode: text,
+                focusNode: text,
+                anchorOffset: 5,
+                focusOffset: 5,
+                isCollapsed: true
+            });
+            var cursor = c.getCursor(),
+                position = cursor.getPosition();
+
+            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('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
+                dom = c.doc().dom(),
+                text = {
+                    alice: findTextNode(dom, 'Alice '),
+                    has: findTextNode(dom, 'has'),
+                    cat: findTextNode(dom, ' cat')
+                },
+                cursor = c.getCursor(),
+                aliceElement = c.getDocumentElement(text.alice),
+                catElement = c.getDocumentElement(text.cat);
+
+
+                [
+                    {focus: text.alice, focusOffset: 1, anchor: text.cat,   anchorOffset: 2, selectionAnchor: catElement},
+                    {focus: text.cat,   focusOffset: 2, anchor: text.alice, anchorOffset: 1, selectionAnchor: aliceElement}
+                ].forEach(function(s, idx) {
+                    getSelection.returns({isColapsed: false, anchorNode: s.anchor, anchorOffset: s.anchorOffset, focusNode: s.focus, focusOffset: s.focusOffset});
+
+                    var selectionStart = cursor.getSelectionStart(),
+                        selectionEnd = cursor.getSelectionEnd(),
+                        selectionAnchor = cursor.getSelectionAnchor();
+
+                    expect(cursor.isSelecting()).to.equal(true, 'cursor is selecting');
+                    expect(selectionStart.element.sameNode(aliceElement)).to.equal(true, '"Alice" is the start of the selection ' + idx);
+                    expect(selectionStart.offset).to.equal(1, '"Alice" offset ok' + idx);
+                    expect(selectionEnd.element.sameNode(catElement)).to.equal(true, '"Cat" is the start of the selection ' + idx);
+                    expect(selectionEnd.offset).to.equal(2, '"Cat" offset ok' + idx);
+                    expect(selectionAnchor.element.sameNode(s.selectionAnchor)).to.equal(true, 'anchor ok');
+                    expect(selectionAnchor.offset).to.equal(s.anchorOffset, 'anchor offset ok');
+                });
+        });
+
+        it('recognizes when browser selection boundries lies in sibling DocumentTextElements', function() {
+            var c = canvas.fromXML('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
+                dom = c.doc().dom(),
+                text = {
+                    alice: findTextNode(dom, 'Alice '),
+                    has: findTextNode(dom, 'has'),
+                    a: findTextNode(dom, ' a '),
+                    big: findTextNode(dom, 'big'),
+                    cat: findTextNode(dom, ' cat'),
+                },
+                cursor = c.getCursor();
+
+            expect($(text.alice).text()).to.equal('Alice ');
+            expect($(text.has).text()).to.equal('has');
+            expect($(text.a).text()).to.equal(' a ');
+            expect($(text.big).text()).to.equal('big');
+            expect($(text.cat).text()).to.equal(' cat');
+
+            getSelection.returns({anchorNode: text.alice, focusNode: text.a});
+            expect(cursor.isSelectingSiblings()).to.equal(true, '"Alice" and "a" are children');
+
+            getSelection.returns({anchorNode: text.alice, focusNode: text.cat});
+            expect(cursor.isSelectingSiblings()).to.equal(true, '"Alice" and "cat" are children');
+
+            getSelection.returns({anchorNode: text.alice, focusNode: text.has});
+            expect(cursor.isSelectingSiblings()).to.equal(false, '"Alice" and "has" are not children');
+
+            getSelection.returns({anchorNode: text.has, focusNode: text.big});
+            expect(cursor.isSelectingSiblings()).to.equal(false, '"has" and "big" are not children');
+            
+        })
+    });
+
+    describe('Serializing document to WLXML', function() {
+        it('keeps document intact when no changes have been made', function() {
+            var xmlIn = '<section>Alice<div>has</div>a <span class="uri" meta-uri="http://cat.com">cat</span>!</section>',
+                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 = '<section a="1" xmlns:dcterms="http://purl.org/dc/terms/"></section>',
+                $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('<section class="uri" meta-uri="some.uri"></section>');
+            c.doc().setWlxmlMetaAttr('uri', '');
+            expect($(c.toXML()).attr('meta-uri')).to.equal(undefined, 'overriding attribute with zero length string');
+
+            c = canvas.fromXML('<section class="uri"></section>');
+            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 = '<section>< ></section>',
+                    c = canvas.fromXML(xmlIn),
+                    xmlOut = c.toXML();
+                expect(xmlOut).to.equal(xmlIn);
+            });
+            it('keeps entities intact when they form html/xml', function() {
+                var xmlIn = '<section><abc></section>',
+                    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 = '  <section></section>  ',
+                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 = '<section>\n\n\n<div></div>\n\n\n<div></div>\n\n\n</section>',
+                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 = '<section>\n\n\n<span></span>\n\n\n<span></span>\n\n\n</section>',
+                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 = '<section>    abc<div>some div</div>    abc</section>',
+                    c = canvas.fromXML(xmlIn),
+                    xmlOut = c.toXML();
+
+                expect(xmlOut).to.equal(xmlIn);
+            });
+
+            it('nests new children block elements', function() {
+                var c = canvas.fromXML('<section></section>');
+    
+                c.doc().append({tag: 'header'});
+
+                var xmlOut = c.toXML();
+                expect(xmlOut.split('\n  ')[0]).to.equal('<section>', 'nesting start ok');
+                expect(xmlOut.split('\n').slice(-1)[0]).to.equal('</section>', 'nesting end ok');
+
+            });
+
+            it('doesn\'t nest new children inline elements', function() {
+                var c = canvas.fromXML('<section></section>');
+    
+                c.doc().append({tag: 'span'});
+
+                var xmlOut = c.toXML();
+                expect(xmlOut).to.equal('<section><span></span></section>');
+            });
+
+            it('keeps original white space at the end of text', function() {
+                
+                var xmlIn = '<header>    Some text ended with white space \
+                \
+                <span class="uri">Some text</span> some text\
+            \
+            </header>',
+                    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 = '<section>\
+                <header>header1</header>\
+                Some text surrounded by white space\
+                <header>header2</header>\
+            </section>',
+                    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 = '<section>\
+                <header>header</header>\
+                    \
+                Some text surrounded by white space\
+                    \
+            </section>',
+                    c = canvas.fromXML(xmlIn);
+
+                var xmlOut = c.toXML();
+                expect(xmlOut).to.equal(xmlIn);
+            });
+
+            it('keeps white space after detaching text element', function() {
+                var xmlIn = '<section><header>header</header>\n\
+                    \n\
+                text1\n\
+                    \n\
+            </section>',
+                    expectedXmlOut = '<section><header>header</header>\n\
+                    \n\
+                \n\
+                    \n\
+            </section>',
+                    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);
+            });
+
+        })
+    })