4 'modules/documentCanvas/canvas/canvas',
 
   5 'modules/documentCanvas/canvas/documentElement'
 
   6 ], function(chai, sinon, canvas, documentElement) {
 
  10 var expect = chai.expect;
 
  13 describe('Canvas', function() {
 
  15     describe('Internal HTML representation of a sample document', function() {
 
  16         it('works', function() {
 
  17             var c = canvas.fromXML('\
 
  19                     This is some text without its own wrapping tag.\
 
  20                     <div class="p.subclass">\
 
  24                         This is text in a div <span>with some inline text</span>.\
 
  26                     This is some text without its own wrapping tag.\
 
  29             var expected = '<div wlxml-tag="section">'
 
  30                             + 'This is some text without its own wrapping tag.'
 
  31                             + '<div wlxml-tag="div" wlxml-class="p-subclass">This is a paragraph.</div>'
 
  32                             + '<div wlxml-tag="div">This is text in a div <div wlxml-tag="span">with some inline text</div>.</div>'
 
  33                             + 'This is some text without its own wrapping tag.'
 
  35             expect(c.doc().dom()[0].isEqualNode($(expected)[0])).to.be.true;
 
  39     describe('Internal HTML representation of a DocumentNodeElement', function() {
 
  40         it('is always a div tag', function() {
 
  41             ['section', 'header', 'span', 'aside', 'figure'].forEach(function(tagName) {
 
  42                 var dom = canvas.fromXML('<' + tagName + '></' + tagName + '>').doc().dom();
 
  43                 expect(dom.prop('tagName')).to.equal('DIV', tagName + ' is represented as div');
 
  46         it('has wlxml tag put into wlxml-tag attribute', function() {
 
  47             var dom = canvas.fromXML('<section></section>').doc().dom();
 
  48             expect(dom.attr('wlxml-tag')).to.equal('section');
 
  50         it('has wlxml class put into wlxml-class, dots replaced with dashes', function() {
 
  51             var dom = canvas.fromXML('<section class="some.class"></section>').doc().dom();
 
  52             expect(dom.attr('wlxml-class')).to.equal('some-class');
 
  56     describe('Internal HTML representation of a DocumentTextElement', function() {
 
  57         it('is just a TextNode', function() {
 
  58             var dom = canvas.fromXML('<section>Alice</section>').doc().children()[0].dom();
 
  59             expect(dom[0].nodeType === Node.TEXT_NODE);
 
  63     describe('basic properties', function() {
 
  64         it('renders empty document when canvas created from empty XML', function() {
 
  65             var c = canvas.fromXML('');
 
  66             expect(c.doc()).to.equal(null);
 
  69         it('gives access to its document root node', function() {
 
  70             var c = canvas.fromXML('<section></section>');
 
  71             expect(c.doc().getWlxmlTag()).to.equal('section');
 
  74         describe('DocumentTextElement', function() {
 
  75             it('can have its content set', function() {
 
  76                 var c = canvas.fromXML('<section>Alice</section>'),
 
  78                     text = root.children()[0];
 
  80                 text.setText('a cat');
 
  81                 expect(root.children()[0].getText()).to.equal('a cat');
 
  85         describe('DocumentNodeElement', function() {
 
  86             it('knows index of its child', function() {
 
  87                 var c = canvas.fromXML('<section><div></div><header></header><span></span></section>'),
 
  89                     child = root.children()[1];
 
  90                 expect(root.childIndex(child)).to.equal(1);
 
  93             it('knows WLXML tag it renders', function(){
 
  94                 var c = canvas.fromXML('<section></section>'),
 
  96                 expect(section.getWlxmlTag()).to.equal('section', 'initial tag is section');
 
  97                 section.setWlxmlTag('header');
 
  98                 expect(section.getWlxmlTag()).to.equal('header', 'tag is changed to header');
 
 101             it('knows WLXML class of a WLXML tag it renders', function(){
 
 102                 var c = canvas.fromXML('<section class="some.class"></section>'),
 
 104                 expect(section.getWlxmlClass()).to.equal('some.class');
 
 105                 section.setWlxmlClass('some.other.class');
 
 106                 expect(section.getWlxmlClass()).to.equal('some.other.class');
 
 107                 section.setWlxmlClass(null);
 
 108                 expect(section.getWlxmlClass()).to.be.undefined;
 
 112         it('returns DocumentNodeElement instance from HTMLElement', function() {
 
 113             var c = canvas.fromXML('<section></section>'),
 
 114                 htmlElement = c.doc().dom().get(0),
 
 115                 element = c.getDocumentElement(htmlElement);
 
 116             expect(element).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 117             expect(element.sameNode(c.doc()));
 
 120         it('returns DocumentTextElement instance from Text Node', function() {
 
 121             var c = canvas.fromXML('<section>Alice</section>'),
 
 122                 aliceElement = c.doc().children()[0],
 
 123                 textNode = aliceElement.dom()[0],
 
 124                 element = c.getDocumentElement(textNode);
 
 126             expect(textNode.nodeType).to.equal(Node.TEXT_NODE, 'text node selected');
 
 127             expect($(textNode).text()).to.equal('Alice');
 
 129             expect(element).to.be.instanceOf(documentElement.DocumentTextElement);
 
 130             expect(element.sameNode(c.doc().children()[0]));
 
 136     describe('document representation api', function() {
 
 137         describe('document root element', function() {
 
 138             var c = canvas.fromXML('<section></section>');
 
 139             it('exists', function() {
 
 140                 expect(c.doc()).to.be.instanceOf(documentElement.DocumentElement);
 
 142             it('is of type DocumentNodeElement', function() {
 
 143                 expect(c.doc()).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 147         describe('DocumentElements comparison', function() {
 
 148             it('reports dwo DocumentElements to be the same when they represent the same wlxml document element', function() {
 
 149                 var c = canvas.fromXML('<section><div></div><div></div></section>'),
 
 150                     first_div1 = c.doc().children()[0],
 
 151                     first_div2 = c.doc().children()[0],
 
 152                     second_div = c.doc().children()[1];
 
 153                 expect(first_div1.sameNode(first_div1)).to.be.true;
 
 154                 expect(first_div1.sameNode(first_div2)).to.be.true;
 
 155                 expect(first_div1.sameNode(second_div)).to.be.false;
 
 159         describe('traversing', function() {
 
 160             it('reports element nodes', function() {
 
 161                 var c = canvas.fromXML('<section><div></div></section>'),
 
 162                     children = c.doc().children();
 
 163                 expect(children.length).to.equal(1);
 
 164                 expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 166                 c = canvas.fromXML('<section><div></div><div></div></section>'),
 
 167                     children = c.doc().children();
 
 168                 expect(children.length).to.equal(2);
 
 169                 expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 170                 expect(children[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 173             it('reports text nodes', function() {
 
 174                 var c = canvas.fromXML('<section>Alice</section>'),
 
 175                     children = c.doc().children();
 
 176                 expect(children.length).to.equal(1);
 
 177                 expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 180             describe('accessing parents', function() {
 
 181                 it('returns DocumentNodeElement representing parent in wlxml document as DocumentNodeElement parent', function() {
 
 182                     var c = canvas.fromXML('<section><div></div></section>'),
 
 183                         div = c.doc().children()[0];
 
 184                     expect(div.parent().sameNode(c.doc())).to.be.true;
 
 186                 it('returns DocumentNodeElement representing parent in wlxml document as DocumentTextElement parent', function() {
 
 187                     var c = canvas.fromXML('<section>Alice</section>'),
 
 188                         text = c.doc().children()[0];
 
 189                     expect(text.parent().sameNode(c.doc())).to.be.true;
 
 193             describe('free text handling', function() {
 
 194                     it('sees free text', function() {
 
 195                         var c = canvas.fromXML('<section>Alice <span>has</span> a cat</section>'),
 
 196                             children = c.doc().children();
 
 197                         expect(children.length).to.equal(3);
 
 198                         expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 199                         expect(children[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 200                         expect(children[2]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 204             describe('white characters handling', function() {
 
 205                 it('says empty element node has no children', function() {
 
 206                     var c = canvas.fromXML('<section></section>');
 
 207                     expect(c.doc().children().length).to.equal(0);
 
 209                 it('says element node with one space has one DocumentTextElement', function() {
 
 210                     var c = canvas.fromXML('<section> </section>');
 
 211                     expect(c.doc().children().length).to.equal(1);
 
 212                     expect(c.doc().children()[0]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 213                     expect(c.doc().children()[0].getText()).to.equal(' ');
 
 215                 it('ignores white space surrounding block elements', function() {
 
 216                     var c = canvas.fromXML('<section> <div></div> </section>');
 
 217                     var children = c.doc().children();
 
 218                     expect(children.length).to.equal(1);
 
 219                     expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 221                 it('ignores white space between block elements', function() {
 
 222                     var c = canvas.fromXML('<section><div></div> <div></div></section>');
 
 223                     var children = c.doc().children();
 
 224                     expect(children.length === 2);
 
 225                     [0,1].forEach(function(idx) {
 
 226                         expect(children[idx]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 230                 it('trims white space from the beginning and the end of the block elements', function() {
 
 231                     var c = canvas.fromXML('<section> Alice <span>has</span> a cat </section>');
 
 232                     expect(c.doc().children()[0].getText()).to.equal('Alice ');
 
 233                     expect(c.doc().children()[2].getText()).to.equal(' a cat');
 
 236                 it('normalizes string of white characters to one space at the inline element boundries', function() {
 
 237                     var c = canvas.fromXML('<span>   Alice has a cat   </span>');
 
 238                     expect(c.doc().children()[0].getText()).to.equal(' Alice has a cat ');
 
 241                 it('normalizes string of white characters to one space before inline element', function() {
 
 242                     var c = canvas.fromXML('<div>Alice has  <span>a cat</span></div>');
 
 243                     expect(c.doc().children()[0].getText()).to.equal('Alice has ');
 
 246                 it('normalizes string of white characters to one space after inline element', function() {
 
 247                     var c = canvas.fromXML('<div>Alice has <span>a</span>  cat</div>');
 
 248                     expect(c.doc().children()[2].getText()).to.equal(' cat');
 
 253         describe('manipulation api', function() {
 
 255             describe('Basic Element inserting', function() {
 
 256                 it('can put new NodeElement at the end', function() {
 
 257                     var c = canvas.fromXML('<section></section>'),
 
 258                         appended = c.doc().append({tag: 'header', klass: 'some.class'}),
 
 259                         children = c.doc().children();
 
 261                     expect(children.length).to.equal(1);
 
 262                     expect(children[0].sameNode(appended));
 
 265                 it('can put new TextElement at the end', function() {
 
 266                     var c = canvas.fromXML('<section></section>'),
 
 267                         appended = c.doc().append({text: 'Alice'}),
 
 268                         children = c.doc().children();
 
 270                     expect(children.length).to.equal(1);
 
 271                     expect(children[0].sameNode(appended));
 
 272                     expect(children[0].getText()).to.equal('Alice');
 
 275                 it('can put new NodeElement after another NodeElement', function() {
 
 276                     var c = canvas.fromXML('<section><div></div></section>'),
 
 277                         div = c.doc().children()[0],
 
 278                         added = div.after({tag: 'header', klass: 'some.class'}),
 
 279                         children = c.doc().children();
 
 280                     expect(children.length).to.equal(2);
 
 281                     expect(children[1].sameNode(added));
 
 284                 it('can put new Nodeelement before another element', function() {
 
 285                     var c = canvas.fromXML('<section><div></div></section>'),
 
 286                         div = c.doc().children()[0],
 
 287                         added = div.before({tag: 'header', klass: 'some.class'}),
 
 288                         children = c.doc().children();
 
 289                     expect(children.length).to.equal(2);
 
 290                     expect(children[0].sameNode(added));
 
 293                 it('can put new DocumentNodeElement after DocumentTextElement', function() {
 
 294                     var c = canvas.fromXML('<section>Alice</section>'),
 
 295                         text = c.doc().children()[0],
 
 296                         added = text.after({tag: 'p'}),
 
 297                         children = c.doc().children();
 
 299                     expect(children.length).to.equal(2);
 
 300                     expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 301                     expect(children[0].getText()).to.equal('Alice');
 
 302                     expect(children[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 303                     expect(children[1].sameNode(added)).to.be.true;
 
 305                 it('can put new DocumentNodeElement before DocumentTextElement', function() {
 
 306                     var c = canvas.fromXML('<section>Alice</section>'),
 
 307                         text = c.doc().children()[0],
 
 308                         added = text.before({tag: 'p'}),
 
 309                         children = c.doc().children();
 
 311                     expect(children.length).to.equal(2);
 
 312                     expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 313                     expect(children[0].sameNode(added)).to.be.true;
 
 314                     expect(children[1]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 315                     expect(children[1].getText()).to.equal('Alice');
 
 319             describe('Splitting text', function() {
 
 321                 it('splits DocumentTextElement\'s parent into two DocumentNodeElements of the same type', function() {
 
 322                     var c = canvas.fromXML('<section><header>Some header</header></section>'),
 
 324                         text = section.children()[0].children()[0];
 
 326                     text.split({offset: 5});
 
 327                     expect(section.children().length).to.equal(2, 'section has two children');
 
 329                     var header1 = section.children()[0];
 
 330                     var header2 = section.children()[1];
 
 332                     expect(header1.getWlxmlTag()).to.equal('header', 'first section child represents wlxml header');
 
 333                     expect(header1.children().length).to.equal(1, 'first header has one text child');
 
 334                     expect(header1.children()[0].getText()).to.equal('Some ', 'first header has correct content');
 
 335                     expect(header2.getWlxmlTag()).to.equal('header', 'second section child represents wlxml header');
 
 336                     expect(header2.children().length).to.equal(1, 'second header has one text child');
 
 337                     expect(header2.children()[0].getText()).to.equal('header', 'second header has correct content');
 
 340                 it('leaves empty copy of DocumentNodeElement if splitting at the very beginning', function() {
 
 341                         var c = canvas.fromXML('<section><header>Some header</header></section>'),
 
 343                         text = section.children()[0].children()[0];
 
 345                         text.split({offset: 0});
 
 347                         var header1 = section.children()[0];
 
 348                         var header2 = section.children()[1];
 
 350                         expect(header1.children().length).to.equal(0);
 
 351                         expect(header2.children()[0].getText()).to.equal('Some header');
 
 354                 it('leaves empty copy of DocumentNodeElement if splitting at the very end', function() {
 
 355                         var c = canvas.fromXML('<section><header>Some header</header></section>'),
 
 357                         text = section.children()[0].children()[0];
 
 359                         text.split({offset: 11});
 
 361                         var header1 = section.children()[0];
 
 362                         var header2 = section.children()[1];
 
 364                         expect(header1.children()[0].getText()).to.equal('Some header');
 
 365                         expect(header2.children().length).to.equal(0);
 
 368                 it('keeps DocumentTextElement\'s parent\'s children elements intact', function() {
 
 369                     var c = canvas.fromXML('\
 
 372                                     A <span>fancy</span> and <span>nice</span> header\
 
 376                         header = section.children()[0],
 
 377                         textAnd = header.children()[2];
 
 379                     textAnd.split({offset: 2});
 
 381                     var sectionChildren = section.children();
 
 382                     expect(sectionChildren.length).to.equal(2, 'Section has two children');
 
 383                     expect(sectionChildren[0].getWlxmlTag()).to.equal('header', 'First section element is a wlxml header');
 
 384                     expect(sectionChildren[1].getWlxmlTag()).to.equal('header', 'Second section element is a wlxml header');
 
 386                     var firstHeaderChildren = sectionChildren[0].children();
 
 387                     expect(firstHeaderChildren.length).to.equal(3, 'First header has three children');
 
 388                     expect(firstHeaderChildren[0].getText()).to.equal('A ', 'First header starts with a text');
 
 389                     expect(firstHeaderChildren[1].getWlxmlTag()).to.equal('span', 'First header has span in the middle');
 
 390                     expect(firstHeaderChildren[2].getText()).to.equal(' a', 'First header ends with text');
 
 392                     var secondHeaderChildren = sectionChildren[1].children();
 
 393                     expect(secondHeaderChildren.length).to.equal(3, 'Second header has three children');
 
 394                     expect(secondHeaderChildren[0].getText()).to.equal('nd ', 'Second header starts with text');
 
 395                     expect(secondHeaderChildren[1].getWlxmlTag()).to.equal('span', 'Second header has span in the middle');
 
 396                     expect(secondHeaderChildren[2].getText()).to.equal(' header', 'Second header ends with text');
 
 400             describe('wrapping', function() {
 
 401                 it('wraps DocumentNodeElement', function() {
 
 402                     var c = canvas.fromXML('<section><div></div></section>'),
 
 403                         div = c.doc().children()[0];
 
 405                     var returned = div.wrapWithNodeElement({tag: 'header', klass: 'some.class'}),
 
 406                         parent = div.parent(),
 
 407                         parent2 = c.doc().children()[0];
 
 409                     expect(returned.sameNode(parent)).to.be.true;
 
 410                     expect(returned.sameNode(parent2)).to.be.true;
 
 411                     expect(returned.getWlxmlTag()).to.equal('header');
 
 412                     expect(returned.getWlxmlClass()).to.equal('some.class');
 
 414                 it('wraps DocumentTextElement', function() {
 
 415                     var c = canvas.fromXML('<section>Alice</section>'),
 
 416                         text = c.doc().children()[0];
 
 418                     var returned = text.wrapWithNodeElement({tag: 'header', klass: 'some.class'}),
 
 419                         parent = text.parent(),
 
 420                         parent2 = c.doc().children()[0];
 
 422                     expect(returned.sameNode(parent)).to.be.true;
 
 423                     expect(returned.sameNode(parent2)).to.be.true;
 
 424                     expect(returned.getWlxmlTag()).to.equal('header');
 
 425                     expect(returned.getWlxmlClass()).to.equal('some.class');
 
 428                 describe('wrapping part of DocumentTextElement', function() {
 
 429                     [{start: 5, end: 12}, {start: 12, end: 5}].forEach(function(offsets) {
 
 430                         it('wraps in the middle ' + offsets.start + '/' + offsets.end, function() {
 
 431                             var c = canvas.fromXML('<section>Alice has a cat</section>'),
 
 432                                 text = c.doc().children()[0];
 
 434                             var returned = text.wrapWithNodeElement({tag: 'header', klass: 'some.class', start: offsets.start, end: offsets.end}),
 
 435                                 children = c.doc().children();
 
 437                             expect(children.length).to.equal(3);
 
 439                             expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 440                             expect(children[0].getText()).to.equal('Alice');
 
 442                             expect(children[1].sameNode(returned)).to.be.true;
 
 443                             expect(returned.getWlxmlTag()).to.equal('header');
 
 444                             expect(returned.getWlxmlClass()).to.equal('some.class');
 
 445                             expect(children[1].children().length).to.equal(1);
 
 446                             expect(children[1].children()[0].getText()).to.equal(' has a ');
 
 448                             expect(children[2]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 449                             expect(children[2].getText()).to.equal('cat');
 
 453                     it('wraps whole text inside DocumentTextElement if offsets span entire content', function() {
 
 454                          var c = canvas.fromXML('<section>Alice has a cat</section>'),
 
 455                              text = c.doc().children()[0];
 
 457                          var returned = text.wrapWithNodeElement({tag: 'header', klass: 'some.class', start: 0, end: 15}),
 
 458                              children = c.doc().children();
 
 460                          expect(children.length).to.equal(1);
 
 461                          expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 462                          expect(children[0].children()[0].getText()).to.equal('Alice has a cat');
 
 466                 it('wraps text spanning multiple sibling DocumentTextNodes', function() {
 
 467                     var c = canvas.fromXML('<section>Alice has a <span>small</span> cat</section>'),
 
 469                         wrapper = c.wrapText({
 
 471                             _with: {tag: 'span', klass: 'some.class'},
 
 477                     expect(section.children().length).to.equal(2);
 
 478                     expect(section.children()[0]).to.be.instanceOf(documentElement.DocumentTextElement);
 
 479                     expect(section.children()[0].getText()).to.equal('Alice ');
 
 481                     var wrapper2 = section.children()[1];
 
 482                     expect(wrapper2.sameNode(wrapper)).to.be.true;
 
 484                     var wrapperChildren = wrapper.children();
 
 485                     expect(wrapperChildren.length).to.equal(3);
 
 486                     expect(wrapperChildren[0].getText()).to.equal('has a ');
 
 488                     expect(wrapperChildren[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
 
 489                     expect(wrapperChildren[1].children().length).to.equal(1);
 
 490                     expect(wrapperChildren[1].children()[0].getText()).to.equal('small');
 
 492                     expect(wrapperChildren[2].getText()).to.equal(' cat');
 
 496             describe('unwrapping', function() {
 
 497                 it('unwraps DocumentTextElement from its parent DocumentNodeElement if it\'s its only child', function() {
 
 498                     var c = canvas.fromXML('<section><div>Alice has a cat</div></section>'),
 
 500                     text = section.children()[0].children()[0];
 
 504                     expect(section.children().length).to.equal(1);
 
 505                     expect(section.children()[0].getText()).to.equal('Alice has a cat');
 
 510         describe('Lists api', function() {
 
 511             describe('creating lists', function() {
 
 512                 it('allows creation of a list from existing sibling DocumentElements', function() {
 
 513                     var c = canvas.fromXML('\
 
 521                         textHas = section.children()[1],
 
 522                         divA = section.children()[2]
 
 524                     c.list.create({element1: textHas, element2: divA});
 
 526                     expect(section.children().length).to.equal(3, 'section has three child elements');
 
 528                     var child1 = section.children()[0],
 
 529                         list = section.children()[1],
 
 530                         child3 = section.children()[2];
 
 532                     expect(child1.getText()).to.equal('Alice');
 
 533                     expect(list.is('list')).to.equal(true, 'second child is a list');
 
 534                     expect(list.children().length).to.equal(2, 'list contains two elements');
 
 535                     list.children().forEach(function(child) {
 
 536                         expect(child.getWlxmlClass()).to.equal('item', 'list childs have wlxml class of item');
 
 538                     expect(child3.children()[0].getText()).to.equal('cat');
 
 541                 it('allows creating nested list from existing sibling list items', function() {
 
 542                     var c = canvas.fromXML('\
 
 544                             <div class="list-items">\
 
 545                                 <div class="item">A</div>\
 
 546                                 <div class="item">B</div>\
 
 547                                 <div class="item">C</div>\
 
 548                                 <div class="item">D</div>\
 
 551                         outerList = c.doc().children()[0],
 
 552                         itemB = outerList.children()[1],
 
 553                         itemC = outerList.children()[2];
 
 556                         c.list.create({element1: itemB, element2: itemC});
 
 558                     var outerListItems = outerList.children(),
 
 559                         innerList = outerListItems[1].children()[0],
 
 560                         innerListItems = innerList.children();
 
 562                     expect(outerListItems.length).to.equal(3, 'outer list has three items');
 
 563                     expect(outerListItems[0].children()[0].getText()).to.equal('A', 'first outer item ok');
 
 564                     expect(outerListItems[1].getWlxmlClass()).to.equal('item', 'inner list is wrapped by item element');
 
 566                     expect(innerList.is('list')).to.equal(true, 'inner list created');
 
 567                     expect(innerListItems.length).to.equal(2, 'inner list has two items');
 
 568                     expect(innerListItems[0].children()[0].getText()).to.equal('B', 'first inner item ok');
 
 569                     expect(innerListItems[1].children()[0].getText()).to.equal('C', 'second inner item ok');
 
 571                     expect(outerListItems[2].children()[0].getText()).to.equal('D', 'last outer item ok');
 
 577             describe('extracting list items', function() {
 
 578                 it('creates two lists with extracted items in the middle if extracting from the middle of the list', function() {
 
 579                     var c = canvas.fromXML('\
 
 581                             <div class="list.items">\
 
 582                                 <div class="item">0</div>\
 
 583                                 <div class="item">1</div>\
 
 584                                 <div class="item">2</div>\
 
 585                                 <div class="item">3</div>\
 
 588                         list = c.doc().children()[0],
 
 589                         item1 = list.children()[1],
 
 590                         item2 = list.children()[2];
 
 592                     c.list.extractItems({element1: item1, element2: item2});
 
 594                     var section = c.doc(),
 
 595                         list1 = section.children()[0],
 
 596                         oldItem1 = section.children()[1],
 
 597                         oldItem2 = section.children()[2],
 
 598                         list2 = section.children()[3];
 
 600                     expect(section.children().length).to.equal(4, 'section contains four children');
 
 602                     expect(list1.is('list')).to.equal(true, 'first section child is a list');
 
 603                     expect(list1.children().length).to.equal(1, 'first list has one child');
 
 604                     expect(list1.children()[0].children()[0].getText()).to.equal('0', 'first item of the first list is a first item of the original list');
 
 606                     expect(oldItem1.children()[0].getText()).to.equal('1', 'first item got extracted');
 
 607                     expect(oldItem1.getWlxmlClass() === undefined).to.equal(true, 'first extracted element has no wlxml class');
 
 609                     expect(oldItem2.children()[0].getText()).to.equal('2', 'second item got extracted');
 
 610                     expect(oldItem2.getWlxmlClass() === undefined).to.equal(true, 'second extracted element has no wlxml class');
 
 612                     expect(list2.is('list')).to.equal(true, 'last section child is a list');
 
 613                     expect(list2.children().length).to.equal(1, 'second list has one child');
 
 614                     expect(list2.children()[0].children()[0].getText()).to.equal('3', 'first item of the second list is a last item of the original list');
 
 617                 it('puts extracted items above the list if starting item is the first one', function() {
 
 618                     var c = canvas.fromXML('\
 
 620                             <div class="list.items">\
 
 621                                 <div class="item">0</div>\
 
 622                                 <div class="item">1</div>\
 
 623                                 <div class="item">2</div>\
 
 626                         list = c.doc().children()[0],
 
 627                         item1 = list.children()[0],
 
 628                         item2 = list.children()[1],
 
 629                         item3 = list.children()[2];
 
 631                     c.list.extractItems({element1: item1, element2: item2});
 
 633                     var section = c.doc(),
 
 634                         oldItem1 = section.children()[0],
 
 635                         oldItem2 = section.children()[1],
 
 636                         newList = section.children()[2];
 
 638                     expect(section.children().length).to.equal(3, 'section has three children');
 
 639                     expect(oldItem1.children()[0].getText()).to.equal('0', 'first item extracted');
 
 640                     expect(oldItem2.children()[0].getText()).to.equal('1', 'second item extracted');
 
 641                     expect(newList.is('list')).to.equal(true, 'list lies below extracted item');
 
 642                     expect(newList.children().length).to.equal(1, 'list has now one child');
 
 645                 it('puts extracted items below the list if ending item is the last one', function() {
 
 646                     var c = canvas.fromXML('\
 
 648                             <div class="list.items">\
 
 649                                 <div class="item">0</div>\
 
 650                                 <div class="item">1</div>\
 
 651                                 <div class="item">2</div>\
 
 654                         list = c.doc().children()[0],
 
 655                         item1 = list.children()[0],
 
 656                         item2 = list.children()[1],
 
 657                         item3 = list.children()[2];
 
 659                     c.list.extractItems({element1: item2, element2: item3});
 
 661                     var section = c.doc(),
 
 662                         oldItem1 = section.children()[1],
 
 663                         oldItem2 = section.children()[2],
 
 664                         newList = section.children()[0];
 
 666                     expect(section.children().length).to.equal(3, 'section has three children');
 
 667                     expect(oldItem1.children()[0].getText()).to.equal('1', 'first item extracted');
 
 668                     expect(oldItem2.children()[0].getText()).to.equal('2', 'second item extracted');
 
 669                     expect(newList.is('list')).to.equal(true, 'list lies above extracted item');
 
 670                     expect(newList.children().length).to.equal(1, 'list has now one child');
 
 673                 it('removes list if all its items are extracted', function() {
 
 674                     var c = canvas.fromXML('\
 
 676                             <div class="list.items">\
 
 677                                 <div class="item">some item</div>\
 
 678                                 <div class="item">some item 2</div>\
 
 681                         list = c.doc().children()[0],
 
 682                         item1 = list.children()[0],
 
 683                         item2 = list.children()[1];
 
 685                     c.list.extractItems({element1: item1, element2: item2});
 
 687                     var section = c.doc(),
 
 688                         list1 = section.children()[0],
 
 689                         oldItem1 = section.children()[0],
 
 690                         oldItem2 = section.children()[1];
 
 692                     expect(section.children().length).to.equal(2, 'section contains two children');
 
 693                     expect(oldItem1.children()[0].getText()).to.equal('some item');
 
 694                     expect(oldItem2.children()[0].getText()).to.equal('some item 2');
 
 697                 it('creates two lists with extracted items in the middle if extracting from the middle of the list - nested case' , function() {
 
 698                     var c = canvas.fromXML('\
 
 700                             <div class="list.items">\
 
 701                                 <div class="item">0</div>\
 
 703                                     <div class="list.items">\
 
 704                                         <div class="item">1.1</div>\
 
 705                                         <div class="item">1.2</div>\
 
 706                                         <div class="item">1.3</div>\
 
 709                                 <div class="item">2</div>\
 
 712                         list = c.doc().children()[0],
 
 713                         nestedList = list.children()[1].children()[0],
 
 714                         nestedListItem = nestedList.children()[1];
 
 716                     c.list.extractItems({element1: nestedListItem, element2: nestedListItem});
 
 718                     var section = c.doc(),
 
 719                         list = section.children()[0],
 
 720                         item1 = list.children()[0],
 
 721                         item2 = list.children()[1], //
 
 722                         item3 = list.children()[2],
 
 723                         item4 = list.children()[3], //
 
 724                         item5 = list.children()[4],
 
 725                         nestedList1 = item2.children()[0],
 
 726                         nestedList2 = item4.children()[0];
 
 728                     expect(list.children().length).to.equal(5, 'top list has five items');
 
 730                     expect(item1.children()[0].getText()).to.equal('0', 'first item ok');
 
 732                     expect(item2.getWlxmlClass()).to.equal('item', 'first nested list is still wrapped in item element');
 
 733                     expect(nestedList1.children().length).to.equal(1, 'first nested list is left with one child');
 
 734                     expect(nestedList1.children()[0].children()[0].getText()).to.equal('1.1', 'first nested list item left alone');
 
 736                     expect(item3.children()[0].getText()).to.equal('1.2', 'third item ok');
 
 738                     expect(item4.getWlxmlClass()).to.equal('item', 'second nested list is still wrapped in item element');
 
 739                     expect(nestedList2.children().length).to.equal(1, 'second nested list is left with one child');
 
 740                     expect(nestedList2.children()[0].children()[0].getText()).to.equal('1.3', 'second nested list item left alone');
 
 742                     expect(item5.children()[0].getText()).to.equal('2', 'last item ok');
 
 745                 it('puts extracted items below the list if ending item is the last one - nested case' , function() {
 
 746                     var c = canvas.fromXML('\
 
 748                             <div class="list.items">\
 
 749                                 <div class="item">0</div>\
 
 751                                     <div class="list.items">\
 
 752                                         <div class="item">1.1</div>\
 
 753                                         <div class="item">1.2</div>\
 
 754                                         <div class="item">1.3</div>\
 
 757                                 <div class="item">2</div>\
 
 760                         list = c.doc().children()[0],
 
 761                         nestedList = list.children()[1].children()[0],
 
 762                         nestedListItem1 = nestedList.children()[1],
 
 763                         nestedListItem2 = nestedList.children()[2];
 
 765                     c.list.extractItems({element1: nestedListItem1, element2: nestedListItem2});
 
 767                     var section = c.doc(),
 
 768                         list = section.children()[0],
 
 769                         item1 = list.children()[0],
 
 770                         item2 = list.children()[1],
 
 771                         item3 = list.children()[2],
 
 772                         item4 = list.children()[3],
 
 773                         item5 = list.children()[4];
 
 774                     nestedList = item2.children()[0];
 
 776                     expect(list.children().length).to.equal(5, 'top list has five items');
 
 777                     expect(item1.children()[0].getText()).to.equal('0', 'first item ok');
 
 778                     expect(item2.getWlxmlClass()).to.equal('item', 'nested list is still wrapped in item element');
 
 779                     expect(nestedList.children().length).to.equal(1, 'nested list is left with one child');
 
 780                     expect(nestedList.children()[0].children()[0].getText()).to.equal('1.1', 'nested list item left alone');
 
 781                     expect(item3.children()[0].getText()).to.equal('1.2', 'third item ok');
 
 782                     expect(item4.children()[0].getText()).to.equal('1.3', 'fourth item ok');
 
 783                     expect(item5.children()[0].getText()).to.equal('2', 'fifth item ok');
 
 786                 it('puts extracted items above the list if starting item is the first one - nested case' , function() {
 
 787                     var c = canvas.fromXML('\
 
 789                             <div class="list.items">\
 
 790                                 <div class="item">0</div>\
 
 792                                     <div class="list.items">\
 
 793                                         <div class="item">1.1</div>\
 
 794                                         <div class="item">1.2</div>\
 
 795                                         <div class="item">1.3</div>\
 
 798                                 <div class="item">2</div>\
 
 801                         list = c.doc().children()[0],
 
 802                         nestedList = list.children()[1].children()[0],
 
 803                         nestedListItem1 = nestedList.children()[0],
 
 804                         nestedListItem2 = nestedList.children()[1];
 
 806                     c.list.extractItems({element1: nestedListItem1, element2: nestedListItem2});
 
 808                     var section = c.doc(),
 
 809                         list = section.children()[0],
 
 810                         item1 = list.children()[0],
 
 811                         item2 = list.children()[1],
 
 812                         item3 = list.children()[2],
 
 813                         item4 = list.children()[3],
 
 814                         item5 = list.children()[4];
 
 815                     nestedList = item4.children()[0];
 
 817                     expect(list.children().length).to.equal(5, 'top list has five items');
 
 818                     expect(item1.children()[0].getText()).to.equal('0', 'first item ok');
 
 819                     expect(item2.children()[0].getText()).to.equal('1.1', 'second item ok');
 
 820                     expect(item3.children()[0].getText()).to.equal('1.2', 'third item ok');
 
 822                     expect(item4.getWlxmlClass()).to.equal('item', 'nested list is still wrapped in item element');
 
 823                     expect(nestedList.children().length).to.equal(1, 'nested list is left with one child');
 
 824                     expect(nestedList.children()[0].children()[0].getText()).to.equal('1.3', 'nested list item left alone');
 
 825                     expect(item5.children()[0].getText()).to.equal('2', 'fifth item ok');
 
 828                 it('removes list if all its items are extracted - nested case', function() {
 
 829                     var c = canvas.fromXML('\
 
 831                             <div class="list.items">\
 
 832                                 <div class="item">0</div>\
 
 834                                     <div class="list.items">\
 
 835                                         <div class="item">1.1</div>\
 
 836                                         <div class="item">1.2</div>\
 
 839                                 <div class="item">2</div>\
 
 842                         list = c.doc().children()[0],
 
 843                         nestedList = list.children()[1].children()[0],
 
 844                         nestedListItem1 = nestedList.children()[0],
 
 845                         nestedListItem2 = nestedList.children()[1];
 
 847                     c.list.extractItems({element1: nestedListItem1, element2: nestedListItem2});
 
 849                     var section = c.doc(),
 
 850                         list = section.children()[0],
 
 851                         item1 = list.children()[0],
 
 852                         item2 = list.children()[1],
 
 853                         item3 = list.children()[2],
 
 854                         item4 = list.children()[3];
 
 856                     expect(list.children().length).to.equal(4, 'top list has four items');
 
 857                     expect(item1.children()[0].getText()).to.equal('0', 'first item ok');
 
 858                     expect(item2.children()[0].getText()).to.equal('1.1', 'second item ok');
 
 859                     expect(item3.children()[0].getText()).to.equal('1.2', 'third item ok');
 
 860                     expect(item4.children()[0].getText()).to.equal('2', 'fourth item ok');
 
 863                 it('extracts items out of outer most list when merge flag is set to false', function() {
 
 864                     var c = canvas.fromXML('\
 
 866                             <div class="list.items">\
 
 867                                 <div class="item">0</div>\
 
 869                                     <div class="list.items">\
 
 870                                         <div class="item">1.1</div>\
 
 871                                         <div class="item">1.2</div>\
 
 874                                 <div class="item">2</div>\
 
 878                         list = section.children()[0],
 
 879                         nestedList = list.children()[1].children()[0],
 
 880                         nestedListItem = nestedList.children()[0];
 
 882                     var test = c.list.extractItems({element1: nestedListItem, element2: nestedListItem, merge: false});
 
 884                     expect(test).to.equal(true, 'extraction status ok');
 
 886                     var sectionChildren = section.children(),
 
 887                         extractedItem = sectionChildren[1];
 
 889                     expect(sectionChildren.length).to.equal(3, 'section has three children');
 
 890                     expect(sectionChildren[0].is('list')).to.equal(true, 'first child is a list');
 
 892                     expect(extractedItem.getWlxmlTag()).to.equal('div', 'extracted item is a wlxml div');
 
 893                     expect(extractedItem.getWlxmlClass()).to.equal(undefined, 'extracted item has no wlxml class');
 
 894                     expect(extractedItem.children()[0].getText()).to.equal('1.1', 'extracted item ok');
 
 895                     expect(sectionChildren[2].is('list')).to.equal(true, 'second child is a list');
 
 902     describe('Cursor', function() {
 
 906         beforeEach(function() {
 
 907             getSelection = sinon.stub(window, 'getSelection');
 
 910         afterEach(function() {
 
 911             getSelection.restore();
 
 914         it('returns position when browser selection collapsed', function() {
 
 915             var c = canvas.fromXML('<section>Alice has a cat</section>'),
 
 917                 text = dom.contents()[0];
 
 919             expect($(text).text()).to.equal('Alice has a cat');
 
 921             getSelection.returns({
 
 928             var cursor = c.getCursor(),
 
 929                 position = cursor.getPosition();
 
 931             expect(cursor.isSelecting()).to.equal(false, 'cursor is not selecting anything');
 
 932             expect(position.element.getText()).to.equal('Alice has a cat');
 
 933             expect(position.offset).to.equal(5);
 
 936         it('returns boundries of selection when browser selection not collapsed', function() {
 
 937             var c = canvas.fromXML('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
 
 940                     alice: dom.contents()[0],
 
 941                     has: $(dom.contents()[1]).contents()[0],
 
 942                     cat: dom.contents()[4]
 
 944                 cursor = c.getCursor(),
 
 945                 aliceElement = c.getDocumentElement(text.alice),
 
 946                 catElement = c.getDocumentElement(text.cat);
 
 950                     {focus: text.alice, focusOffset: 1, anchor: text.cat,   anchorOffset: 2, selectionAnchor: catElement},
 
 951                     {focus: text.cat,   focusOffset: 2, anchor: text.alice, anchorOffset: 1, selectionAnchor: aliceElement}
 
 952                 ].forEach(function(s, idx) {
 
 953                     getSelection.returns({isColapsed: false, anchorNode: s.anchor, anchorOffset: s.anchorOffset, focusNode: s.focus, focusOffset: s.focusOffset});
 
 955                     var selectionStart = cursor.getSelectionStart(),
 
 956                         selectionEnd = cursor.getSelectionEnd(),
 
 957                         selectionAnchor = cursor.getSelectionAnchor();
 
 959                     expect(cursor.isSelecting()).to.equal(true, 'cursor is selecting');
 
 960                     expect(selectionStart.element.sameNode(aliceElement)).to.equal(true, '"Alice" is the start of the selection ' + idx);
 
 961                     expect(selectionStart.offset).to.equal(1, '"Alice" offset ok' + idx);
 
 962                     expect(selectionEnd.element.sameNode(catElement)).to.equal(true, '"Cat" is the start of the selection ' + idx);
 
 963                     expect(selectionEnd.offset).to.equal(2, '"Cat" offset ok' + idx);
 
 964                     expect(selectionAnchor.element.sameNode(s.selectionAnchor)).to.equal(true, 'anchor ok');
 
 965                     expect(selectionAnchor.offset).to.equal(s.anchorOffset, 'anchor offset ok');
 
 969         it('recognizes when browser selection boundries lies in sibling DocumentTextElements', function() {
 
 970             var c = canvas.fromXML('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
 
 973                     alice: dom.contents()[0],
 
 974                     has: $(dom.contents()[1]).contents()[0],
 
 975                     a: dom.contents()[2],
 
 976                     big: $(dom.contents()[3]).contents()[0],
 
 977                     cat: dom.contents()[4]
 
 979                 cursor = c.getCursor();
 
 981             expect($(text.alice).text()).to.equal('Alice ');
 
 982             expect($(text.has).text()).to.equal('has');
 
 983             expect($(text.a).text()).to.equal(' a ');
 
 984             expect($(text.big).text()).to.equal('big');
 
 985             expect($(text.cat).text()).to.equal(' cat');
 
 987             getSelection.returns({anchorNode: text.alice, focusNode: text.a});
 
 988             expect(cursor.isSelectingSiblings()).to.equal(true, '"Alice" and "a" are children');
 
 990             getSelection.returns({anchorNode: text.alice, focusNode: text.cat});
 
 991             expect(cursor.isSelectingSiblings()).to.equal(true, '"Alice" and "cat" are children');
 
 993             getSelection.returns({anchorNode: text.alice, focusNode: text.has});
 
 994             expect(cursor.isSelectingSiblings()).to.equal(false, '"Alice" and "has" are not children');
 
 996             getSelection.returns({anchorNode: text.has, focusNode: text.big});
 
 997             expect(cursor.isSelectingSiblings()).to.equal(false, '"has" and "big" are not children');