Skip to content

Commit 6775bbe

Browse files
committed
Merge branch 't/12071'
2 parents d4bf2f9 + 0504a72 commit 6775bbe

File tree

7 files changed

+527
-0
lines changed

7 files changed

+527
-0
lines changed

bender.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ var config = {
8585
'tickets/',
8686
'!/_'
8787
]
88+
},
89+
90+
'Utils': {
91+
applications: [ 'ckeditor' ],
92+
basePath: 'tests/',
93+
paths: [
94+
'utils/',
95+
'!/_'
96+
]
8897
}
8998
}
9099
};

tests/utils/misc.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* bender-tags: editor,unit,utils */
2+
3+
( function() {
4+
'use strict';
5+
6+
bender.test( {
7+
'test assert.isMatching': function() {
8+
assert.isMatching( /abc/, 'abc' );
9+
assert.isMatching( /ab?c/i, 'AC' );
10+
11+
var error = null;
12+
try {
13+
assert.isMatching( /ab?c/i, 'def', 'should fail' );
14+
} catch ( e ) {
15+
error = e;
16+
}
17+
18+
assert.isNotNull( error );
19+
assert.areEqual( 'def', error.actual );
20+
assert.areEqual( '/ab?c/i', error.expected );
21+
assert.areEqual( 'should fail', error.message );
22+
23+
error = null;
24+
try {
25+
assert.isMatching( /ab?c/i, undefined, 'should fail' );
26+
} catch ( e ) {
27+
error = e;
28+
}
29+
30+
assert.isNotNull( error );
31+
assert.isUndefined( error.actual );
32+
assert.areEqual( '/ab?c/i', error.expected );
33+
assert.areEqual( 'should fail', error.message );
34+
},
35+
36+
'test synchronous wait/resume': function() {
37+
var tc = this;
38+
39+
function onTestResume( cb ) {
40+
cb.call( tc );
41+
}
42+
43+
onTestResume( function() {
44+
this.resume( function() {
45+
assert.isTrue( true );
46+
} );
47+
} );
48+
49+
this.wait();
50+
}
51+
} );
52+
} )();

tests/utils/range/setgetwithhtml.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<div id="playground" contentEditable="true"></div>

