Skip to content

Commit

Permalink
Merge pull request #34 from airbnb/is--animated-mocks-for-testing-with
Browse files Browse the repository at this point in the history
animated mocks for testing with
  • Loading branch information
sibnerian authored Aug 15, 2017
2 parents 1d80d54 + 5afbf1b commit 69b6b66
Show file tree
Hide file tree
Showing 9 changed files with 1,692 additions and 0 deletions.
1,191 changes: 1,191 additions & 0 deletions jest/Animated/AnimatedImplementation.js

Large diffs are not rendered by default.

267 changes: 267 additions & 0 deletions jest/Animated/Easing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule Easing
* @flow
*/
'use strict';

let ease;

/**
* The `Easing` module implements common easing functions. This module is used
* by [Animate.timing()](docs/animate.html#timing) to convey physically
* believable motion in animations.
*
* You can find a visualization of some common easing functions at
* http://easings.net/
*
* ### Predefined animations
*
* The `Easing` module provides several predefined animations through the
* following methods:
*
* - [`back`](docs/easing.html#back) provides a simple animation where the
* object goes slightly back before moving forward
* - [`bounce`](docs/easing.html#bounce) provides a bouncing animation
* - [`ease`](docs/easing.html#ease) provides a simple inertial animation
* - [`elastic`](docs/easing.html#elastic) provides a simple spring interaction
*
* ### Standard functions
*
* Three standard easing functions are provided:
*
* - [`linear`](docs/easing.html#linear)
* - [`quad`](docs/easing.html#quad)
* - [`cubic`](docs/easing.html#cubic)
*
* The [`poly`](docs/easing.html#poly) function can be used to implement
* quartic, quintic, and other higher power functions.
*
* ### Additional functions
*
* Additional mathematical functions are provided by the following methods:
*
* - [`bezier`](docs/easing.html#bezier) provides a cubic bezier curve
* - [`circle`](docs/easing.html#circle) provides a circular function
* - [`sin`](docs/easing.html#sin) provides a sinusoidal function
* - [`exp`](docs/easing.html#exp) provides an exponential function
*
* The following helpers are used to modify other easing functions.
*
* - [`in`](docs/easing.html#in) runs an easing function forwards
* - [`inOut`](docs/easing.html#inout) makes any easing function symmetrical
* - [`out`](docs/easing.html#out) runs an easing function backwards
*/
class Easing {
/**
* A stepping function, returns 1 for any positive value of `n`.
*/
static step0(n) {
return n > 0 ? 1 : 0;
}

/**
* A stepping function, returns 1 if `n` is greater than or equal to 1.
*/
static step1(n) {
return n >= 1 ? 1 : 0;
}

/**
* A linear function, `f(t) = t`. Position correlates to elapsed time one to
* one.
*
* http://cubic-bezier.com/#0,0,1,1
*/
static linear(t) {
return t;
}

/**
* A simple inertial interaction, similar to an object slowly accelerating to
* speed.
*
* http://cubic-bezier.com/#.42,0,1,1
*/
static ease(t: number): number {
if (!ease) {
ease = Easing.bezier(0.42, 0, 1, 1);
}
return ease(t);
}

/**
* A quadratic function, `f(t) = t * t`. Position equals the square of elapsed
* time.
*
* http://easings.net/#easeInQuad
*/
static quad(t) {
return t * t;
}

/**
* A cubic function, `f(t) = t * t * t`. Position equals the cube of elapsed
* time.
*
* http://easings.net/#easeInCubic
*/
static cubic(t) {
return t * t * t;
}

/**
* A power function. Position is equal to the Nth power of elapsed time.
*
* n = 4: http://easings.net/#easeInQuart
* n = 5: http://easings.net/#easeInQuint
*/
static poly(n) {
return (t) => Math.pow(t, n);
}

/**
* A sinusoidal function.
*
* http://easings.net/#easeInSine
*/
static sin(t) {
return 1 - Math.cos(t * Math.PI / 2);
}

/**
* A circular function.
*
* http://easings.net/#easeInCirc
*/
static circle(t) {
return 1 - Math.sqrt(1 - t * t);
}

/**
* An exponential function.
*
* http://easings.net/#easeInExpo
*/
static exp(t) {
return Math.pow(2, 10 * (t - 1));
}

/**
* A simple elastic interaction, similar to a spring oscillating back and
* forth.
*
* Default bounciness is 1, which overshoots a little bit once. 0 bounciness
* doesn't overshoot at all, and bounciness of N > 1 will overshoot about N
* times.
*
* http://easings.net/#easeInElastic
*
* Wolfram Plots:
*
* - http://tiny.cc/elastic_b_1 (bounciness = 1, default)
* - http://tiny.cc/elastic_b_3 (bounciness = 3)
*/
static elastic(bounciness: number = 1): (t: number) => number {
const p = bounciness * Math.PI;
return (t) => 1 - Math.pow(Math.cos(t * Math.PI / 2), 3) * Math.cos(t * p);
}

/**
* Use with `Animated.parallel()` to create a simple effect where the object
* animates back slightly as the animation starts.
*
* Wolfram Plot:
*
* - http://tiny.cc/back_default (s = 1.70158, default)
*/
static back(s: number): (t: number) => number {
if (s === undefined) {
s = 1.70158;
}
return (t) => t * t * ((s + 1) * t - s);
}

/**
* Provides a simple bouncing effect.
*
* http://easings.net/#easeInBounce
*/
static bounce(t: number): number {
if (t < 1 / 2.75) {
return 7.5625 * t * t;
}

if (t < 2 / 2.75) {
t -= 1.5 / 2.75;
return 7.5625 * t * t + 0.75;
}

if (t < 2.5 / 2.75) {
t -= 2.25 / 2.75;
return 7.5625 * t * t + 0.9375;
}

t -= 2.625 / 2.75;
return 7.5625 * t * t + 0.984375;
}

/**
* Provides a cubic bezier curve, equivalent to CSS Transitions'
* `transition-timing-function`.
*
* A useful tool to visualize cubic bezier curves can be found at
* http://cubic-bezier.com/
*/
static bezier(
x1: number,
y1: number,
x2: number,
y2: number
): (t: number) => number {
const _bezier = require('bezier');
return _bezier(x1, y1, x2, y2);
}

/**
* Runs an easing function forwards.
*/
static in(
easing: (t: number) => number,
): (t: number) => number {
return easing;
}

/**
* Runs an easing function backwards.
*/
static out(
easing: (t: number) => number,
): (t: number) => number {
return (t) => 1 - easing(1 - t);
}

/**
* Makes any easing function symmetrical. The easing function will run
* forwards for half of the duration, then backwards for the rest of the
* duration.
*/
static inOut(
easing: (t: number) => number,
): (t: number) => number {
return (t) => {
if (t < 0.5) {
return easing(t * 2) / 2;
}
return 1 - easing((1 - t) * 2) / 2;
};
}
}

