wip: moving non wlxml specific extension support from wlxml.js to smartxml.js
[fnpeditor.git] / src / wlxml / extensions / list / list.test.js
1 define(function(require) {
2     
3 'use strict';
4
5 var chai = require('libs/chai'),
6     wlxml = require('wlxml/wlxml'),
7     expect = chai.expect,
8     $ = require('libs/jquery'),
9     listsExtension = require('wlxml/extensions/list/list');
10
11
12 var getDocumentFromXML = function(xml, options) {
13     var doc = wlxml.WLXMLDocumentFromXML(xml, options || {});
14     doc.registerExtension(listsExtension);
15     return doc;
16 };
17
18 var removeEmptyTextNodes = function(xml) {
19     xml = $($.trim(xml));
20     xml.find(':not(iframe)')
21         .addBack()
22         .contents()
23         .filter(function() {return this.nodeType === Node.TEXT_NODE;})
24         .each(function() {
25             if(!this.data.length) {
26                 $(this).remove();
27             }
28         });
29     return $('<w>').append(xml).html();
30 };
31
32
33 describe('Lists extension', function() {
34
35     describe('creating lists', function() {
36         it('allows creation of a list from existing sibling DocumentElements', function() {
37             var doc = getDocumentFromXML('<section>Alice<div>has</div>a<div>cat</div></section>'),
38                 section = doc.root,
39                 div1 = section.contents()[1],
40                 textA = section.contents()[2];
41             
42             doc.transform('createList', {node1: div1, node2: textA});
43
44             expect(section.contents().length).to.equal(3, 'section has three child nodes');
45
46             var child1 = section.contents()[0],
47                 list = section.contents()[1],
48                 child3 = section.contents()[2];
49
50             expect(child1.getText()).to.equal('Alice');
51             expect(list.is('list')).to.equal(true, 'second child is a list');
52             expect(list.contents().length).to.equal(2, 'list contains two elements');
53             list.contents().forEach(function(child) {
54                  expect(child.getClass()).to.equal('item', 'list childs have wlxml class of item');
55             });
56             expect(child3.contents()[0].getText()).to.equal('cat');
57         });
58
59         it('allows creating nested list from existing sibling list items', function() {
60             var doc = getDocumentFromXML('\
61                 <section>\
62                     <div class="list">\
63                         <div class="item">A</div>\
64                         <div class="item">B</div>\
65                         <div class="item">C</div>\
66                         <div class="item">D</div>\
67                     </div>\
68                 </section>');
69                 
70                 var outerList = doc.root.contents('.list')[0],
71                 itemB = outerList.contents('.item')[1],
72                 itemC = outerList.contents('.item')[2];
73
74             
75             doc.transform('createList', {node1: itemB, node2: itemC});
76
77             var outerListItems = outerList.contents('.item'),
78                 innerList = outerListItems[1].contents()[0];
79             
80             var innerListItems = innerList.contents('.item');
81
82             expect(outerListItems.length).to.equal(3, 'outer list has three items');
83             expect(outerListItems[0].contents()[0].getText()).to.equal('A', 'first outer item ok');
84             expect(outerListItems[1].getClass()).to.equal('item', 'inner list is wrapped by item element');
85
86             expect(innerList.is('list')).to.equal(true, 'inner list created');
87             expect(innerListItems.length).to.equal(2, 'inner list has two items');
88             expect(innerListItems[0].contents()[0].getText()).to.equal('B', 'first inner item ok');
89             expect(innerListItems[1].contents()[0].getText()).to.equal('C', 'second inner item ok');
90
91             expect(outerListItems[2].contents()[0].getText()).to.equal('D', 'last outer item ok');
92
93         });
94     });
95
96     describe('extracting list items', function() {
97         it('creates two lists with extracted items in the middle if extracting from the middle of the list', function() {
98             var doc = getDocumentFromXML(removeEmptyTextNodes('\
99                 <section>\
100                     <div class="list">\
101                         <div class="item">0</div>\
102                         <div class="item">1</div>\
103                         <div class="item">2</div>\
104                         <div class="item">3</div>\
105                     </div>\
106                 </section>')),
107                 list = doc.root.contents()[0],
108                 item1 = list.contents()[1],
109                 item2 = list.contents()[2];
110
111             doc.transform('extractItems', {item1: item1, item2: item2});
112
113             var section = doc.root,
114                 list1 = section.contents()[0],
115                 oldItem1 = section.contents()[1],
116                 oldItem2 = section.contents()[2],
117                 list2 = section.contents()[3];
118
119             expect(section.contents().length).to.equal(4, 'section contains two old items and two lists');
120             
121             expect(list1.is('list')).to.equal(true, 'first section child is a list');
122             expect(list1.contents().length).to.equal(1, 'first list has one child');
123             expect(list1.contents()[0].contents()[0].getText()).to.equal('0', 'first item of the first list is a first item of the original list');
124
125             expect(oldItem1.contents()[0].getText()).to.equal('1', 'first item got extracted');
126             expect(oldItem1.getClass() === '').to.equal(true, 'first extracted element has no wlxml class');
127
128             expect(oldItem2.contents()[0].getText()).to.equal('2', 'second item got extracted');
129             expect(oldItem2.getClass() === '').to.equal(true, 'second extracted element has no wlxml class');
130
131             expect(list2.is('list')).to.equal(true, 'last section child is a list');
132             expect(list2.contents().length).to.equal(1, 'second list has one child');
133             expect(list2.contents()[0].contents()[0].getText()).to.equal('3', 'first item of the second list is a last item of the original list');
134         });
135
136         it('puts extracted items above the list if starting item is the first one', function() {
137             var doc = getDocumentFromXML(removeEmptyTextNodes('\
138                 <section>\
139                     <div class="list">\
140                         <div class="item">0</div>\
141                         <div class="item">1</div>\
142                         <div class="item">2</div>\
143                     </div>\
144                 </section>')),
145                 list = doc.root.contents()[0],
146                 item1 = list.contents()[0],
147                 item2 = list.contents()[1],
148                 item3 = list.contents()[2];
149
150             doc.transform('extractItems', {item1: item1, item2: item2});
151
152             var section = doc.root,
153                 oldItem1 = section.contents()[0],
154                 oldItem2 = section.contents()[1],
155                 newList = section.contents()[2];
156
157             expect(section.contents().length).to.equal(3, 'section has three children');
158             expect(oldItem1.contents()[0].getText()).to.equal('0', 'first item extracted');
159             expect(oldItem2.contents()[0].getText()).to.equal('1', 'second item extracted');
160             expect(newList.is('list')).to.equal(true, 'list lies below extracted item');
161             expect(newList.contents().length).to.equal(1, 'list has now one child');
162         });
163
164         it('puts extracted items below the list if ending item is the last one', function() {
165             var doc = getDocumentFromXML(removeEmptyTextNodes('\
166                 <section>\
167                     <div class="list">\
168                         <div class="item">0</div>\
169                         <div class="item">1</div>\
170                         <div class="item">2</div>\
171                     </div>\
172                 </section>')),
173                 list = doc.root.contents()[0],
174                 item1 = list.contents()[0],
175                 item2 = list.contents()[1],
176                 item3 = list.contents()[2];
177
178             doc.transform('extractItems', {item1: item2, item2: item3});
179
180             var section = doc.root,
181                 oldItem1 = section.contents()[1],
182                 oldItem2 = section.contents()[2],
183                 newList = section.contents()[0];
184
185             expect(section.contents().length).to.equal(3, 'section has three children');
186             expect(oldItem1.contents()[0].getText()).to.equal('1', 'first item extracted');
187             expect(oldItem2.contents()[0].getText()).to.equal('2', 'second item extracted');
188             expect(newList.is('list')).to.equal(true, 'list lies above extracted item');
189             expect(newList.contents().length).to.equal(1, 'list has now one child');
190         });
191
192         it('removes list if all its items are extracted', function() {
193             var doc = getDocumentFromXML(removeEmptyTextNodes('\
194                 <section>\
195                     <div class="list">\
196                         <div class="item">some item</div>\
197                         <div class="item">some item 2</div>\
198                     </div>\
199                 </section>')),
200                 list = doc.root.contents()[0],
201                 item1 = list.contents()[0],
202                 item2 = list.contents()[1];
203
204             doc.transform('extractItems', {item1: item1, item2: item2});
205
206             var section = doc.root,
207                 oldItem1 = section.contents()[0],
208                 oldItem2 = section.contents()[1];
209
210             expect(section.contents().length).to.equal(2, 'section contains two children');
211             expect(oldItem1.contents()[0].getText()).to.equal('some item');
212             expect(oldItem2.contents()[0].getText()).to.equal('some item 2');
213         });
214
215         it('creates two lists with extracted items in the middle if extracting from the middle of the list - nested case' , function() {
216             var doc = getDocumentFromXML(removeEmptyTextNodes('\
217                 <section>\
218                     <div class="list">\
219                         <div class="item">0</div>\
220                         <div class="item">\
221                             <div class="list.items">\
222                                 <div class="item">1.1</div>\
223                                 <div class="item">1.2</div>\
224                                 <div class="item">1.3</div>\
225                             </div>\
226                         </div>\
227                         <div class="item">2</div>\
228                     </div>\
229                 </section>')),
230                 list = doc.root.contents()[0],
231                 nestedList = list.contents()[1].contents()[0],
232                 nestedListItem = nestedList.contents()[1];
233
234             doc.transform('extractItems', {item1: nestedListItem, item2: nestedListItem});
235
236             var section = doc.root,
237                 list = section.contents()[0],
238                 item1 = list.contents()[0],
239                 item2 = list.contents()[1], //
240                 item3 = list.contents()[2],
241                 item4 = list.contents()[3], //
242                 item5 = list.contents()[4],
243                 nestedList1 = item2.contents()[0],
244                 nestedList2 = item4.contents()[0];
245
246             expect(list.contents().length).to.equal(5, 'top list has five items');
247             
248             expect(item1.contents()[0].getText()).to.equal('0', 'first item ok');
249
250             expect(item2.getClass()).to.equal('item', 'first nested list is still wrapped in item element');
251             expect(nestedList1.contents().length).to.equal(1, 'first nested list is left with one child');
252             expect(nestedList1.contents()[0].contents()[0].getText()).to.equal('1.1', 'first nested list item left alone');
253             
254             expect(item3.contents()[0].getText()).to.equal('1.2', 'third item ok');
255
256             expect(item4.getClass()).to.equal('item', 'second nested list is still wrapped in item element');
257             expect(nestedList2.contents().length).to.equal(1, 'second nested list is left with one child');
258             expect(nestedList2.contents()[0].contents()[0].getText()).to.equal('1.3', 'second nested list item left alone');
259
260             expect(item5.contents()[0].getText()).to.equal('2', 'last item ok');
261         });
262
263         it('puts extracted items below the list if ending item is the last one - nested case' , function() {
264             var doc = getDocumentFromXML(removeEmptyTextNodes('\
265                 <section>\
266                     <div class="list.items">\
267                         <div class="item">0</div>\
268                         <div class="item">\
269                             <div class="list.items">\
270                                 <div class="item">1.1</div>\
271                                 <div class="item">1.2</div>\
272                                 <div class="item">1.3</div>\
273                             </div>\
274                         </div>\
275                         <div class="item">2</div>\
276                     </div>\
277                 </section>')),
278                 list = doc.root.contents()[0],
279                 nestedList = list.contents()[1].contents()[0],
280                 nestedListItem1 = nestedList.contents()[1],
281                 nestedListItem2 = nestedList.contents()[2];
282
283             doc.transform('extractItems', {item1: nestedListItem1, item2: nestedListItem2});
284
285             var section = doc.root,
286                 list = section.contents()[0],
287                 item1 = list.contents()[0],
288                 item2 = list.contents()[1],
289                 item3 = list.contents()[2],
290                 item4 = list.contents()[3],
291                 item5 = list.contents()[4];
292             nestedList = item2.contents()[0];
293
294             expect(list.contents().length).to.equal(5, 'top list has five items');
295             expect(item1.contents()[0].getText()).to.equal('0', 'first item ok');
296             expect(item2.getClass()).to.equal('item', 'nested list is still wrapped in item element');
297             expect(nestedList.contents().length).to.equal(1, 'nested list is left with one child');
298             expect(nestedList.contents()[0].contents()[0].getText()).to.equal('1.1', 'nested list item left alone');
299             expect(item3.contents()[0].getText()).to.equal('1.2', 'third item ok');
300             expect(item4.contents()[0].getText()).to.equal('1.3', 'fourth item ok');
301             expect(item5.contents()[0].getText()).to.equal('2', 'fifth item ok');
302         });
303
304         it('puts extracted items above the list if starting item is the first one - nested case' , function() {
305             var doc = getDocumentFromXML(removeEmptyTextNodes('\
306                 <section>\
307                     <div class="list.items">\
308                         <div class="item">0</div>\
309                         <div class="item">\
310                             <div class="list.items">\
311                                 <div class="item">1.1</div>\
312                                 <div class="item">1.2</div>\
313                                 <div class="item">1.3</div>\
314                             </div>\
315                         </div>\
316                         <div class="item">2</div>\
317                     </div>\
318                 </section>')),
319                 list = doc.root.contents()[0],
320                 nestedList = list.contents()[1].contents()[0],
321                 nestedListItem1 = nestedList.contents()[0],
322                 nestedListItem2 = nestedList.contents()[1];
323
324             doc.transform('extractItems', {item1: nestedListItem1, item2: nestedListItem2});
325
326             var section = doc.root,
327                 list = section.contents()[0],
328                 item1 = list.contents()[0],
329                 item2 = list.contents()[1],
330                 item3 = list.contents()[2],
331                 item4 = list.contents()[3],
332                 item5 = list.contents()[4];
333             nestedList = item4.contents()[0];
334
335             expect(list.contents().length).to.equal(5, 'top list has five items');
336             expect(item1.contents()[0].getText()).to.equal('0', 'first item ok');
337             expect(item2.contents()[0].getText()).to.equal('1.1', 'second item ok');
338             expect(item3.contents()[0].getText()).to.equal('1.2', 'third item ok');
339             
340             expect(item4.getClass()).to.equal('item', 'nested list is still wrapped in item element');
341             expect(nestedList.contents().length).to.equal(1, 'nested list is left with one child');
342             expect(nestedList.contents()[0].contents()[0].getText()).to.equal('1.3', 'nested list item left alone');
343             expect(item5.contents()[0].getText()).to.equal('2', 'fifth item ok');
344         });
345
346         it('removes list if all its items are extracted - nested case', function() {
347             var doc = getDocumentFromXML(removeEmptyTextNodes('\
348                 <section>\
349                     <div class="list.items">\
350                         <div class="item">0</div>\
351                         <div class="item">\
352                             <div class="list.items">\
353                                 <div class="item">1.1</div>\
354                                 <div class="item">1.2</div>\
355                             </div>\
356                         </div>\
357                         <div class="item">2</div>\
358                     </div>\
359                 </section>')),
360                 list = doc.root.contents()[0],
361                 nestedList = list.contents()[1].contents()[0],
362                 nestedListItem1 = nestedList.contents()[0],
363                 nestedListItem2 = nestedList.contents()[1];
364
365             doc.transform('extractItems', {item1: nestedListItem1, item2: nestedListItem2});
366
367             var section = doc.root,
368                 list = section.contents()[0],
369                 item1 = list.contents()[0],
370                 item2 = list.contents()[1],
371                 item3 = list.contents()[2],
372                 item4 = list.contents()[3];
373
374             expect(list.contents().length).to.equal(4, 'top list has four items');
375             expect(item1.contents()[0].getText()).to.equal('0', 'first item ok');
376             expect(item2.contents()[0].getText()).to.equal('1.1', 'second item ok');
377             expect(item3.contents()[0].getText()).to.equal('1.2', 'third item ok');
378             expect(item4.contents()[0].getText()).to.equal('2', 'fourth item ok');
379         });
380
381         it('extracts items out of outer most list when merge flag is set to false', function() {
382             var doc = getDocumentFromXML(removeEmptyTextNodes('\
383                 <section>\
384                     <div class="list.items">\
385                         <div class="item">0</div>\
386                         <div class="item">\
387                             <div class="list.items">\
388                                 <div class="item">1.1</div>\
389                                 <div class="item">1.2</div>\
390                             </div>\
391                         </div>\
392                         <div class="item">2</div>\
393                     </div>\
394                 </section>')),
395                 section = doc.root,
396                 list = section.contents()[0],
397                 nestedList = list.contents()[1].contents()[0],
398                 nestedListItem = nestedList.contents()[0];
399
400             var test = doc.transform('extractItems', {item1: nestedListItem, item2: nestedListItem, merge: false});
401
402             expect(test).to.equal(true, 'extraction status ok');
403
404             var sectionContents = section.contents(),
405                 extractedItem = sectionContents[1];
406
407             expect(sectionContents.length).to.equal(3, 'section has three children');
408             expect(sectionContents[0].is('list')).to.equal(true, 'first child is a list');
409
410             expect(extractedItem.getTagName()).to.equal('div', 'extracted item is a wlxml div');
411             expect(extractedItem.getClass()).to.equal('', 'extracted item has no wlxml class');
412             expect(extractedItem.contents()[0].getText()).to.equal('1.1', 'extracted item ok');
413             expect(sectionContents[2].is('list')).to.equal(true, 'second child is a list');
414         });
415     });
416
417 });
418
419 });