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];
265 elementNode.transform('testTransformation');
269 textNode.transform('testTransformation');
273 doc.transform('testTransformation');
275 expect(doc.testMethod).to.be.undefined;
276 expect(elementNode.testMethod).to.be.undefined;
277 expect(textNode.testMethod).to.be.undefined;
280 it('allows adding method to a document', function() {
281 extension = {document: {methods: {
282 testMethod: function() { return this; }
285 doc.registerExtension(extension);
286 expect(doc.testMethod()).to.equal(doc, 'context is set to a document instance');
289 it('allows adding transformation to a document', function() {
290 extension = {document: {transformations: {
291 testTransformation: function() { return this; },
292 testTransformation2: {impl: function() { return this;}}
295 doc.registerExtension(extension);
296 expect(doc.transform('testTransformation')).to.equal(doc, 'context is set to a document instance');
297 expect(doc.transform('testTransformation2')).to.equal(doc, 'context is set to a document instance');
300 it('allows adding method to a DocumentNode instance', function() {
301 extension = {documentNode: {methods: {
302 testMethod: function() { return this; }
305 doc.registerExtension(extension);
306 expect(elementNode.testMethod().sameNode(elementNode)).to.equal(true, 'context is set to a node instance');
307 expect(textNode.testMethod().sameNode(textNode)).to.equal(true, 'context is set to a node instance');
310 it('allows adding transformation to a DocumentNode', function() {
311 extension = {documentNode: {transformations: {
312 testTransformation: function() { return this; },
313 testTransformation2: {impl: function() { return this;}}
316 doc.registerExtension(extension);
318 expect(elementNode.transform('testTransformation').sameNode(elementNode)).to.equal(true, '1');
319 expect(elementNode.transform('testTransformation2').sameNode(elementNode)).to.equal(true, '2');
320 expect(textNode.transform('testTransformation').sameNode(textNode)).to.equal(true, '3');
321 expect(textNode.transform('testTransformation2').sameNode(textNode)).to.equal(true, '4');
324 it('allows adding method to an ElementNode of specific class', function() {
325 extension = {wlxmlClass: {test_class: {methods: {
326 testMethod: function() { return this; }
328 doc.registerExtension(extension);
329 testClassNode = doc.root.contents()[1];
330 expect(testClassNode.object.testMethod().sameNode(testClassNode)).to.equal(true, '1');
333 it('allows adding transformation to an ElementNode of specific class', function() {
334 extension = {wlxmlClass: {test_class: {transformations: {
335 testTransformation: function() { return this; },
336 testTransformation2: {impl: function() { return this; }}
338 doc.registerExtension(extension);
339 testClassNode = doc.root.contents()[1];
340 expect(testClassNode.object.transform('testTransformation').sameNode(testClassNode)).to.equal(true, '1');
341 expect(testClassNode.object.transform('testTransformation2').sameNode(testClassNode)).to.equal(true, '1');