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