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