4 ], function(chai, wlxml) {
 
   9 /* global it, describe */
 
  11 var expect = chai.expect;
 
  13 var nodeFromXML = function(xml) {
 
  14     return wlxml.WLXMLElementNodeFromXML(xml);
 
  17 var getDocumentFromXML = function(xml, options) {
 
  18     return wlxml.WLXMLDocumentFromXML(xml, options || {});
 
  22 describe('WLXMLDocument', function() {
 
  24     describe('Basic wlxml element node properties', function() {
 
  25         it('returns its class', function() {
 
  26             var node = nodeFromXML('<header class="class.subclass"></header>');
 
  27             expect(node.getClass()).to.equal('class.subclass');
 
  30         it('returns attributes other than class and meta-* as other attributes', function() {
 
  31             var node = nodeFromXML('<span class="uri" meta-attr="val" attr1="val1" attr2="val2"></span>');
 
  32             expect(node.getOtherAttributes()).to.eql({attr1: 'val1', attr2: 'val2'});
 
  36     describe('WLXML node meta attributes', function() {
 
  38         it('inherits keys from super classes', function() {
 
  41                         attrs: {'common': {type: 'string'}}
 
  44                         attrs: {'a_attr': {type: 'string'}}
 
  47                         attrs: {'a_b_attr': {type: 'string'}}
 
  50                         attrs: {'a_b_c_attr': {type: 'string'}}
 
  53                 doc = getDocumentFromXML('<section></section>', {wlxmlClasses: testClasses}),
 
  56             expect(section.getMetaAttributes().keys()).to.eql(['common']);
 
  58             section.setClass('a');
 
  59             expect(section.getMetaAttributes().keys().sort()).to.eql(['common', 'a_attr'].sort());
 
  61             section.setClass('a.b');
 
  62             expect(section.getMetaAttributes().keys().sort()).to.eql(['common', 'a_attr', 'a_b_attr'].sort());
 
  64             section.setClass('a.b.c');
 
  65             expect(section.getMetaAttributes().keys().sort()).to.eql(['common', 'a_attr', 'a_b_attr', 'a_b_c_attr'].sort());
 
  68         describe('api', function() {
 
  69             it('returns meta attributes as a dict', function() {
 
  73                                 attr1: {type: 'string'},
 
  78                     node = getDocumentFromXML(
 
  79                         '<span class="test" meta-attr1="val1" meta-attr2="2014-01-01"></span>',
 
  80                         {wlxmlClasses: testClasses}
 
  82                     attrs = node.getMetaAttributes();
 
  84                 expect(attrs.keys().sort()).to.eql(['attr1', 'attr2'].sort());
 
  85                 expect(attrs.attr1.value).to.equal('val1');
 
  86                 expect(attrs.attr1.type).to.equal('string');
 
  87                 expect(attrs.attr2.value).to.equal('2014-01-01');
 
  88                 expect(attrs.attr2.type).to.equal('date');
 
  90             it('returns undefined value if attribute is missing', function() {
 
  94                                 attr1: {type: 'string'},
 
  98                     node = getDocumentFromXML('<span class="test"></span>', {wlxmlClasses: testClasses}).root,
 
  99                     attrs = node.getMetaAttributes();
 
 100                     expect(attrs.attr1.value).to.be.undefined;
 
 105     describe('White space handling', function() {
 
 106         it('ignores white space surrounding block elements', function() {
 
 107             var node = nodeFromXML('<section> <div></div> </section>'),
 
 108                 contents = node.contents();
 
 109             expect(contents).to.have.length(1);
 
 110             expect(contents[0].nodeType).to.equal(Node.ELEMENT_NODE);
 
 112         it('ignores white space between block elements', function() {
 
 113             var node = nodeFromXML('<section><div></div> <div></div></section>'),
 
 114             contents = node.contents();
 
 115             expect(contents).to.have.length(2);
 
 116             [0,1].forEach(function(idx) {
 
 117                 expect(contents[idx].nodeType).to.equal(Node.ELEMENT_NODE);
 
 120         it('trims white space from the beginning and the end of the block elements', function() {
 
 121             var node = nodeFromXML('<section> Alice <span>has</span> a cat </section>');
 
 122             expect(node.contents()[0].getText()).to.equal('Alice ');
 
 123             expect(node.contents()[2].getText()).to.equal(' a cat');
 
 125         it('normalizes string of white characters to one space at the inline element boundries', function() {
 
 126             var node = nodeFromXML('<span>   Alice has a cat   </span>');
 
 127             expect(node.contents()[0].getText()).to.equal(' Alice has a cat ');
 
 129         it('normalizes string of white characters to one space before inline element', function() {
 
 130             var node = nodeFromXML('<div>Alice has  <span>a cat</span></div>');
 
 131             expect(node.contents()[0].getText()).to.equal('Alice has ');
 
 133         it('normalizes string of white characters to one space after inline element', function() {
 
 134             var node = nodeFromXML('<div>Alice has <span>a</span>  cat</div>');
 
 135             expect(node.contents()[2].getText()).to.equal(' cat');
 
 139     describe('formatting output xml', function() {
 
 141         /*jshint multistr: true */
 
 143         it('keeps white space between XML nodes', function() {
 
 144             var xmlIn = '<section>\n\n\n<div></div>\n\n\n<div></div>\n\n\n</section>',
 
 145             doc = getDocumentFromXML(xmlIn),
 
 146             xmlOut = doc.toXML();
 
 148             var partsIn = xmlIn.split('\n\n\n'),
 
 149                 partsOut = xmlOut.split('\n\n\n');
 
 151             expect(partsIn).to.deep.equal(partsOut);
 
 154         it('keeps white space between XML nodes - inline case', function() {
 
 155             var xmlIn = '<section>\n\n\n<span></span>\n\n\n<span></span>\n\n\n</section>',
 
 156                 doc = getDocumentFromXML(xmlIn),
 
 157                 xmlOut = doc.toXML();
 
 159             var partsIn = xmlIn.split('\n\n\n'),
 
 160                 partsOut = xmlOut.split('\n\n\n');
 
 161             expect(partsIn).to.deep.equal(partsOut);
 
 164         it('keeps white space at the beginning of text', function() {
 
 165             var xmlIn = '<section>    abc<div>some div</div>    abc</section>',
 
 166                 doc = getDocumentFromXML(xmlIn),
 
 167                 xmlOut = doc.toXML();
 
 169             expect(xmlOut).to.equal(xmlIn);
 
 172         // it('nests new children block elements', function() {
 
 173         //     var doc = getDocumentFromXML('<section></section>');
 
 175         //     doc.root.append({tag: 'header'});
 
 177         //     var xmlOut = doc.toXML();
 
 178         //     expect(xmlOut.split('\n  ')[0]).to.equal('<section>', 'nesting start ok');
 
 179         //     expect(xmlOut.split('\n').slice(-1)[0]).to.equal('</section>', 'nesting end ok');
 
 183         // it('doesn\'t nest new children inline elements', function() {
 
 184         //     var doc = getDocumentFromXML('<section></section>');
 
 186         //     doc.root.append({tag: 'span'});
 
 188         //     var xmlOut = doc.toXML();
 
 189         //     expect(xmlOut).to.equal('<section><span></span></section>');
 
 192         it('keeps original white space at the end of text', function() {
 
 194             var xmlIn = '<header>    Some text ended with white space \
 
 196             <span class="uri">Some text</span> some text\
 
 199                 doc = getDocumentFromXML(xmlIn),
 
 200                 xmlOut = doc.toXML();
 
 202             expect(xmlOut).to.equal(xmlIn);
 
 205         it('keeps white space around text node', function() {
 
 206             var xmlIn = '<section>\
 
 207             <header>header1</header>\
 
 208             Some text surrounded by white space\
 
 209             <header>header2</header>\
 
 211                 doc = getDocumentFromXML(xmlIn),
 
 212                 xmlOut = doc.toXML();
 
 213             expect(xmlOut).to.equal(xmlIn);
 
 216         it('keeps white space around text node - last node case', function() {
 
 217             var xmlIn = '<section>\
 
 218             <header>header</header>\
 
 220             Some text surrounded by white space\
 
 223                 doc = getDocumentFromXML(xmlIn),
 
 224                 xmlOut = doc.toXML();
 
 226             expect(xmlOut).to.equal(xmlIn);
 
 229         it('keeps white space after detaching text element', function() {
 
 230             var xmlIn = '<section><header>header</header>\n\
 
 235                 expectedXmlOut = '<section><header>header</header>\n\
 
 240                 doc = getDocumentFromXML(xmlIn),
 
 241                 contents = doc.root.contents(),
 
 242                 text = contents[contents.length-1];
 
 244             expect(text.getText()).to.equal('text1');
 
 248             var xmlOut = doc.toXML();
 
 249             expect(xmlOut).to.equal(expectedXmlOut);
 
 254     describe('Extension', function() {
 
 255         var doc, extension, elementNode, textNode, testClassNode;
 
 257         beforeEach(function() {
 
 258             doc = getDocumentFromXML('<section>Alice<div class="test_class"></div></section>');
 
 259             elementNode = doc.root;
 
 260             textNode = doc.root.contents()[0];
 
 264                 elementNode.transform('testTransformation');
 
 267                 textNode.transform('testTransformation');
 
 270                 doc.transform('testTransformation');
 
 272             expect(doc.testMethod).to.be.undefined;
 
 273             expect(elementNode.testMethod).to.be.undefined;
 
 274             expect(textNode.testMethod).to.be.undefined;
 
 276             // spr+ a expect dotyczacy object api?
 
 279         it('allows adding method to a document', function() {
 
 280             extension = {document: {methods: {
 
 281                 testMethod: function() { return this; }
 
 284             doc.registerExtension(extension);
 
 285             expect(doc.testMethod()).to.equal(doc, 'context is set to a document instance');
 
 288         it('allows adding transformation to a document', function() {
 
 289             extension = {document: {transformations: {
 
 290                 testTransformation: function() { return this; },
 
 291                 testTransformation2: {impl: function() { return this;}}
 
 294             doc.registerExtension(extension);
 
 295             expect(doc.transform('testTransformation')).to.equal(doc, 'context is set to a document instance');
 
 296             expect(doc.transform('testTransformation2')).to.equal(doc, 'context is set to a document instance');
 
 299         it('allows adding method to a DocumentNode instance', function() {
 
 300             extension = {documentNode: {methods: {
 
 301                 testMethod: function() { return this; }    
 
 304             doc.registerExtension(extension);
 
 307             elementNode = doc.root;
 
 308             textNode = doc.root.contents()[0];
 
 310             expect(elementNode.testMethod().sameNode(elementNode)).to.equal(true, 'context is set to a node instance');
 
 311             expect(textNode.testMethod().sameNode(textNode)).to.equal(true, 'context is set to a node instance');
 
 314         it('allows adding transformation to a DocumentNode', function() {
 
 315             extension = {documentNode: {transformations: {
 
 316                 testTransformation: function() { return this; },
 
 317                 testTransformation2: {impl: function() { return this;}}
 
 320             doc.registerExtension(extension);
 
 322             expect(elementNode.transform('testTransformation').sameNode(elementNode)).to.equal(true, '1');
 
 323             expect(elementNode.transform('testTransformation2').sameNode(elementNode)).to.equal(true, '2');
 
 324             expect(textNode.transform('testTransformation').sameNode(textNode)).to.equal(true, '3');
 
 325             expect(textNode.transform('testTransformation2').sameNode(textNode)).to.equal(true, '4');
 
 328         it('allows adding method to an ElementNode of specific class', function() {
 
 329             extension = {wlxmlClass: {test_class: {methods: {
 
 330                 testMethod: function() { return this; }
 
 332             doc.registerExtension(extension);
 
 333             testClassNode = doc.root.contents()[1];
 
 334             expect(testClassNode.object.testMethod().sameNode(testClassNode)).to.equal(true, '1');
 
 337         it('allows adding transformation to an ElementNode of specific class', function() {
 
 338             extension = {wlxmlClass: {test_class: {transformations: {
 
 339                 testTransformation: function() { return this; },
 
 340                 testTransformation2: {impl: function() { return this; }}
 
 342             doc.registerExtension(extension);
 
 343             testClassNode = doc.root.contents()[1];
 
 344             expect(testClassNode.object.transform('testTransformation').sameNode(testClassNode)).to.equal(true, '1');
 
 345             expect(testClassNode.object.transform('testTransformation2').sameNode(testClassNode)).to.equal(true, '1');