tests/utils/range/setgetwithhtml.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/* bender-tags: editor,unit,utils */
2+
3+
( function() {
4+
'use strict';
5+
6+
var doc = CKEDITOR.document,
7+
playground = doc.getById( 'playground' ),
8+
setRange = bender.tools.range.setWithHtml,
9+
getRange = bender.tools.range.getWithHtml,
10+
playgroundAddress = playground.getAddress(),
11+
12+
failIE11 = CKEDITOR.env.ie && CKEDITOR.env.version > 10,
13+
failIE8 = CKEDITOR.env.ie && CKEDITOR.env.version < 9;
14+
15+
// Asserts setRange and getRange.
16+
function s( html, collapsed, startAddress, startOffset, endAddress, endOffset, htmlWithRange ) {
17+
return function() {
18+
var range = setRange( playground, html ),
19+
startContainer, endContainer, range;
20+
21+
// Get startContainer by address.
22+
if ( startAddress && startOffset != undefined )
23+
startContainer = doc.getByAddress( playgroundAddress.concat( startAddress ) );
24+
25+
// Get endContainer by address.
26+
if ( collapsed === true ) {
27+
endContainer = startContainer;
28+
endOffset = startOffset;
29+
} else if ( collapsed === false )
30+
endContainer = doc.getByAddress( playgroundAddress.concat( endAddress ) );
31+
32+
if ( startContainer && endContainer ) {
33+
assert.isTrue( startContainer.equals( range.startContainer ), 'startContainer' );
34+
assert.isTrue( endContainer.equals( range.endContainer ), 'endContainer' );
35+
assert.areSame( startOffset, range.startOffset, 'startOffset' );
36+
assert.areSame( endOffset, range.endOffset, 'endOffset' );
37+
assert.areSame( collapsed, range.collapsed, 'collapsed' );
38+
} else {
39+
assert.isNull( range, 'No ranges returned' );
40+
}
41+
42+
assert.areSame( html.replace( /[\{\}\[\]]/g, '' ), bender.tools.fixHtml( playground.getHtml(), 1, 1 ), 'Markers cleaned - setRange' );
43+
assert.areSame( htmlWithRange == undefined ? html : htmlWithRange, bender.tools.fixHtml( getRange( playground, range ), 1, 1 ), 'getRange' );
44+
};
45+
}
46+
47+
bender.test( {
48+
_should: {
49+
ignore: {
50+
// IE11 inserts extra <br>.
51+
'test text #0': failIE11,
52+
53+
// IE8 normalizes double spaces, etc.
54+
'test text #16': failIE8,
55+
'test text #18': failIE8,
56+
'test text #19': failIE8,
57+
'test element #13': failIE8,
58+
'test element #14': failIE8,
59+
'test element #15': failIE8,
60+
'test element #16': failIE8,
61+
'test element #17': failIE8,
62+
'test mixed #8': failIE8
63+
}
64+
},
65+
66+
// Collapsed Start Address Start Offset End Address End offset HtmlWithRange
67+
'test text #0': s( '' ),
68+
'test text #1': s( '{}', null, null, null, null, null, '' ),
69+
'test text #2': s( '<p>x</p>' ),
70+
'test text #3': s( '<p>x{}x</p>', true, [ 0, 0 ], 1 ),
71+
'test text #4': s( '<p>{}x</p>', true, [ 0, 0 ], 0 ),
72+
'test text #5': s( '<p>x{}</p>', true, [ 0, 0 ], 1 ),
73+
'test text #6': s( '<p>{x}</p>', false, [ 0, 0 ], 0, [ 0, 0 ], 1 ),
74+
'test text #7': s( '<p>{x</p><p>y}</p>', false, [ 0, 0 ], 0, [ 1, 0 ], 1 ),
75+
'test text #8': s( '<p>x{</p><p>y}</p>', false, [ 0, 0 ], 1, [ 1, 0 ], 1 ),
76+
'test text #9': s( '<p>x{</p><p>}y</p>', false, [ 0, 0 ], 1, [ 1, 0 ], 0 ),
77+
'test text #10': s( '<ul><li>x{x</li><li>}y</li></ul>', false, [ 0, 0, 0 ], 1, [ 0, 1, 0 ], 0 ),
78+
'test text #11': s( '<ol><li>x{}<ul><li>y</li></ul></li></ol>', true, [ 0, 0, 0 ], 1 ),
79+
'test text #12': s( '<p>{}<span>x</span></p>', null, null, null, null, null, '<p><span>x</span></p>' ),
80+
'test text #13': s( '<p>{<span>x</span>}</p>', null, null, null, null, null, '<p><span>x</span></p>' ),
81+
'test text #14': s( '<p>x {}</p>', true, [ 0, 0 ], 2 ),
82+
'test text #15': s( '<p>{} x</p>', true, [ 0, 0 ], 0 ),
83+
'test text #16': s( '<p> {} </p>', true, [ 0, 0 ], 1 ),
84+
'test text #17': s( '<p>{ }</p>', false, [ 0, 0 ], 0, [ 0, 0 ], 1 ),
85+
'test text #18': s( '<p>{ }</p>', false, [ 0, 0 ], 0, [ 0, 0 ], 2 ),
86+
'test text #19': s( '<div>{ <p> }</p></div>', false, [ 0, 0 ], 0, [ 0, 1, 0 ], 1 ),
87+
'test text #20': s( '<p>{<span>x</span> }</p>', false, null, null, null, null, '<p><span>x</span> </p>' ),
88+
89+
'test element #0': s( '[]', true, [], 0 ),
90+
'test element #1': s( '<p>x[]x</p>', true, [ 0 ], 1 ),
91+
'test element #2': s( '<p>[]x</p>', true, [ 0 ], 0 ),
92+
'test element #3': s( '<p>x[]</p>', true, [ 0 ], 1 ),
93+
'test element #4': s( '<p>[x]</p>', false, [ 0 ], 0, [ 0 ], 1 ),
94+
'test element #5': s( '<ul>[<li>x</li><li>y</li>]</ul>', false, [ 0 ], 0, [ 0 ], 2 ),
95+
'test element #6': s( '<ul><li>x[x</li><li>]y</li></ul>', false, [ 0, 0 ], 1, [ 0, 1 ], 0 ),
96+
'test element #7': s( '<p>x[<span>y</span>]</p>', false, [ 0 ], 1, [ 0 ], 2 ),
97+
'test element #8': s( '<p>[]<span>x</span></p>', true, [ 0 ], 0 ),
98+
'test element #9': s( '<table><tbody><tr>[<td>x</td>]<td>x</td></tr></tbody></table>', false, [ 0, 0, 0 ], 0, [ 0, 0, 0 ], 1 ),
99+
'test element #10': s( '<ol><li>x[]<ul><li>y</li></ul></li></ol>', true, [ 0, 0 ], 1 ),
100+
'test element #11': s( '<ol>[<li>x</li><li>y<ul><li>z</li>]<li>a</li></ul></li></ol>', false, [ 0 ], 0, [ 0, 1, 1 ], 1 ),
101+
'test element #12': s( '<p>x []</p>', true, [ 0 ], 1 ),
102+
'test element #13': s( '<p>[] x</p>', true, [ 0 ], 0 ),
103+
'test element #14': s( '<p> [] </p>', true, [ 0 ], 1 ),
104+
'test element #15': s( '<p>[ ]</p>', false, [ 0 ], 0, [ 0 ], 1 ),
105+
'test element #16': s( '<p>[ ]</p>', false, [ 0 ], 0, [ 0 ], 1 ),
106+
'test element #17': s( '<div>[ <p> ]</p></div>', false, [ 0 ], 0, [ 0, 1 ], 1 ),
107+
108+
'test mixed #1': s( '<p>x{x]</p>', false, [ 0, 0 ], 1, [ 0 ], 1 ),
109+
'test mixed #2': s( '<p>{x]</p>', false, [ 0, 0 ], 0, [ 0 ], 1 ),
110+
'test mixed #3': s( '<p>[x}</p>', false, [ 0 ], 0, [ 0, 0 ], 1 ),
111+
'test mixed #4': s( '<p>[}x</p>', false, [ 0 ], 0, [ 0, 0 ], 0 ),
112+
'test mixed #5': s( '<p>x{]</p>', false, [ 0, 0 ], 1, [ 0 ], 1 ),
113+
'test mixed #6': s( '<p>[x</p><p>y}</p>', false, [ 0 ], 0, [ 1, 0 ], 1 ),
114+
'test mixed #7': s( '<p>{ ]</p>', false, [ 0, 0 ], 0, [ 0 ], 1 ),
115+
'test mixed #8': s( '<p> { ] </p>', false, [ 0, 0 ], 1, [ 0 ], 1 )
116+
} );
117+
} )();
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/* bender-tags: editor,unit,utils */
2+
3+
( function() {
4+
'use strict';
5+
6+
bender.editor = true;
7+
8+
bender.test( {
9+
'test setSelection - none': function() {
10+
var editor = this.editor,
11+
selectionChangeCalled = 0;
12+
13+
var listener = editor.on( 'selectionChange', function() {
14+
++selectionChangeCalled;
15+
} );
16+
17+
var selection = bender.tools.selection.setWithHtml( editor, '<p>x</p>' );
18+
19+
listener.removeListener();
20+
21+
assert.areSame( 0, selectionChangeCalled, 'selectionChange called' );
22+
assert.isTrue( selection instanceof CKEDITOR.dom.selection, 'CKEDITOR.dom.selection' );
23+
assert.areSame( '<p>x</p>', editor.getData(), 'editor data' );
24+
},
25+
26+
'test setSelection - element': function() {
27+
var editor = this.editor,
28+
selectionChangeCalled = 0;
29+
30+
var listener = editor.on( 'selectionChange', function() {
31+
++selectionChangeCalled;
32+
} );
33+
34+
var selection = bender.tools.selection.setWithHtml( editor, '<p>[x]</p>' );
35+
36+
listener.removeListener();
37+
38+
assert.areSame( 1, selectionChangeCalled, 'selectionChange called' );
39+
assert.isTrue( selection instanceof CKEDITOR.dom.selection, 'CKEDITOR.dom.selection' );
40+
assert.areSame( '<p>x</p>', editor.getData(), 'editor data' );
41+
},
42+
43+
'test setSelection - text': function() {
44+
var editor = this.editor,
45+
selectionChangeCalled = 0;
46+
47+
var listener = editor.on( 'selectionChange', function() {
48+
++selectionChangeCalled;
49+
} );
50+
51+
var selection = bender.tools.selection.setWithHtml( editor, '<p>{x}</p>' );
52+
53+
listener.removeListener();
54+
55+
assert.areSame( 1, selectionChangeCalled, 'selectionChange called' );
56+
assert.isTrue( selection instanceof CKEDITOR.dom.selection, 'CKEDITOR.dom.selection' );
57+
assert.areSame( '<p>x</p>', editor.getData(), 'editor data' );
58+
},
59+
60+
'test setSelection - selectionChange is always fired': function() {
61+
var editor = this.editor,
62+
bot = this.editorBot,
63+
selectionChangeCalled = 0;
64+
65+
bot.setData( '<p>x</p>', function() {
66+
var listener = editor.on( 'selectionChange', function() {
67+
++selectionChangeCalled;
68+
} );
69+
70+
// Focus editor what may make browser preparing initial selection
71+
// after we set editable's HTML. That selection may be placed in
72+
// exactly the same location, so selectionChange would not be fired.
73+
editor.focus();
74+
75+
selectionChangeCalled = 0;
76+
77+
bender.tools.selection.setWithHtml( editor, '<p>[]x</p>' );
78+
assert.areSame( 1, selectionChangeCalled, 'selectionChange called #1a' );
79+
80+
bender.tools.selection.setWithHtml( editor, '<p>[]x</p>' );
81+
assert.areSame( 2, selectionChangeCalled, 'selectionChange called #1b' );
82+
83+
selectionChangeCalled = 0;
84+
85+
bender.tools.selection.setWithHtml( editor, '<p>{}x</p>' );
86+
assert.areSame( 1, selectionChangeCalled, 'selectionChange called #2a' );
87+
88+
bender.tools.selection.setWithHtml( editor, '<p>{}x</p>' );
89+
assert.areSame( 2, selectionChangeCalled, 'selectionChange called #2b' );
90+
91+
selectionChangeCalled = 0;
92+
93+
bender.tools.selection.setWithHtml( editor, '<p>[x]</p>' );
94+
assert.areSame( 1, selectionChangeCalled, 'selectionChange called #3a' );
95+
96+
bender.tools.selection.setWithHtml( editor, '<p>[x]</p>' );
97+
assert.areSame( 2, selectionChangeCalled, 'selectionChange called #3b' );
98+
99+
listener.removeListener();
100+
} );
101+
},
102+
103+
'test getSelection - element': function() {
104+
var editor = this.editor,
105+
htmlWithRange = '<p>[x]</p>';
106+
107+
var selection = bender.tools.selection.setWithHtml( editor, htmlWithRange );
108+
109+
assert.isMatching( /<p>[\[\{]x[\]\}](<br>)?<\/p>/gi, bender.tools.selection.getWithHtml( editor ), 'getSelection' );
110+
assert.isMatching( '<p>x(<br>)?</p>', bender.tools.fixHtml( editor.editable().getHtml(), 1, 1 ), 'editable innerHTML' );
111+
},
112+
113+
'test getSelection - text': function() {
114+
var editor = this.editor,
115+
htmlWithRange = '<p>{x}</p>';
116+
117+
var selection = bender.tools.selection.setWithHtml( editor, htmlWithRange );
118+
119+
assert.isMatching( /<p>[\[\{]x[\]\}](<br>)?<\/p>/gi, bender.tools.selection.getWithHtml( editor ), 'getSelection' );
120+
assert.isMatching( '<p>x(<br>)?</p>', bender.tools.fixHtml( editor.editable().getHtml(), 1, 1 ), 'editable innerHTML' );
121+
},
122+
123+
'test getSelection - multiple ranges': function() {
124+
var editor = this.editor,
125+
revert = bender.tools.replaceMethod( CKEDITOR.dom.selection.prototype, 'getRanges', function() {
126+
return [ 1, 2 ];
127+
} ),
128+
error;
129+
130+
try {
131+
bender.tools.selection.getWithHtml( editor );
132+
} catch( e ) {
133+
error = e;
134+
} finally {
135+
revert();
136+
}
137+
138+
assert.isNotUndefined( error, 'Error is expected to be thrown' );
139+
}
140+
} );
141+
} )();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<div id="playground" contentEditable="true"></div>
2+
<textarea id="textarea_1">
3+
<ol id="ol_1">[<li id="li_3">leve1<ol><li id="li_4">level2</li></ol></li>]</ol>
4+
</textarea>
5+
<textarea id="textarea_2">
6+
<ol><li id="li_1">[leve1]<ol><li id="li_2">[level2]</li></ol></li></ol>
7+
</textarea>
8+
<textarea id="textarea_3">
9+
<p id="p_1">some[<span id="span_1">text</span>]</p>
10+
</textarea>
11+
<textarea id="textarea_4">
12+
<p id="p_2">so^me<span id="span_2">text</span></p>
13+
</textarea>
14+
<textarea id="textarea_5">
15+
<table>
16+
<tr id="tr_1">
17+
[<td>cell</td>]
18+
<td>cell</td>
19+
</tr>
20+
<tr id="tr_2">
21+
<td>cell</td>
22+
[<td>cell</td>]
23+
</tr>
24+
</table>
25+
</textarea>
26+
<textarea id="textarea_6">
27+
<ol id="ol_2">
28+
[<li>foo</li>
29+
<li>bar
30+
<ul id="ul_1">
31+
<li>
32+
baz
33+
</li>]
34+
<li>quz</li>
35+
</ul>
36+
</li>
37+
</ol>
38+
</textarea>
39+
<textarea id="textarea_7">
40+
<ol>
41+
<li id="li_5">foo^
42+
<ul><li>bar</li></ul>
43+
</li>
44+
</ol>
45+
</textarea>

0 commit comments

Comments
 (0)