Skip to content

Commit 09fa1d8

Browse files
committed
feat: css animation polyfill
1 parent 7157a02 commit 09fa1d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+10358
-367
lines changed

apps/platform-tests/src/components/App.js

Lines changed: 575 additions & 4 deletions
Large diffs are not rendered by default.
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
*/
9+
10+
import { getInterpolatedStyle } from '../animationInterpolation';
11+
12+
// Mock dependencies
13+
jest.mock('../../react-native', () => ({
14+
Animated: {
15+
Value: jest.fn()
16+
}
17+
}));
18+
19+
jest.mock('../keyframeRegistry', () => ({
20+
keyframeRegistry: {
21+
resolve: jest.fn()
22+
}
23+
}));
24+
25+
jest.mock('../../modules/sharedAnimationUtils', () => ({
26+
collectAnimatedProperties: jest.fn(() => ({}))
27+
}));
28+
29+
jest.mock('../animationProperties', () => ({
30+
applyFillModeStyles: jest.fn(() => null)
31+
}));
32+
33+
jest.mock('../propertyInterpolation', () => ({
34+
interpolateTransformProperty: jest.fn(),
35+
interpolateRegularProperty: jest.fn()
36+
}));
37+
38+
jest.mock('../../utils/stylePropertyUtils', () => ({
39+
toReactNativeStyle: jest.fn((style) => style)
40+
}));
41+
42+
describe('animationInterpolation', () => {
43+
let mockAnimatedValue;
44+
let mockKeyframeRegistry;
45+
let mockCollectAnimatedProperties;
46+
let mockApplyFillModeStyles;
47+
let mockInterpolateTransformProperty;
48+
let mockInterpolateRegularProperty;
49+
50+
beforeEach(() => {
51+
jest.clearAllMocks();
52+
53+
mockAnimatedValue = { value: 0.5 };
54+
mockKeyframeRegistry = require('../keyframeRegistry').keyframeRegistry;
55+
mockCollectAnimatedProperties =
56+
require('../../modules/sharedAnimationUtils').collectAnimatedProperties;
57+
mockApplyFillModeStyles =
58+
require('../animationProperties').applyFillModeStyles;
59+
mockInterpolateTransformProperty =
60+
require('../propertyInterpolation').interpolateTransformProperty;
61+
mockInterpolateRegularProperty =
62+
require('../propertyInterpolation').interpolateRegularProperty;
63+
});
64+
65+
describe('getInterpolatedStyle', () => {
66+
test('should return base style when keyframe definition is not found', () => {
67+
mockKeyframeRegistry.resolve.mockReturnValue(null);
68+
69+
const baseStyle = { opacity: 0.5 };
70+
const result = getInterpolatedStyle(
71+
mockAnimatedValue,
72+
'nonexistent',
73+
baseStyle
74+
);
75+
76+
expect(result).toBe(baseStyle);
77+
expect(mockKeyframeRegistry.resolve).toHaveBeenCalledWith('nonexistent');
78+
});
79+
80+
test('should return fillMode result when applyFillModeStyles returns non-null', () => {
81+
const keyframeDefinition = {
82+
id: 'test',
83+
keyframes: {
84+
'0%': { opacity: 0 },
85+
'100%': { opacity: 1 }
86+
}
87+
};
88+
const fillModeResult = { opacity: 1 };
89+
90+
mockKeyframeRegistry.resolve.mockReturnValue(keyframeDefinition);
91+
mockApplyFillModeStyles.mockReturnValue(fillModeResult);
92+
93+
const baseStyle = { opacity: 0.5 };
94+
const result = getInterpolatedStyle(
95+
mockAnimatedValue,
96+
'test',
97+
baseStyle,
98+
'reverse',
99+
'forwards',
100+
'finished'
101+
);
102+
103+
expect(result).toBe(fillModeResult);
104+
expect(mockApplyFillModeStyles).toHaveBeenCalledWith(
105+
keyframeDefinition.keyframes,
106+
'reverse',
107+
'forwards',
108+
'finished',
109+
baseStyle
110+
);
111+
});
112+
113+
test('should interpolate transform properties', () => {
114+
const keyframeDefinition = {
115+
id: 'test',
116+
keyframes: {
117+
'0%': { transform: 'translateX(0px)' },
118+
'100%': { transform: 'translateX(100px)' }
119+
}
120+
};
121+
122+
mockKeyframeRegistry.resolve.mockReturnValue(keyframeDefinition);
123+
mockApplyFillModeStyles.mockReturnValue(null);
124+
mockCollectAnimatedProperties.mockReturnValue({ transform: true });
125+
126+
const baseStyle = {};
127+
getInterpolatedStyle(mockAnimatedValue, 'test', baseStyle, 'alternate');
128+
129+
expect(mockInterpolateTransformProperty).toHaveBeenCalledWith(
130+
expect.any(Object),
131+
'transform',
132+
keyframeDefinition.keyframes,
133+
mockAnimatedValue,
134+
'alternate'
135+
);
136+
expect(mockInterpolateRegularProperty).not.toHaveBeenCalled();
137+
});
138+
139+
test('should interpolate regular properties', () => {
140+
const keyframeDefinition = {
141+
id: 'test',
142+
keyframes: {
143+
'0%': { opacity: 0 },
144+
'100%': { opacity: 1 }
145+
}
146+
};
147+
148+
mockKeyframeRegistry.resolve.mockReturnValue(keyframeDefinition);
149+
mockApplyFillModeStyles.mockReturnValue(null);
150+
mockCollectAnimatedProperties.mockReturnValue({ opacity: true });
151+
152+
const baseStyle = { opacity: 0.5 };
153+
getInterpolatedStyle(mockAnimatedValue, 'test', baseStyle);
154+
155+
expect(mockInterpolateRegularProperty).toHaveBeenCalledWith(
156+
expect.any(Object),
157+
'opacity',
158+
keyframeDefinition.keyframes,
159+
baseStyle,
160+
mockAnimatedValue,
161+
'normal'
162+
);
163+
expect(mockInterpolateTransformProperty).not.toHaveBeenCalled();
164+
});
165+
166+
test('should handle mixed transform and regular properties', () => {
167+
const keyframeDefinition = {
168+
id: 'test',
169+
keyframes: {
170+
'0%': { opacity: 0, transform: 'scale(1)' },
171+
'100%': { opacity: 1, transform: 'scale(2)' }
172+
}
173+
};
174+
175+
mockKeyframeRegistry.resolve.mockReturnValue(keyframeDefinition);
176+
mockApplyFillModeStyles.mockReturnValue(null);
177+
mockCollectAnimatedProperties.mockReturnValue({
178+
opacity: true,
179+
transform: true
180+
});
181+
182+
const baseStyle = { opacity: 0.5 };
183+
getInterpolatedStyle(mockAnimatedValue, 'test', baseStyle);
184+
185+
expect(mockInterpolateTransformProperty).toHaveBeenCalledWith(
186+
expect.any(Object),
187+
'transform',
188+
keyframeDefinition.keyframes,
189+
mockAnimatedValue,
190+
'normal'
191+
);
192+
expect(mockInterpolateRegularProperty).toHaveBeenCalledWith(
193+
expect.any(Object),
194+
'opacity',
195+
keyframeDefinition.keyframes,
196+
baseStyle,
197+
mockAnimatedValue,
198+
'normal'
199+
);
200+
});
201+
202+
test('should use default parameter values', () => {
203+
const keyframeDefinition = {
204+
id: 'test',
205+
keyframes: {
206+
'0%': { opacity: 0 },
207+
'100%': { opacity: 1 }
208+
}
209+
};
210+
211+
mockKeyframeRegistry.resolve.mockReturnValue(keyframeDefinition);
212+
mockApplyFillModeStyles.mockReturnValue(null);
213+
mockCollectAnimatedProperties.mockReturnValue({});
214+
215+
const baseStyle = {};
216+
getInterpolatedStyle(mockAnimatedValue, 'test', baseStyle);
217+
218+
expect(mockApplyFillModeStyles).toHaveBeenCalledWith(
219+
keyframeDefinition.keyframes,
220+
'normal', // default direction
221+
'none', // default fillMode
222+
'not-started', // default animationState
223+
baseStyle
224+
);
225+
});
226+
});
227+
});

0 commit comments

Comments
 (0)