7c69bdbf3666bfc54a2f1935171dd747ce0210c1
[fnpeditor.git] / src / wlxml / wlxml.test.js
1 define([
2     'libs/chai',
3     './wlxml.js'
4 ], function(chai, wlxml) {
5     
6 'use strict';
7
8 /* jshint expr:true */
9 /* global it, describe, beforeEach */
10
11 var expect = chai.expect;
12
13 var nodeFromXML = function(xml) {
14     return wlxml.WLXMLElementNodeFromXML(xml);
15 };
16
17 var getDocumentFromXML = function(xml, options) {
18     return wlxml.WLXMLDocumentFromXML(xml, options || {});
19 };
20
21
22 describe('WLXMLDocument', function() {
23     
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');
28         });
29
30         it('returns its class hierarchy', function() {
31             var node = nodeFromXML('<div class="a.b.c"></div>');
32             expect(node.getClassHierarchy()).to.eql(['', 'a', 'a.b', 'a.b.c']);
33         });
34     });
35
36     describe('White space handling', function() {
37         /* globals Node */
38
39         it('ignores white space surrounding block elements', function() {
40             var node = nodeFromXML('<section> <div></div> </section>'),
41                 contents = node.contents();
42             expect(contents).to.have.length(1);
43             expect(contents[0].nodeType).to.equal(Node.ELEMENT_NODE);
44         });
45         it('ignores white space between block elements', function() {
46             var node = nodeFromXML('<section><div></div> <div></div></section>'),
47             contents = node.contents();
48             expect(contents).to.have.length(2);
49             [0,1].forEach(function(idx) {
50                 expect(contents[idx].nodeType).to.equal(Node.ELEMENT_NODE);
51             });
52         });
53         it('trims white space from the beginning and the end of the block elements', function() {
54             var node = nodeFromXML('<section> Alice <span>has</span> a cat </section>');
55             expect(node.contents()[0].getText()).to.equal('Alice ');
56             expect(node.contents()[2].getText()).to.equal(' a cat');
57         });
58         it('normalizes string of white characters to one space at the inline element boundries', function() {
59             var node = nodeFromXML('<span>   Alice has a cat   </span>');
60             expect(node.contents()[0].getText()).to.equal(' Alice has a cat ');
61         });
62         it('normalizes string of white characters to one space before inline element', function() {
63             var node = nodeFromXML('<div>Alice has  <span>a cat</span></div>');
64             expect(node.contents()[0].getText()).to.equal('Alice has ');
65         });
66         it('normalizes string of white characters to one space after inline element', function() {
67             var node = nodeFromXML('<div>Alice has <span>a</span>  cat</div>');
68             expect(node.contents()[2].getText()).to.equal(' cat');
69         });
70     });
71
72     describe('formatting output xml', function() {
73
74         /*jshint multistr: true */
75
76         it('keeps white space between XML nodes', function() {
77             var xmlIn = '<section>\n\n\n<div></div>\n\n\n<div></div>\n\n\n</section>',
78             doc = getDocumentFromXML(xmlIn),
79             xmlOut = doc.toXML();
80
81             var partsIn = xmlIn.split('\n\n\n'),
82                 partsOut = xmlOut.split('\n\n\n');
83
84             expect(partsIn).to.deep.equal(partsOut);
85         });
86
87         it('keeps white space between XML nodes - inline case', function() {
88             var xmlIn = '<section>\n\n\n<span></span>\n\n\n<span></span>\n\n\n</section>',
89                 doc = getDocumentFromXML(xmlIn),
90                 xmlOut = doc.toXML();
91
92             var partsIn = xmlIn.split('\n\n\n'),
93                 partsOut = xmlOut.split('\n\n\n');
94             expect(partsIn).to.deep.equal(partsOut);
95         });
96
97         it('keeps white space at the beginning of text', function() {
98             var xmlIn = '<section>    abc<div>some div</div>    abc</section>',
99                 doc = getDocumentFromXML(xmlIn),
100                 xmlOut = doc.toXML();
101
102             expect(xmlOut).to.equal(xmlIn);
103         });
104
105         // it('nests new children block elements', function() {
106         //     var doc = getDocumentFromXML('<section></section>');
107     
108         //     doc.root.append({tag: 'header'});
109
110         //     var xmlOut = doc.toXML();
111         //     expect(xmlOut.split('\n  ')[0]).to.equal('<section>', 'nesting start ok');
112         //     expect(xmlOut.split('\n').slice(-1)[0]).to.equal('</section>', 'nesting end ok');
113
114         // });
115
116         // it('doesn\'t nest new children inline elements', function() {
117         //     var doc = getDocumentFromXML('<section></section>');
118     
119         //     doc.root.append({tag: 'span'});
120
121         //     var xmlOut = doc.toXML();
122         //     expect(xmlOut).to.equal('<section><span></span></section>');
123         // });
124
125         it('keeps original white space at the end of text', function() {
126             
127             var xmlIn = '<header>    Some text ended with white space \
128             \
129             <span class="uri">Some text</span> some text\
130         \
131         </header>',
132                 doc = getDocumentFromXML(xmlIn),
133                 xmlOut = doc.toXML();
134         
135             expect(xmlOut).to.equal(xmlIn);
136         });
137
138         it('keeps white space around text node', function() {
139             var xmlIn = '<section>\
140             <header>header1</header>\
141             Some text surrounded by white space\
142             <header>header2</header>\
143         </section>',
144                 doc = getDocumentFromXML(xmlIn),
145                 xmlOut = doc.toXML();
146             expect(xmlOut).to.equal(xmlIn);
147         });
148
149         it('keeps white space around text node - last node case', function() {
150             var xmlIn = '<section>\
151             <header>header</header>\
152                 \
153             Some text surrounded by white space\
154                 \
155         </section>',
156                 doc = getDocumentFromXML(xmlIn),
157                 xmlOut = doc.toXML();
158
159             expect(xmlOut).to.equal(xmlIn);
160         });
161
162         it('keeps white space after detaching text element', function() {
163             var xmlIn = '<section><header>header</header>\n\
164                 \n\
165             text1\n\
166                 \n\
167         </section>',
168                 expectedXmlOut = '<section><header>header</header>\n\
169                 \n\
170             \n\
171                 \n\
172         </section>',
173                 doc = getDocumentFromXML(xmlIn),
174                 contents = doc.root.contents(),
175                 text = contents[contents.length-1];
176             
177             expect(text.getText()).to.equal('text1');
178
179             text.detach();
180
181             var xmlOut = doc.toXML();
182             expect(xmlOut).to.equal(expectedXmlOut);
183         });
184
185     });
186
187     describe('Extension', function() {
188         var doc, extension, elementNode, textNode, testClassNode;
189
190         beforeEach(function() {
191             doc = getDocumentFromXML('<section>Alice<div class="test_class"></div><div class="test_class.a"></div></section>');
192             elementNode = doc.root;
193             textNode = doc.root.contents()[0];
194             testClassNode = doc.root.contents('.test_class');
195             extension = {};
196             
197             expect(testClassNode.object).to.be.undefined;
198
199         });
200
201         it('allows adding method to an ElementNode of specific class', function() {
202             extension = {wlxmlClass: {test_class: {methods: {
203                 testMethod: function() { return this; }
204             }}}};
205             doc.registerExtension(extension);
206             testClassNode = doc.root.contents()[1];
207             expect(testClassNode.object.testMethod().sameNode(testClassNode)).to.equal(true, '1');
208         });
209
210         it('allows adding non-function properties to an ElementNode of specific class', function() {
211             extension = {wlxmlClass: {test_class: {methods: {
212                 testProp: 123
213             }}}};
214             doc.registerExtension(extension);
215             testClassNode = doc.root.contents()[1];
216             expect(testClassNode.object.testProp).to.equal(123);
217         });
218
219         it('allows adding transformation to an ElementNode of specific class', function() {
220             extension = {wlxmlClass: {test_class: {transformations: {
221                 testTransformation: function() { return this; },
222                 testTransformation2: {impl: function() { return this; }}
223             }}}};
224             doc.registerExtension(extension);
225             testClassNode = doc.root.contents()[1];
226             expect(testClassNode.object.testTransformation().sameNode(testClassNode)).to.equal(true, '1');
227             expect(testClassNode.object.testTransformation2().sameNode(testClassNode)).to.equal(true, '1');
228         });
229
230         it('added methods are inherited by nodes with subclasses', function() {
231             extension = {wlxmlClass: {test_class: {methods: {
232                 testMethod: function() { return this; }
233             }}}};
234             doc.registerExtension(extension);
235             testClassNode = doc.root.contents()[2];
236             expect(testClassNode.object.testMethod().sameNode(testClassNode)).to.equal(true);
237         });
238         it('added transformations are inherited by nodes with subclasses', function() {
239             extension = {wlxmlClass: {test_class: {transformations: {
240                 testTransformation: function() { return this; },
241                 testTransformation2: {impl: function() { return this; }}
242             }}}};
243             doc.registerExtension(extension);
244             testClassNode = doc.root.contents()[2];
245             expect(testClassNode.object.testTransformation().sameNode(testClassNode)).to.equal(true, '1');
246             expect(testClassNode.object.testTransformation2().sameNode(testClassNode)).to.equal(true, '2');
247         });
248     });
249 });
250
251 });