Splitting text
[fnpeditor.git] / modules / documentCanvas / canvas / canvas.test3.js
1 define([
2 'libs/chai',
3 'modules/documentCanvas/canvas/canvas',
4 'modules/documentCanvas/canvas/documentElement'
5 ], function(chai, canvas, documentElement) {
6     
7 'use strict';
8
9 var expect = chai.expect;
10
11
12 describe('Canvas', function() {
13     describe('basic properties', function() {
14         it('renders empty document when canvas created from empty XML', function() {
15             var c = canvas.fromXML('');
16             expect(c.doc()).to.equal(null);
17         });
18
19         it('gives access to its document root node', function() {
20             var c = canvas.fromXML('<section></section>');
21             expect(c.doc().wlxmlTag).to.equal('section');
22         });
23
24         describe('DocumentElement', function() {
25             it('knows index of its child', function() {
26                 var c = canvas.fromXML('<section><div></div><header></header><span></span></section>'),
27                     root = c.doc(),
28                     child = root.children()[1];
29                 expect(root.childIndex(child)).to.equal(1);
30             });
31
32             describe('DocumentTextElement can have its content set', function() {
33                 var c = canvas.fromXML('<section>Alice</section>'),
34                     root = c.doc(),
35                     text = root.children()[0];
36                 
37                 text.setText('a cat');
38                 expect(root.children()[0].getText()).to.equal('a cat');
39             });
40         });
41     });
42
43     describe('document representation api', function() {
44         describe('document root element', function() {
45             var c = canvas.fromXML('<section></section>');
46             it('exists', function() {
47                 expect(c.doc()).to.be.instanceOf(documentElement.DocumentElement);
48             });
49             it('is of type DocumentNodeElement', function() {
50                 expect(c.doc()).to.be.instanceOf(documentElement.DocumentNodeElement);
51             });
52         });
53
54         describe('DocumentElements comparison', function() {
55             it('reports dwo DocumentElements to be the same when they represent the same wlxml document element', function() {
56                 var c = canvas.fromXML('<section><div></div><div></div></section>'),
57                     first_div1 = c.doc().children()[0],
58                     first_div2 = c.doc().children()[0],
59                     second_div = c.doc().children()[1];
60                 expect(first_div1.sameNode(first_div1)).to.be.true;
61                 expect(first_div1.sameNode(first_div2)).to.be.true;
62                 expect(first_div1.sameNode(second_div)).to.be.false;
63             });
64         });
65
66         describe('traversing', function() {
67             it('reports element nodes', function() {
68                 var c = canvas.fromXML('<section><div></div></section>'),
69                     children = c.doc().children();
70                 expect(children.length).to.equal(1);
71                 expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
72
73                 c = canvas.fromXML('<section><div></div><div></div></section>'),
74                     children = c.doc().children();
75                 expect(children.length).to.equal(2);
76                 expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
77                 expect(children[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
78             });
79             
80             it('reports text nodes', function() {
81                 var c = canvas.fromXML('<section>Alice</section>'),
82                     children = c.doc().children();
83                 expect(children.length).to.equal(1);
84                 expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
85             });
86
87             describe('accessing parents', function() {
88                 it('returns DocumentNodeElement representing parent in wlxml document as DocumentNodeElement parent', function() {
89                     var c = canvas.fromXML('<section><div></div></section>'),
90                         div = c.doc().children()[0];
91                     expect(div.parent().sameNode(c.doc())).to.be.true;
92                 });
93                 it('returns DocumentNodeElement representing parent in wlxml document as DocumentTextElement parent', function() {
94                     var c = canvas.fromXML('<section>Alice</section>'),
95                         text = c.doc().children()[0];
96                     expect(text.parent().sameNode(c.doc())).to.be.true;
97                 });
98             });
99
100             describe('free text handling', function() {
101                     it('sees free text', function() {
102                         var c = canvas.fromXML('<section>Alice <span>has</span> a cat</section>'),
103                             children = c.doc().children();
104                         expect(children.length).to.equal(3);
105                         expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
106                         expect(children[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
107                         expect(children[2]).to.be.instanceOf(documentElement.DocumentTextElement);
108                     });
109             });
110             
111             describe('white characters handling', function() {
112                 it('says empty element node has no children', function() {
113                     var c = canvas.fromXML('<section></section>');
114                     expect(c.doc().children().length).to.equal(0);
115                 });
116                 it('says element node with one space has one DocumentTextElement', function() {
117                     var c = canvas.fromXML('<section> </section>');
118                     expect(c.doc().children().length).to.equal(1);
119                     expect(c.doc().children()[0]).to.be.instanceOf(documentElement.DocumentTextElement);
120                 });
121                 it('ignores white space surrounding block elements', function() {
122                     var c = canvas.fromXML('<section> <div></div> </section>');
123                     var children = c.doc().children();
124                     expect(children.length).to.equal(1);
125                     expect(children[0]).to.be.instanceOf(documentElement.DocumentNodeElement);
126                 });
127                 it('ignores white space between block elements', function() {
128                     var c = canvas.fromXML('<section><div></div> <div></div></section>');
129                     var children = c.doc().children();
130                     expect(children.length === 2);
131                     [0,1].forEach(function(idx) {
132                         expect(children[idx]).to.be.instanceOf(documentElement.DocumentNodeElement);
133                     });
134                 });
135
136                 it('trims white space from the beginning and the end of the block elements', function() {
137                     var c = canvas.fromXML('<section> Alice <span>has</span> a cat </section>');
138                     expect(c.doc().children()[0].getText()).to.equal('Alice ');
139                     expect(c.doc().children()[2].getText()).to.equal(' a cat');
140                 });
141
142                 it('normalizes string of white characters to one space at the inline element boundries', function() {
143                     var c = canvas.fromXML('<span>   Alice has a cat   </span>');
144                     expect(c.doc().children()[0].getText()).to.equal(' Alice has a cat ');
145                 });
146
147                 it('normalizes string of white characters to one space before inline element', function() {
148                     var c = canvas.fromXML('<div>Alice has  <span>a cat</span></div>');
149                     expect(c.doc().children()[0].getText()).to.equal('Alice has ');
150                 });
151                 
152                 it('normalizes string of white characters to one space after inline element', function() {
153                     var c = canvas.fromXML('<div>Alice has <span>a</span>  cat</div>');
154                     expect(c.doc().children()[2].getText()).to.equal(' cat');
155                 });
156             });
157         });
158
159         describe('manipulation api', function() {
160
161             describe('Basic Element inserting', function() {
162                 it('can put new NodeElement at the end', function() {
163                     var c = canvas.fromXML('<section></section>'),
164                         appended = c.doc().append({tag: 'header', klass: 'some.class'}),
165                         children = c.doc().children();
166
167                     expect(children.length).to.equal(1);
168                     expect(children[0].sameNode(appended));
169                 });
170
171                 it('can put new TextElement at the end', function() {
172                     var c = canvas.fromXML('<section></section>'),
173                         appended = c.doc().append({text: 'Alice'}),
174                         children = c.doc().children();
175
176                     expect(children.length).to.equal(1);
177                     expect(children[0].sameNode(appended));
178                     expect(children[0].getText()).to.equal('Alice');
179                 });
180
181                 it('can put new NodeElement after another NodeElement', function() {
182                     var c = canvas.fromXML('<section><div></div></section>'),
183                         div = c.doc().children()[0],
184                         added = div.after({tag: 'header', klass: 'some.class'}),
185                         children = c.doc().children();
186                     expect(children.length).to.equal(2);
187                     expect(children[1].sameNode(added));
188                 });
189
190                 it('can put new Nodeelement before another element', function() {
191                     var c = canvas.fromXML('<section><div></div></section>'),
192                         div = c.doc().children()[0],
193                         added = div.before({tag: 'header', klass: 'some.class'}),
194                         children = c.doc().children();
195                     expect(children.length).to.equal(2);
196                     expect(children[0].sameNode(added));
197                 });
198
199                 it('can put new DocumentNodeElement after DocumentTextElement', function() {
200                     var c = canvas.fromXML('<section>Alice</section>'),
201                         text = c.doc().children()[0],
202                         added = text.after({tag: 'p'}),
203                         children = c.doc().children();
204
205                     expect(children.length).to.equal(2);
206                     expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
207                     expect(children[0].getText()).to.equal('Alice');
208                     expect(children[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
209                     expect(children[1].sameNode(added)).to.be.true;
210                 });
211             });
212
213             describe('Splitting text', function() {
214                 
215                 it('splits DocumentTextElement\'s parent into two DocumentNodeElements of the same type', function() {
216                     var c = canvas.fromXML('<section><header>Some header</header></section>'),
217                         section = c.doc(),
218                         text = section.children()[0].children()[0];
219
220                     text.split({offset: 5});
221                     expect(section.children().length).to.equal(2, 'section has two children');
222                     
223                     var header1 = section.children()[0];
224                     var header2 = section.children()[1];
225
226                     expect(header1.wlxmlTag).to.equal('header', 'first section child represents wlxml header');
227                     expect(header1.children().length).to.equal(1, 'first header has one text child');
228                     expect(header1.children()[0].getText()).to.equal('Some ', 'first header has correct content');
229                     expect(header2.wlxmlTag).to.equal('header', 'second section child represents wlxml header');
230                     expect(header2.children().length).to.equal(1, 'second header has one text child');
231                     expect(header2.children()[0].getText()).to.equal('header', 'second header has correct content');
232                 });
233
234                 it('keeps DocumentTextElement\'s parent\'s children elements intact', function() {
235                     var c = canvas.fromXML('\
236                             <section>\
237                                 <header>\
238                                     A <span>fancy</span> and <span>nice</span> header\
239                                 </header>\
240                             </section>'),
241                         section = c.doc(),
242                         header = section.children()[0],
243                         textAnd = header.children()[2];
244
245                     textAnd.split({offset: 2});
246                     
247                     var sectionChildren = section.children();
248                     expect(sectionChildren.length).to.equal(2, 'Section has two children');
249                     expect(sectionChildren[0].wlxmlTag).to.equal('header', 'First section element is a wlxml header');
250                     expect(sectionChildren[1].wlxmlTag).to.equal('header', 'Second section element is a wlxml header');
251
252                     var firstHeaderChildren = sectionChildren[0].children();
253                     expect(firstHeaderChildren.length).to.equal(3, 'First header has three children');
254                     expect(firstHeaderChildren[0].getText()).to.equal('A ', 'First header starts with a text');
255                     expect(firstHeaderChildren[1].wlxmlTag).to.equal('span', 'First header has span in the middle');
256                     expect(firstHeaderChildren[2].getText()).to.equal(' a', 'First header ends with text');
257
258                     var secondHeaderChildren = sectionChildren[1].children();
259                     expect(secondHeaderChildren.length).to.equal(3, 'Second header has three children');
260                     expect(secondHeaderChildren[0].getText()).to.equal('nd ', 'Second header starts with text');
261                     expect(secondHeaderChildren[1].wlxmlTag).to.equal('span', 'Second header has span in the middle');
262                     expect(secondHeaderChildren[2].getText()).to.equal(' header', 'Second header ends with text');
263                 });
264             });
265
266             describe('wrapping', function() {
267                 it('wraps DocumentNodeElement', function() {
268                     var c = canvas.fromXML('<section><div></div></section>'),
269                         div = c.doc().children()[0];
270                     
271                     var returned = div.wrapWithNodeElement({tag: 'header', klass: 'some.class'}),
272                         parent = div.parent(),
273                         parent2 = c.doc().children()[0];
274
275                     expect(returned.sameNode(parent)).to.be.true;
276                     expect(returned.sameNode(parent2)).to.be.true;
277                 });
278                 it('wraps DocumentTextElement', function() {
279                     var c = canvas.fromXML('<section>Alice</section>'),
280                         text = c.doc().children()[0];
281                     
282                     var returned = text.wrapWithNodeElement({tag: 'header', klass: 'some.class'}),
283                         parent = text.parent(),
284                         parent2 = c.doc().children()[0];
285
286                     expect(returned.sameNode(parent)).to.be.true;
287                     expect(returned.sameNode(parent2)).to.be.true;
288                 });
289                 
290                 it('wraps part of DocumentTextElement', function() {
291                     var c = canvas.fromXML('<section>Alice has a cat</section>'),
292                         text = c.doc().children()[0];
293                     
294                     var returned = text.wrapWithNodeElement({tag: 'header', klass: 'some.class', start: 5, end: 12}),
295                         children = c.doc().children();
296
297                     expect(children.length).to.equal(3);
298                     
299                     expect(children[0]).to.be.instanceOf(documentElement.DocumentTextElement);
300                     expect(children[0].getText()).to.equal('Alice');
301
302                     expect(children[1].sameNode(returned)).to.be.true;
303                     expect(children[1].children().length).to.equal(1);
304                     expect(children[1].children()[0].getText()).to.equal(' has a ');
305
306                     expect(children[2]).to.be.instanceOf(documentElement.DocumentTextElement);
307                     expect(children[2].getText()).to.equal('cat');
308                 });
309
310                 it('wraps text spanning multiple sibling DocumentTextNodes', function() {
311                     var c = canvas.fromXML('<section>Alice has a <span>small</span> cat</section>'),
312                         section = c.doc(),
313                         wrapper = c.wrapText({
314                             inside: section, 
315                             _with: {tag: 'span', klass: 'some.class'},
316                             offsetStart: 6,
317                             offsetEnd: 4,
318                             textNodeIdx: [0,2]
319                         });
320
321                     expect(section.children().length).to.equal(2);
322                     expect(section.children()[0]).to.be.instanceOf(documentElement.DocumentTextElement);
323                     expect(section.children()[0].getText()).to.equal('Alice ');
324
325                     var wrapper2 = section.children()[1];
326                     expect(wrapper2.sameNode(wrapper)).to.be.true;
327
328                     var wrapperChildren = wrapper.children();
329                     expect(wrapperChildren.length).to.equal(3);
330                     expect(wrapperChildren[0].getText()).to.equal('has a ');
331
332                     expect(wrapperChildren[1]).to.be.instanceOf(documentElement.DocumentNodeElement);
333                     expect(wrapperChildren[1].children().length).to.equal(1);
334                     expect(wrapperChildren[1].children()[0].getText()).to.equal('small');
335
336                     expect(wrapperChildren[2].getText()).to.equal(' cat');
337                 });
338             });
339         });
340
341     });
342 });
343
344
345 });