@@ -466,7 +466,6 @@ describe('Native Animated', () => {
466466 { type : 'addition' , input : expect . any ( Array ) } ,
467467 ) ;
468468 const additionCalls =
469- // $FlowFixMe[prop-missing]
470469 // $FlowFixMe[prop-missing]
471470 NativeAnimatedModule . createAnimatedNode . mock . calls . filter (
472471 call => call [ 1 ] . type === 'addition' ,
@@ -475,7 +474,6 @@ describe('Native Animated', () => {
475474 const additionCall = additionCalls [ 0 ] ;
476475 const additionNodeTag = additionCall [ 0 ] ;
477476 const additionConnectionCalls =
478- // $FlowFixMe[prop-missing]
479477 // $FlowFixMe[prop-missing]
480478 NativeAnimatedModule . connectAnimatedNodes . mock . calls . filter (
481479 call => call [ 1 ] === additionNodeTag ,
@@ -1505,5 +1503,258 @@ describe('Native Animated', () => {
15051503 1 ,
15061504 ) ;
15071505 } ) ;
1506+
1507+ it ( 'creates new props, style and transform nodes at update' , async ( ) => {
1508+ const { Animated} = importModules ( ) ;
1509+
1510+ const opacityA = new Animated . Value ( 0 , {
1511+ debugID : 'opacityA' ,
1512+ useNativeDriver : true ,
1513+ } ) ;
1514+ const opacityB = new Animated . Value ( 0 , {
1515+ debugID : 'opacityB' ,
1516+ useNativeDriver : true ,
1517+ } ) ;
1518+ opacityA . __makeNative ( ) ;
1519+ opacityB . __makeNative ( ) ;
1520+ const scaleA = new Animated . Value ( 0 , {
1521+ debugID : 'scaleA' ,
1522+ useNativeDriver : true ,
1523+ } ) ;
1524+ const scaleB = new Animated . Value ( 0 , {
1525+ debugID : 'scaleB' ,
1526+ useNativeDriver : true ,
1527+ } ) ;
1528+ scaleA . __makeNative ( ) ;
1529+ scaleB . __makeNative ( ) ;
1530+
1531+ expect ( NativeAnimatedModule . createAnimatedNode ) . not . toHaveBeenCalled ( ) ;
1532+
1533+ // 1. First render, both opacity and transform scale are managed by Animated
1534+ const root = await create (
1535+ < Animated . View
1536+ style = { { opacity : opacityA , transform : [ { scale : scaleA } ] } }
1537+ /> ,
1538+ ) ;
1539+
1540+ let createAnimatedNodeCalledTimes = 0 ;
1541+ let dropAnimatedNodeCalledTimes = 0 ;
1542+
1543+ expect (
1544+ // $FlowFixMe[prop-missing]
1545+ NativeAnimatedModule . createAnimatedNode . mock . calls . slice ( 0 , 5 ) ,
1546+ ) . toEqual ( [
1547+ [ 1 , { debugID : 'opacityA' , offset : 0 , type : 'value' , value : 0 } ] ,
1548+ [ 4 , { debugID : 'scaleA' , offset : 0 , type : 'value' , value : 0 } ] ,
1549+ [
1550+ 3 ,
1551+ {
1552+ debugID : undefined ,
1553+ transforms : [ { nodeTag : 4 , property : 'scale' , type : 'animated' } ] ,
1554+ type : 'transform' ,
1555+ } ,
1556+ ] ,
1557+ [
1558+ 2 ,
1559+ {
1560+ debugID : undefined ,
1561+ style : {
1562+ opacity : 1 ,
1563+ transform : 3 ,
1564+ } ,
1565+ type : 'style' ,
1566+ } ,
1567+ ] ,
1568+ [ 5 , { debugID : undefined , props : { style : 2 } , type : 'props' } ] ,
1569+ ] ) ;
1570+
1571+ createAnimatedNodeCalledTimes += 5 ;
1572+
1573+ expect ( NativeAnimatedModule . dropAnimatedNode ) . not . toHaveBeenCalled ( ) ;
1574+ expect ( NativeAnimatedModule . restoreDefaultValues ) . not . toHaveBeenCalled ( ) ;
1575+ expect (
1576+ NativeAnimatedModule . disconnectAnimatedNodeFromView ,
1577+ ) . not . toHaveBeenCalled ( ) ;
1578+ expect (
1579+ NativeAnimatedModule . connectAnimatedNodeToView ,
1580+ ) . toHaveBeenCalledTimes ( 1 ) ;
1581+
1582+ // 2. Update the Animated node to control opacity style
1583+ await update (
1584+ root ,
1585+ < Animated . View
1586+ style = { { opacity : opacityB , transform : [ { scale : scaleA } ] } }
1587+ /> ,
1588+ ) ;
1589+ jest . runAllTicks ( ) ;
1590+
1591+ expect (
1592+ // $FlowFixMe[prop-missing]
1593+ NativeAnimatedModule . createAnimatedNode . mock . calls . slice ( 5 , 9 ) ,
1594+ ) . toEqual ( [
1595+ [ 6 , { debugID : 'opacityB' , offset : 0 , type : 'value' , value : 0 } ] ,
1596+ // transform node is still recreated even though `scale` is unchanged
1597+ [
1598+ 8 ,
1599+ {
1600+ debugID : undefined ,
1601+ transforms : [ { nodeTag : 4 , property : 'scale' , type : 'animated' } ] ,
1602+ type : 'transform' ,
1603+ } ,
1604+ ] ,
1605+ [
1606+ 7 ,
1607+ {
1608+ debugID : undefined ,
1609+ style : {
1610+ opacity : 6 ,
1611+ transform : 8 ,
1612+ } ,
1613+ type : 'style' ,
1614+ } ,
1615+ ] ,
1616+ [ 9 , { debugID : undefined , props : { style : 7 } , type : 'props' } ] ,
1617+ ] ) ;
1618+
1619+ createAnimatedNodeCalledTimes += 4 ;
1620+
1621+ expect (
1622+ // $FlowFixMe[prop-missing]
1623+ NativeAnimatedModule . dropAnimatedNode . mock . calls . slice ( 0 , 4 ) ,
1624+ ) . toEqual ( [ [ 1 ] , [ 3 ] , [ 2 ] , [ 5 ] ] ) ;
1625+
1626+ dropAnimatedNodeCalledTimes += 4 ;
1627+
1628+ expect ( NativeAnimatedModule . createAnimatedNode ) . toHaveBeenCalledTimes (
1629+ createAnimatedNodeCalledTimes ,
1630+ ) ;
1631+ expect ( NativeAnimatedModule . dropAnimatedNode ) . toHaveBeenCalledTimes (
1632+ dropAnimatedNodeCalledTimes ,
1633+ ) ;
1634+
1635+ expect ( NativeAnimatedModule . restoreDefaultValues ) . toHaveBeenCalledTimes (
1636+ 1 ,
1637+ ) ;
1638+ expect (
1639+ NativeAnimatedModule . disconnectAnimatedNodeFromView ,
1640+ ) . toHaveBeenCalledTimes ( 1 ) ;
1641+ expect (
1642+ NativeAnimatedModule . connectAnimatedNodeToView ,
1643+ ) . toHaveBeenCalledTimes ( 2 ) ;
1644+
1645+ // 3. Opacity is controlled by React while transform scale is still managed by Animated
1646+ await update (
1647+ root ,
1648+ < Animated . View style = { { opacity : 1 , transform : [ { scale : scaleB } ] } } /> ,
1649+ ) ;
1650+ jest . runAllTicks ( ) ;
1651+
1652+ expect (
1653+ // $FlowFixMe[prop-missing]
1654+ NativeAnimatedModule . createAnimatedNode . mock . calls . slice ( 9 , 13 ) ,
1655+ ) . toEqual ( [
1656+ [ 10 , { debugID : 'scaleB' , offset : 0 , type : 'value' , value : 0 } ] ,
1657+ [
1658+ 11 ,
1659+ {
1660+ debugID : undefined ,
1661+ transforms : [ { nodeTag : 10 , property : 'scale' , type : 'animated' } ] ,
1662+ type : 'transform' ,
1663+ } ,
1664+ ] ,
1665+ [
1666+ 12 ,
1667+ {
1668+ debugID : undefined ,
1669+ style : {
1670+ transform : 11 ,
1671+ } ,
1672+ type : 'style' ,
1673+ } ,
1674+ ] ,
1675+ [ 13 , { debugID : undefined , props : { style : 12 } , type : 'props' } ] ,
1676+ ] ) ;
1677+
1678+ createAnimatedNodeCalledTimes += 4 ;
1679+
1680+ expect (
1681+ // $FlowFixMe[prop-missing]
1682+ NativeAnimatedModule . dropAnimatedNode . mock . calls . slice ( 4 , 9 ) ,
1683+ ) . toEqual ( [ [ 6 ] , [ 4 ] , [ 8 ] , [ 7 ] , [ 9 ] ] ) ;
1684+
1685+ dropAnimatedNodeCalledTimes += 5 ;
1686+
1687+ expect ( NativeAnimatedModule . createAnimatedNode ) . toHaveBeenCalledTimes (
1688+ createAnimatedNodeCalledTimes ,
1689+ ) ;
1690+ expect ( NativeAnimatedModule . dropAnimatedNode ) . toHaveBeenCalledTimes (
1691+ dropAnimatedNodeCalledTimes ,
1692+ ) ;
1693+ expect ( NativeAnimatedModule . restoreDefaultValues ) . toHaveBeenCalledTimes (
1694+ 2 ,
1695+ ) ;
1696+ expect (
1697+ NativeAnimatedModule . disconnectAnimatedNodeFromView ,
1698+ ) . toHaveBeenCalledTimes ( 2 ) ;
1699+ expect (
1700+ NativeAnimatedModule . connectAnimatedNodeToView ,
1701+ ) . toHaveBeenCalledTimes ( 3 ) ;
1702+
1703+ // 4. Both opacity and transform scale are controlled by React instead of Animated
1704+ await update (
1705+ root ,
1706+ < Animated . View style = { { opacity : 1 , transform : [ { scale : 1 } ] } } /> ,
1707+ ) ;
1708+ jest . runAllTicks ( ) ;
1709+
1710+ {
1711+ const droppedTags = [ 10 , 11 , 12 , 13 ] ;
1712+ for ( let i = 0 ; i < droppedTags . length ; i ++ ) {
1713+ expect ( NativeAnimatedModule . dropAnimatedNode ) . toHaveBeenNthCalledWith (
1714+ i + dropAnimatedNodeCalledTimes + 1 ,
1715+ droppedTags [ i ] ,
1716+ ) ;
1717+ }
1718+
1719+ dropAnimatedNodeCalledTimes += droppedTags . length ;
1720+ }
1721+ expect ( NativeAnimatedModule . createAnimatedNode ) . toHaveBeenCalledTimes (
1722+ createAnimatedNodeCalledTimes ,
1723+ ) ;
1724+ expect ( NativeAnimatedModule . dropAnimatedNode ) . toHaveBeenCalledTimes (
1725+ dropAnimatedNodeCalledTimes ,
1726+ ) ;
1727+
1728+ // View is no longer connected to PropsAnimatedNode
1729+ expect (
1730+ NativeAnimatedModule . disconnectAnimatedNodeFromView ,
1731+ ) . toHaveBeenCalledTimes ( 3 ) ;
1732+ expect (
1733+ NativeAnimatedModule . connectAnimatedNodeToView ,
1734+ ) . toHaveBeenCalledTimes ( 3 ) ;
1735+ expect ( NativeAnimatedModule . restoreDefaultValues ) . toHaveBeenCalledTimes (
1736+ 3 ,
1737+ ) ;
1738+
1739+ // 5. Unmount
1740+ await unmount ( root ) ;
1741+ jest . runAllTicks ( ) ;
1742+ // No change for Animated nodes on unmount.
1743+ expect ( NativeAnimatedModule . createAnimatedNode ) . toHaveBeenCalledTimes (
1744+ createAnimatedNodeCalledTimes ,
1745+ ) ;
1746+ expect ( NativeAnimatedModule . dropAnimatedNode ) . toHaveBeenCalledTimes (
1747+ dropAnimatedNodeCalledTimes ,
1748+ ) ;
1749+ expect (
1750+ NativeAnimatedModule . disconnectAnimatedNodeFromView ,
1751+ ) . toHaveBeenCalledTimes ( 3 ) ;
1752+ expect (
1753+ NativeAnimatedModule . connectAnimatedNodeToView ,
1754+ ) . toHaveBeenCalledTimes ( 3 ) ;
1755+ expect ( NativeAnimatedModule . restoreDefaultValues ) . toHaveBeenCalledTimes (
1756+ 3 ,
1757+ ) ;
1758+ } ) ;
15081759 } ) ;
15091760} ) ;
0 commit comments