Skip to content

Commit 195e937

Browse files
zeyapfacebook-github-bot
authored andcommitted
Add NativeAnimated jest test to verify node creation behavior at update
Summary: ## Changelog: [Internal] [Added] - Add NativeAnimated jest test to verify node creation behavior at update Reviewed By: yungsters Differential Revision: D79729178
1 parent 54770ce commit 195e937

1 file changed

Lines changed: 253 additions & 2 deletions

File tree

packages/react-native/src/private/animated/__tests__/AnimatedNative-test.js

Lines changed: 253 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)