@@ -149,6 +149,91 @@ describe('Test Dom module', function () {
149149 expect ( names . toString ( ) ) . equals ( 'LI,2,LI,1' ) ;
150150 } ) ;
151151 } ) ;
152+
153+ describe ( 'Many siblings' , function ( ) {
154+ it ( 'Should iterate wide sibling lists in proper order' , ( ) => {
155+ const node = document . createElement ( 'div' ) ;
156+
157+ node . innerHTML = new Array ( 10 )
158+ . fill ( 0 )
159+ . map ( ( _ , i ) => `<span>${ i } </span>` )
160+ . join ( '' ) ;
161+
162+ const values = [ ] ;
163+
164+ Dom . find (
165+ node . firstChild ,
166+ n => {
167+ if ( Dom . isText ( n ) ) {
168+ values . push ( n . nodeValue ) ;
169+ }
170+ } ,
171+ node
172+ ) ;
173+
174+ expect ( values . join ( '' ) ) . equals ( '123456789' ) ;
175+
176+ values . length = 0 ;
177+
178+ Dom . find (
179+ node . lastChild ,
180+ n => {
181+ if ( Dom . isText ( n ) ) {
182+ values . push ( n . nodeValue ) ;
183+ }
184+ } ,
185+ node ,
186+ false
187+ ) ;
188+
189+ expect ( values . join ( '' ) ) . equals ( '876543210' ) ;
190+ } ) ;
191+ } ) ;
192+ } ) ;
193+
194+ describe ( 'Method between' , function ( ) {
195+ it ( 'Should call callback for all nodes between start and end' , ( ) => {
196+ const node = document . createElement ( 'div' ) ;
197+
198+ node . innerHTML =
199+ '<p>1<span id="s"></span>2</p><p>3</p><p>4<span id="e"></span>5</p>' ;
200+
201+ Dom . between (
202+ node . querySelector ( '#s' ) ,
203+ node . querySelector ( '#e' ) ,
204+ iterate
205+ ) ;
206+
207+ expect ( names . toString ( ) ) . equals ( '2,P,3,P,4' ) ;
208+ } ) ;
209+
210+ it ( 'Should stop iterating when callback returns true' , ( ) => {
211+ const node = document . createElement ( 'div' ) ;
212+
213+ node . innerHTML =
214+ '<p>1<span id="s"></span>2</p><p>3</p><p>4<span id="e"></span>5</p>' ;
215+
216+ Dom . between (
217+ node . querySelector ( '#s' ) ,
218+ node . querySelector ( '#e' ) ,
219+ elm => {
220+ iterate ( elm ) ;
221+ return Dom . isText ( elm ) && elm . nodeValue === '3' ;
222+ }
223+ ) ;
224+
225+ expect ( names . toString ( ) ) . equals ( '2,P,3' ) ;
226+ } ) ;
227+
228+ it ( 'Should not iterate outside when end is an ancestor of start' , ( ) => {
229+ const node = document . createElement ( 'div' ) ;
230+
231+ node . innerHTML = '<p>1<span id="s"></span></p><p>2</p>' ;
232+
233+ Dom . between ( node . querySelector ( '#s' ) , node . firstChild , iterate ) ;
234+
235+ expect ( names . toString ( ) ) . equals ( '' ) ;
236+ } ) ;
152237 } ) ;
153238 } ) ;
154239
@@ -280,6 +365,72 @@ describe('Test Dom module', function () {
280365 } ) ;
281366 } ) ;
282367
368+ describe ( 'Method isFragment' , function ( ) {
369+ it ( 'Should return true for document fragments' , function ( ) {
370+ expect ( Dom . isFragment ( document . createDocumentFragment ( ) ) ) . is . true ;
371+
372+ // fragment inside an inert document
373+ const template = document . createElement ( 'template' ) ;
374+ template . innerHTML = '<p>test</p>' ;
375+ expect ( Dom . isFragment ( template . content ) ) . is . true ;
376+ } ) ;
377+
378+ it ( 'Should return false for other values' , function ( ) {
379+ expect ( Dom . isFragment ( document . createElement ( 'div' ) ) ) . is . false ;
380+ expect ( Dom . isFragment ( document . createTextNode ( 'test' ) ) ) . is . false ;
381+ expect ( Dom . isFragment ( document ) ) . is . false ;
382+ expect ( Dom . isFragment ( null ) ) . is . false ;
383+ expect ( Dom . isFragment ( '' ) ) . is . false ;
384+ } ) ;
385+ } ) ;
386+
387+ describe ( 'Method replace' , function ( ) {
388+ it ( 'Should replace one tag with another keeping content and attributes' , function ( ) {
389+ const editor = getJodit ( ) ;
390+ const div = document . createElement ( 'div' ) ;
391+ div . innerHTML = '<span data-x="1">content</span>' ;
392+
393+ const strong = Dom . replace (
394+ div . firstChild ,
395+ 'strong' ,
396+ editor . createInside ,
397+ true
398+ ) ;
399+
400+ expect ( div . innerHTML ) . equals ( '<strong data-x="1">content</strong>' ) ;
401+ expect ( strong . tagName ) . equals ( 'STRONG' ) ;
402+ } ) ;
403+
404+ it ( 'Should replace tag with ready element' , function ( ) {
405+ const div = document . createElement ( 'div' ) ;
406+ div . innerHTML = '<span>content</span>' ;
407+
408+ const em = document . createElement ( 'em' ) ;
409+ const result = Dom . replace ( div . firstChild , em ) ;
410+
411+ expect ( result ) . equals ( em ) ;
412+ expect ( div . innerHTML ) . equals ( '<em>content</em>' ) ;
413+ } ) ;
414+ } ) ;
415+
416+ describe ( 'Method replaceTemporaryFromString' , function ( ) {
417+ it ( 'Should remove temporary wrappers and keep their content' , function ( ) {
418+ expect (
419+ Dom . replaceTemporaryFromString (
420+ '<p>a <span data-jodit-temp="true">b</span> c</p>'
421+ )
422+ ) . equals ( '<p>a b c</p>' ) ;
423+ } ) ;
424+
425+ it ( 'Should support the attribute without a value' , function ( ) {
426+ expect (
427+ Dom . replaceTemporaryFromString (
428+ '<p><span data-jodit-temp>b</span></p>'
429+ )
430+ ) . equals ( '<p>b</p>' ) ;
431+ } ) ;
432+ } ) ;
433+
283434 describe ( 'Method isOrContains' , function ( ) {
284435 it ( 'Should return true if element inside root' , function ( ) {
285436 const node = document . createElement ( 'div' ) ;
@@ -663,5 +814,69 @@ describe('Test Dom module', function () {
663814 walker . setWork ( div ) ;
664815 } ) ;
665816 } ) ;
817+
818+ describe ( 'Repeated setWork' , ( ) => {
819+ it ( 'should process only the last tree and emit end once' , done => {
820+ const walker = new LazyWalker ( new Async ( ) ) ;
821+ const names = [ ] ;
822+ let endCount = 0 ;
823+
824+ walker
825+ . on ( 'visit' , node => {
826+ names . push ( node . nodeName . toLowerCase ( ) ) ;
827+ } )
828+ . on ( 'end' , ( ) => {
829+ endCount += 1 ;
830+ expect ( endCount ) . eq ( 1 ) ;
831+ expect ( names ) . deep . eq ( [ 'p' , '#text' ] ) ;
832+ done ( ) ;
833+ } ) ;
834+
835+ const div1 = document . createElement ( 'div' ) ;
836+ div1 . innerHTML = '<span>a</span>' ;
837+
838+ const div2 = document . createElement ( 'div' ) ;
839+ div2 . innerHTML = '<p>b</p>' ;
840+
841+ walker . setWork ( div1 ) ;
842+ walker . setWork ( div2 ) ;
843+ } ) ;
844+ } ) ;
845+
846+ describe ( 'Restart after break' , ( ) => {
847+ it ( 'should reset the affect flag between passes' , done => {
848+ const asyncM = new Async ( ) ;
849+ const walker = new LazyWalker ( asyncM , {
850+ timeoutChunkSize : 1 ,
851+ timeout : 100
852+ } ) ;
853+
854+ const div = document . createElement ( 'div' ) ;
855+ div . innerHTML = '<b>1</b><i>2</i><u>3</u>' ;
856+
857+ let pass = 1 ;
858+
859+ // the first pass "affects" nodes, the second one - does not
860+ walker . on ( 'visit' , ( ) => pass === 1 ) ;
861+
862+ walker . on ( 'break' , ( ) => {
863+ asyncM . setTimeout ( ( ) => {
864+ pass = 2 ;
865+ walker . setWork ( div ) ;
866+ } , 10 ) ;
867+ } ) ;
868+
869+ walker . on ( 'end' , affect => {
870+ expect ( pass ) . eq ( 2 ) ;
871+ expect ( affect ) . is . false ;
872+ done ( ) ;
873+ } ) ;
874+
875+ walker . setWork ( div ) ;
876+
877+ // break the first pass in the middle, between two chunks
878+ asyncM . setTimeout ( ( ) => walker . break ( ) , 150 ) ;
879+ } ) ;
880+ } ) ;
666881 } ) ;
667882} ) ;
0 commit comments