module.exports = Easing;
10 changes: 10 additions & 0 deletions jest/Animated/Interpolation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* https://github.com/facebook/react-native/blob/master/Libraries/Animated/src/Interpolation.js
*/
class Interpolation {
static create(config) {
// TODO(lmr):
}
}

module.exports = Interpolation;
80 changes: 80 additions & 0 deletions jest/Animated/SpringConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* https://github.com/facebook/react-native/blob/master/Libraries/Animated/src/SpringConfig.js
*/

function tensionFromOrigamiValue(oValue) {
return (oValue - 30) * 3.62 + 194;
}

function frictionFromOrigamiValue(oValue) {
return (oValue - 8) * 3 + 25;
}

function fromOrigamiTensionAndFriction(tension, friction) {
return {
tension: tensionFromOrigamiValue(tension),
friction: frictionFromOrigamiValue(friction)
};
}

function fromBouncinessAndSpeed(bounciness, speed) {
function normalize(value, startValue, endValue) {
return (value - startValue) / (endValue - startValue);
}

function projectNormal(n, start, end) {
return start + (n * (end - start));
}

function linearInterpolation(t, start, end) {
return t * end + (1 - t) * start;
}

function quadraticOutInterpolation(t, start, end) {
return linearInterpolation(2 * t - t * t, start, end);
}

function b3Friction1(x) {
return (0.0007 * Math.pow(x, 3)) -
(0.031 * Math.pow(x, 2)) + 0.64 * x + 1.28;
}

function b3Friction2(x) {
return (0.000044 * Math.pow(x, 3)) -
(0.006 * Math.pow(x, 2)) + 0.36 * x + 2;
}

function b3Friction3(x) {
return (0.00000045 * Math.pow(x, 3)) -
(0.000332 * Math.pow(x, 2)) + 0.1078 * x + 5.84;
}

function b3Nobounce(tension) {
if (tension <= 18) {
return b3Friction1(tension);
} else if (tension > 18 && tension <= 44) {
return b3Friction2(tension);
}
return b3Friction3(tension);
}

let b = normalize(bounciness / 1.7, 0, 20);
b = projectNormal(b, 0, 0.8);
const s = normalize(speed / 1.7, 0, 20);
const bouncyTension = projectNormal(s, 0.5, 200);
const bouncyFriction = quadraticOutInterpolation(
b,
b3Nobounce(bouncyTension),
0.01
);

return {
tension: tensionFromOrigamiValue(bouncyTension),
friction: frictionFromOrigamiValue(bouncyFriction)
};
}

module.exports = {
fromOrigamiTensionAndFriction,
fromBouncinessAndSpeed,
};
20 changes: 20 additions & 0 deletions jest/Animated/createAnimatedComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

function createAnimatedComponent(Component) {
const refName = 'node';

class AnimatedComponent extends React.Component {
render() {
return (
<Component
{...this._propsAnimated.__getValue()}
ref={refName}
/>
);
}
}

return AnimatedComponent;
}

module.exports = createAnimatedComponent;
12 changes: 12 additions & 0 deletions jest/Animated/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import createAnimatedComponent from './createAnimatedComponent';
import AnimatedImplementation from './AnimatedImplementation';

const mockAnimatedComponent = require.requireActual('./mockAnimatedComponent');

module.exports = {
...AnimatedImplementation,
createAnimatedComponent,
View: mockAnimatedComponent('Animated.View'),
Text: mockAnimatedComponent('Animated.Text'),
Image: mockAnimatedComponent('IAnimated.mage'),
};
Loading

0 comments on commit 69b6b66

Please sign in to comment.