mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-07 15:27:14 +00:00
* fix(studio): place GSAP step lists and duration-less tweens where GSAP plays them * refactor(studio): drop narrated comments and unnest the extend clamp * fix(studio): match keyframes in time, resolve partial step timing, start readout from prior tween * fix(studio): time step-list keyframes from the parts' last end and format * refactor(studio): trim comments to the package's comment share * fix(parsers): apply timeline defaults as GSAP does to step lists and motion paths * fix(studio): keep GSAP's ease for motion paths with keyframes and read finished tweens * refactor(studio): read a live motion path in its own step * refactor(parsers): leave step-list timing to its one owner and skip timeline defaults there * refactor(studio): move the live motion-path read into its own module * test(parsers): pin an unresolved length for a step list stretched by a variable duration * fix(studio): time keyframes linearly under an outer ease that overshoots or steps * fix(studio): time a converted expression-duration tween from its live tween, and pin no rewrite
68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
findObjectArrayKeyframeIndex,
|
|
getCompatibleObjectArrayKeyframeTiming,
|
|
getObjectArrayKeyframeTiming,
|
|
} from "./gsapObjectArrayTiming.js";
|
|
|
|
describe("getObjectArrayKeyframeTiming", () => {
|
|
it("ends each equal step at its share of the tween, to a tenth of a percent", () => {
|
|
expect(getObjectArrayKeyframeTiming([undefined, undefined, undefined])).toEqual({
|
|
percentages: [33.3, 66.7, 100],
|
|
totalDuration: 1.5,
|
|
});
|
|
expect(getObjectArrayKeyframeTiming([undefined])).toEqual({
|
|
percentages: [100],
|
|
totalDuration: 0.5,
|
|
});
|
|
});
|
|
|
|
it("gives a step without a duration GSAP's 0.5 s beside authored ones", () => {
|
|
expect(getObjectArrayKeyframeTiming([1, undefined, 1])).toEqual({
|
|
percentages: [40, 60, 100],
|
|
totalDuration: 2.5,
|
|
});
|
|
});
|
|
|
|
it("maps positive authored durations to cumulative percentages", () => {
|
|
expect(getObjectArrayKeyframeTiming([1, 2, 1])).toEqual({
|
|
percentages: [25, 75, 100],
|
|
totalDuration: 4,
|
|
});
|
|
});
|
|
|
|
it.each([
|
|
[[0, 1, 1], "zero"],
|
|
[[1, -1, 1], "negative"],
|
|
[[1, Number.NaN, 1], "non-finite"],
|
|
[[1, "__raw:total * 0.5", 1], "expression"],
|
|
])("rejects %s duration timing (%s)", (durations) => {
|
|
expect(getObjectArrayKeyframeTiming(durations)).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("findObjectArrayKeyframeIndex", () => {
|
|
it("falls back to the nearest array entry for an in-range percentage", () => {
|
|
expect(
|
|
findObjectArrayKeyframeIndex([undefined, undefined, undefined, undefined], 50, {
|
|
fallbackToNearest: true,
|
|
}),
|
|
).toBe(1);
|
|
});
|
|
|
|
it("rejects out-of-range and unresolved timing", () => {
|
|
expect(findObjectArrayKeyframeIndex([undefined, undefined], -1)).toBeNull();
|
|
expect(findObjectArrayKeyframeIndex([undefined, undefined], 101)).toBeNull();
|
|
expect(findObjectArrayKeyframeIndex([1, 0, 1], 50)).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("getCompatibleObjectArrayKeyframeTiming", () => {
|
|
it("accepts absent or matching outer durations and rejects conflicts", () => {
|
|
expect(getCompatibleObjectArrayKeyframeTiming([0.25, 0.75], undefined)).not.toBeNull();
|
|
expect(getCompatibleObjectArrayKeyframeTiming([0.25, 0.75], 1)).not.toBeNull();
|
|
expect(getCompatibleObjectArrayKeyframeTiming([0.25, 0.75], 2)).toBeNull();
|
|
expect(getCompatibleObjectArrayKeyframeTiming([0.25, 0.75], "1")).toBeNull();
|
|
});
|
|
});
|