Files
portifolio-evandrodevbr/app/components/showcase/showcase-math.test.ts
T

97 lines
3.3 KiB
TypeScript

import {
easeToward,
localAtProgress,
locateInReel,
REEL_HOLD,
REEL_LAST_TAIL,
reelHolds,
reelStarts,
videoProgress,
} from "./showcase-math";
describe("locateInReel", () => {
const weights = [1, 2, 1];
it("maps overall progress to a project and a position inside it", () => {
expect(locateInReel(weights, 0)).toEqual({ index: 0, local: 0 });
expect(locateInReel(weights, 0.125)).toEqual({ index: 0, local: 0.5 });
const middle = locateInReel(weights, 0.5);
expect(middle.index).toBe(1);
expect(middle.local).toBeCloseTo(0.5);
expect(locateInReel(weights, 1)).toEqual({ index: 2, local: 1 });
});
it("clamps progress outside the pinned range", () => {
expect(locateInReel(weights, -3)).toEqual({ index: 0, local: 0 });
expect(locateInReel(weights, 7)).toEqual({ index: 2, local: 1 });
});
it("copes with an empty reel", () => {
expect(locateInReel([], 0.4)).toEqual({ index: 0, local: 0 });
});
it("gives each project the share of the scroll that its weight asks for", () => {
expect(reelStarts(weights)).toEqual([0, 0.25, 0.75]);
});
});
describe("videoProgress", () => {
it("holds still at the start and at the end of each project's stretch", () => {
expect(videoProgress(0)).toBe(0);
expect(videoProgress(0.1)).toBe(0);
expect(videoProgress(0.5)).toBeCloseTo(0.5);
expect(videoProgress(0.9)).toBe(1);
expect(videoProgress(1)).toBe(1);
});
});
describe("videoProgress with a shorter pause at the end", () => {
it("lets the video run until the tail starts", () => {
expect(videoProgress(0.9, 0.1, 0.03)).toBeCloseTo((0.9 - 0.1) / 0.87, 9);
expect(videoProgress(0.97, 0.1, 0.03)).toBe(1);
expect(videoProgress(1, 0.1, 0.03)).toBe(1);
expect(videoProgress(0.1, 0.1, 0.03)).toBe(0);
});
it("localAtProgress is its inverse inside the moving part", () => {
for (const progress of [0, 0.25, 0.5, 1]) {
const local = localAtProgress(progress, 0.1, 0.03);
expect(videoProgress(local, 0.1, 0.03)).toBeCloseTo(progress, 9);
}
expect(localAtProgress(0)).toBe(REEL_HOLD);
expect(localAtProgress(1)).toBeCloseTo(1 - REEL_HOLD, 9);
});
});
describe("reelHolds", () => {
it("keeps the full pause everywhere but at the end of the last project, which has nothing to wait for", () => {
expect(reelHolds(0, 4)).toEqual({ head: REEL_HOLD, tail: REEL_HOLD });
expect(reelHolds(2, 4)).toEqual({ head: REEL_HOLD, tail: REEL_HOLD });
expect(reelHolds(3, 4)).toEqual({ head: REEL_HOLD, tail: REEL_LAST_TAIL });
expect(REEL_LAST_TAIL).toBeLessThan(REEL_HOLD);
expect(reelHolds(0, 1).tail).toBe(REEL_LAST_TAIL);
});
});
describe("easeToward", () => {
it("moves toward the target and never overshoots", () => {
const first = easeToward(0, 1, 1 / 60);
expect(first).toBeGreaterThan(0);
expect(first).toBeLessThan(1);
expect(easeToward(0.5, 0.5, 1)).toBe(0.5);
expect(easeToward(0, 1, 10)).toBeCloseTo(1, 5);
});
it("does not depend on the frame rate", () => {
let sixty = 0;
for (let i = 0; i < 60; i += 1) sixty = easeToward(sixty, 1, 1 / 60);
let thirty = 0;
for (let i = 0; i < 30; i += 1) thirty = easeToward(thirty, 1, 1 / 30);
expect(sixty).toBeCloseTo(thirty, 6);
});
it("stands still when no time has passed", () => {
expect(easeToward(0.2, 1, 0)).toBe(0.2);
});
});