@@ -23,6 +23,7 @@ import {
23
23
ReplayerHandler ,
24
24
nodeMatching ,
25
25
sameNodeType ,
26
+ handleInsertBefore ,
26
27
} from '../src/diff' ;
27
28
import type { IRRElement , IRRNode } from '../src/document' ;
28
29
import { Replayer } from '@sentry-internal/rrweb' ;
@@ -1469,7 +1470,7 @@ describe('diff algorithm for rrdom', () => {
1469
1470
const rrHtmlEl = rrDocument.createElement('html');
1470
1471
rrDocument.mirror.add(rrHtmlEl, rrdom.getDefaultSN(rrHtmlEl, ${ htmlElId } ));
1471
1472
rrIframeEl.contentDocument.appendChild(rrHtmlEl);
1472
-
1473
+
1473
1474
const replayer = {
1474
1475
mirror: rrdom.createMirror(),
1475
1476
applyCanvas: () => {},
@@ -1478,7 +1479,7 @@ describe('diff algorithm for rrdom', () => {
1478
1479
applyStyleSheetMutation: () => {},
1479
1480
};
1480
1481
rrdom.diff(iframeEl, rrIframeEl, replayer);
1481
-
1482
+
1482
1483
iframeEl.contentDocument.documentElement.className =
1483
1484
'${ className . toLowerCase ( ) } ';
1484
1485
iframeEl.contentDocument.childNodes.length === 2 &&
@@ -2000,4 +2001,69 @@ describe('diff algorithm for rrdom', () => {
2000
2001
expect ( nodeMatching ( node1 , node2 , NodeMirror , rrdomMirror ) ) . toBeFalsy ( ) ;
2001
2002
} ) ;
2002
2003
} ) ;
2004
+
2005
+ describe ( 'test handleInsertBefore function' , ( ) => {
2006
+ it ( 'should insert nodeToMove before insertBeforeNode in oldTree for non-style elements' , ( ) => {
2007
+ const oldTree = document . createElement ( 'div' ) ;
2008
+ const nodeToMove = document . createElement ( 'div' ) ;
2009
+ const insertBeforeNode = document . createElement ( 'div' ) ;
2010
+ oldTree . appendChild ( insertBeforeNode ) ;
2011
+
2012
+ expect ( oldTree . children . length ) . toEqual ( 1 ) ;
2013
+
2014
+ handleInsertBefore ( oldTree , nodeToMove , insertBeforeNode ) ;
2015
+
2016
+ expect ( oldTree . children . length ) . toEqual ( 2 ) ;
2017
+ expect ( oldTree . children [ 0 ] ) . toEqual ( nodeToMove ) ;
2018
+ } ) ;
2019
+
2020
+ it ( 'should not drop inserted styles when moving a style element with inserted styles' , async ( ) => {
2021
+ function MockCSSStyleSheet ( ) {
2022
+ this . replaceSync = jest . fn ( ) ;
2023
+ this . cssRules = [ { cssText : baseStyle } ] ;
2024
+ }
2025
+
2026
+ jest
2027
+ . spyOn ( window , 'CSSStyleSheet' )
2028
+ . mockImplementationOnce ( MockCSSStyleSheet as any ) ;
2029
+
2030
+ const baseStyle = 'body {margin: 0;}' ;
2031
+ const insertedStyle = 'div {display: flex;}' ;
2032
+
2033
+ document . write ( '<html></html>' ) ;
2034
+
2035
+ const insertBeforeNode = document . createElement ( 'style' ) ;
2036
+ document . documentElement . appendChild ( insertBeforeNode ) ;
2037
+
2038
+ const nodeToMove = document . createElement ( 'style' ) ;
2039
+ nodeToMove . appendChild ( document . createTextNode ( baseStyle ) ) ;
2040
+ document . documentElement . appendChild ( nodeToMove ) ;
2041
+ nodeToMove . sheet ?. insertRule ( insertedStyle ) ;
2042
+
2043
+ // validate dom prior to moving element
2044
+ expect ( document . documentElement . children . length ) . toEqual ( 4 ) ;
2045
+ expect ( document . documentElement . children [ 2 ] ) . toEqual ( insertBeforeNode ) ;
2046
+ expect ( document . documentElement . children [ 3 ] ) . toEqual ( nodeToMove ) ;
2047
+ expect ( nodeToMove . sheet ?. cssRules . length ) . toEqual ( 2 ) ;
2048
+ expect ( nodeToMove . sheet ?. cssRules [ 0 ] . cssText ) . toEqual ( insertedStyle ) ;
2049
+ expect ( nodeToMove . sheet ?. cssRules [ 1 ] . cssText ) . toEqual ( baseStyle ) ;
2050
+
2051
+ // move the node
2052
+ handleInsertBefore (
2053
+ document . documentElement ,
2054
+ nodeToMove ,
2055
+ insertBeforeNode ,
2056
+ ) ;
2057
+
2058
+ // nodeToMove was inserted before
2059
+ expect ( document . documentElement . children . length ) . toEqual ( 4 ) ;
2060
+ expect ( document . documentElement . children [ 2 ] ) . toEqual ( nodeToMove ) ;
2061
+ expect ( document . documentElement . children [ 3 ] ) . toEqual ( insertBeforeNode ) ;
2062
+ // styles persisted on the moved element
2063
+ // w/ document.documentElement.insertBefore(nodeToMove, insertBeforeNode) insertedStyle wouldn't be copied
2064
+ expect ( nodeToMove . sheet ?. cssRules . length ) . toEqual ( 2 ) ;
2065
+ expect ( nodeToMove . sheet ?. cssRules [ 0 ] . cssText ) . toEqual ( insertedStyle ) ;
2066
+ expect ( nodeToMove . sheet ?. cssRules [ 1 ] . cssText ) . toEqual ( baseStyle ) ;
2067
+ } ) ;
2068
+ } ) ;
2003
2069
} ) ;
0 commit comments