smartxml: throw exception on transformation returning invalid change root
[fnpeditor.git] / src / editor / modules / documentCanvas / canvas / canvas.test.js
1 define([
2 'libs/jquery',
3 'libs/chai',
4 'libs/sinon',
5 'modules/documentCanvas/canvas/canvas',
6 'modules/documentCanvas/canvas/documentElement',
7 'modules/documentCanvas/canvas/utils',
8 'wlxml/wlxml'
9 ], function($, chai, sinon, canvas, documentElement, utils, wlxml) {
10     
11 'use strict';
12 /* global describe, it, beforeEach, afterEach */
13
14 var expect = chai.expect;
15
16 var getCanvasFromXML = function(xml) {
17     return canvas.fromXMLDocument(getDocumentFromXML(xml));
18 };
19
20 var getDocumentFromXML = function(xml) {
21     return wlxml.WLXMLDocumentFromXML(xml);
22 };
23
24 var wait = function(callback, timeout) {
25     /* globals window */
26     return window.setTimeout(callback, timeout || 0.5);
27 };
28
29
30 describe('new Canvas', function() {
31     it('abc', function() {
32         var doc = wlxml.WLXMLDocumentFromXML('<section>Alice <span>has</span> a cat!</div>'),
33             c = canvas.fromXMLDocument(doc);
34
35         expect(c.doc().children()).to.have.length(3);
36     });
37 });
38
39 describe('Handling empty text nodes', function() {
40     it('puts zero width space into node with about to be remove text', function(done) {
41         var c = getCanvasFromXML('<section>Alice</section>'),
42             textElement = c.doc().children()[0];
43         textElement.setText('');
44
45         /* Wait for MutationObserver to kick in. */
46         wait(function() {
47             expect(textElement.getText({raw:true})).to.equal(utils.unicode.ZWS, 'ZWS in canvas');
48             expect(c.wlxmlDocument.root.contents()[0].getText()).to.equal('', 'empty string in a document');
49             done();
50         });
51     });
52 });
53
54 describe('Handling changes to the document', function() {
55     it('replaces the whole canvas content when document root node replaced', function() {
56         var doc = getDocumentFromXML('<section></section>'),
57             c = canvas.fromXMLDocument(doc);
58
59         var header = doc.root.replaceWith({tagName: 'header'});
60         expect(c.doc().data('wlxmlNode').sameNode(header)).to.equal(true);
61     });
62 });
63
64 describe('Listening to document changes', function() {
65
66     it('Handling element node moved', function() {
67         var doc = getDocumentFromXML('<section><a></a><b></b></section>'),
68             a = doc.root.contents()[0],
69             b = doc.root.contents()[1],
70             c = canvas.fromXMLDocument(doc);
71
72         a.before(b);
73         var sectionChildren = c.doc().children();
74         expect(sectionChildren.length).to.equal(2);
75         expect(sectionChildren[0].getWlxmlTag()).to.equal('b');
76         expect(sectionChildren[1].getWlxmlTag()).to.equal('a');
77     });
78
79     it('Handling text node moved', function() {
80         var doc = getDocumentFromXML('<section><a></a>Alice</section>'),
81             a = doc.root.contents()[0],
82             textNode = doc.root.contents()[1],
83             c = canvas.fromXMLDocument(doc);
84
85         a.before(textNode);
86         var sectionChildren = c.doc().children();
87         expect(sectionChildren.length).to.equal(2);
88         expect(sectionChildren[0].getText()).to.equal('Alice');
89         expect(sectionChildren[1].getWlxmlTag()).to.equal('a');
90     });
91 });
92
93 describe('Cursor', function() {
94     /* globals Node */
95     var getSelection;
96
97     var findTextNode = function(inside, text) {
98         var nodes = inside.find(':not(iframe)').addBack().contents().filter(function() {
99             return this.nodeType === Node.TEXT_NODE && this.data === text;
100         });
101         if(nodes.length) {
102             return nodes[0];
103         }
104         return null;
105     };
106
107     beforeEach(function() {
108         /* globals window */
109         getSelection = sinon.stub(window, 'getSelection');
110     });
111
112     afterEach(function() {
113         getSelection.restore();
114     });
115
116     it('returns position when browser selection collapsed', function() {
117         var c = getCanvasFromXML('<section>Alice has a cat</section>'),
118             dom = c.doc().dom(),
119             text = findTextNode(dom, 'Alice has a cat');
120
121         expect(text.nodeType).to.equal(Node.TEXT_NODE, 'correct node selected');
122         expect($(text).text()).to.equal('Alice has a cat');
123
124         getSelection.returns({
125             anchorNode: text,
126             focusNode: text,
127             anchorOffset: 5,
128             focusOffset: 5,
129             isCollapsed: true
130         });
131         var cursor = c.getCursor(),
132             position = cursor.getPosition();
133
134         expect(cursor.isSelecting()).to.equal(false, 'cursor is not selecting anything');
135         expect(position.element.getText()).to.equal('Alice has a cat');
136         expect(position.offset).to.equal(5);
137         expect(position.offsetAtEnd).to.equal(false, 'offset is not at end');
138
139         getSelection.returns({
140             anchorNode: text,
141             focusNode: text,
142             anchorOffset: 15,
143             focusOffset: 15,
144             isCollapsed: true
145         });
146
147         expect(cursor.getPosition().offsetAtEnd).to.equal(true, 'offset at end');
148     });
149
150     it('returns boundries of selection when browser selection not collapsed', function() {
151         var c = getCanvasFromXML('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
152             dom = c.doc().dom(),
153             text = {
154                 alice: findTextNode(dom, 'Alice '),
155                 has: findTextNode(dom, 'has'),
156                 cat: findTextNode(dom, ' cat')
157             },
158             cursor = c.getCursor(),
159             aliceElement = c.getDocumentElement(text.alice),
160             catElement = c.getDocumentElement(text.cat);
161
162         [
163             {focus: text.alice, focusOffset: 1, anchor: text.cat,   anchorOffset: 2, selectionAnchor: catElement},
164             {focus: text.cat,   focusOffset: 2, anchor: text.alice, anchorOffset: 1, selectionAnchor: aliceElement}
165         ].forEach(function(s, idx) {
166             getSelection.returns({isColapsed: false, anchorNode: s.anchor, anchorOffset: s.anchorOffset, focusNode: s.focus, focusOffset: s.focusOffset});
167
168             var selectionStart = cursor.getSelectionStart(),
169                 selectionEnd = cursor.getSelectionEnd(),
170                 selectionAnchor = cursor.getSelectionAnchor();
171
172             expect(cursor.isSelecting()).to.equal(true, 'cursor is selecting');
173             expect(selectionStart.element.sameNode(aliceElement)).to.equal(true, '"Alice" is the start of the selection ' + idx);
174             expect(selectionStart.offset).to.equal(1, '"Alice" offset ok' + idx);
175             expect(selectionEnd.element.sameNode(catElement)).to.equal(true, '"Cat" is the start of the selection ' + idx);
176             expect(selectionEnd.offset).to.equal(2, '"Cat" offset ok' + idx);
177             expect(selectionAnchor.element.sameNode(s.selectionAnchor)).to.equal(true, 'anchor ok');
178             expect(selectionAnchor.offset).to.equal(s.anchorOffset, 'anchor offset ok');
179         });
180     });
181
182     it('recognizes when browser selection boundries lies in sibling DocumentTextElements', function() {
183         var c = getCanvasFromXML('<section>Alice <span>has</span> a <span>big</span> cat</section>'),
184             dom = c.doc().dom(),
185             text = {
186                 alice: findTextNode(dom, 'Alice '),
187                 has: findTextNode(dom, 'has'),
188                 a: findTextNode(dom, ' a '),
189                 big: findTextNode(dom, 'big'),
190                 cat: findTextNode(dom, ' cat'),
191             },
192             cursor = c.getCursor();
193
194         expect($(text.alice).text()).to.equal('Alice ');
195         expect($(text.has).text()).to.equal('has');
196         expect($(text.a).text()).to.equal(' a ');
197         expect($(text.big).text()).to.equal('big');
198         expect($(text.cat).text()).to.equal(' cat');
199
200         getSelection.returns({anchorNode: text.alice, focusNode: text.a});
201         expect(cursor.isSelectingSiblings()).to.equal(true, '"Alice" and "a" are children');
202
203         getSelection.returns({anchorNode: text.alice, focusNode: text.cat});
204         expect(cursor.isSelectingSiblings()).to.equal(true, '"Alice" and "cat" are children');
205
206         getSelection.returns({anchorNode: text.alice, focusNode: text.has});
207         expect(cursor.isSelectingSiblings()).to.equal(false, '"Alice" and "has" are not children');
208
209         getSelection.returns({anchorNode: text.has, focusNode: text.big});
210         expect(cursor.isSelectingSiblings()).to.equal(false, '"has" and "big" are not children');
211     });
212 });
213
214 });