summaryrefslogtreecommitdiff
path: root/apps/web/src/rendering/__tests__/transition.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/rendering/__tests__/transition.test.ts')
-rw-r--r--apps/web/src/rendering/__tests__/transition.test.ts166
1 files changed, 166 insertions, 0 deletions
diff --git a/apps/web/src/rendering/__tests__/transition.test.ts b/apps/web/src/rendering/__tests__/transition.test.ts
new file mode 100644
index 00000000..4421fe58
--- /dev/null
+++ b/apps/web/src/rendering/__tests__/transition.test.ts
@@ -0,0 +1,166 @@
+import { describe, expect, test } from "bun:test";
+import {
+ applyVisualTransition,
+ buildTransitionFromParams,
+} from "@/rendering/transition";
+import type { Transform } from "@/rendering";
+import { TICKS_PER_SECOND } from "@/wasm";
+
+const baseTransform: Transform = {
+ scaleX: 1,
+ scaleY: 1,
+ position: { x: 0, y: 0 },
+ rotate: 0,
+};
+
+describe("visual transitions", () => {
+ test("fade ramps opacity at clip edges", () => {
+ const transition = buildTransitionFromParams({
+ params: {
+ "transition.kind": "fade",
+ "transition.inDuration": 1,
+ "transition.outDuration": 1,
+ },
+ });
+
+ expect(
+ applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 0,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ }).opacityMultiplier,
+ ).toBe(0);
+ expect(
+ applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 2 * TICKS_PER_SECOND,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ }).opacityMultiplier,
+ ).toBe(1);
+ expect(
+ applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 4 * TICKS_PER_SECOND,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ }).opacityMultiplier,
+ ).toBe(0);
+ });
+
+ test("slide left moves in and out across canvas", () => {
+ const transition = buildTransitionFromParams({
+ params: {
+ "transition.kind": "push-left",
+ "transition.inDuration": 1,
+ "transition.outDuration": 1,
+ },
+ });
+
+ const enter = applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 0,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ });
+ const middle = applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 2 * TICKS_PER_SECOND,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ });
+ const leave = applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 4 * TICKS_PER_SECOND,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ });
+
+ expect(enter.transform.position.x).toBe(100);
+ expect(middle.transform.position.x).toBe(0);
+ expect(leave.transform.position.x).toBe(-100);
+ expect(leave.opacityMultiplier).toBe(1);
+ });
+
+ test("slide right mirrors horizontal entry and exit", () => {
+ const transition = buildTransitionFromParams({
+ params: {
+ "transition.kind": "push-right",
+ "transition.inDuration": 1,
+ "transition.outDuration": 1,
+ },
+ });
+
+ const enter = applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 0,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ });
+ const middle = applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 2 * TICKS_PER_SECOND,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ });
+ const leave = applyVisualTransition({
+ baseTransform,
+ transition,
+ localTime: 4 * TICKS_PER_SECOND,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ });
+
+ expect(enter.transform.position.x).toBe(-100);
+ expect(middle.transform.position.x).toBe(0);
+ expect(leave.transform.position.x).toBe(100);
+ expect(enter.opacityMultiplier).toBe(1);
+ });
+
+ test("zoom and spin variants converge on the base transform", () => {
+ const applyKind = ({
+ kind,
+ localTime,
+ }: {
+ kind: "zoom" | "zoom-out" | "spin";
+ localTime: number;
+ }) =>
+ applyVisualTransition({
+ baseTransform,
+ transition: buildTransitionFromParams({
+ params: {
+ "transition.kind": kind,
+ "transition.inDuration": 1,
+ "transition.outDuration": 0,
+ },
+ }),
+ localTime,
+ duration: 4 * TICKS_PER_SECOND,
+ canvasWidth: 100,
+ });
+
+ expect(applyKind({ kind: "zoom", localTime: 0 }).transform.scaleX).toBe(
+ 0.96,
+ );
+ expect(applyKind({ kind: "zoom-out", localTime: 0 }).transform.scaleX).toBe(
+ 1.04,
+ );
+ expect(applyKind({ kind: "spin", localTime: 0 }).transform.rotate).toBe(-6);
+
+ const settledSpin = applyKind({
+ kind: "spin",
+ localTime: 2 * TICKS_PER_SECOND,
+ });
+ expect(settledSpin.transform.scaleX).toBe(1);
+ expect(settledSpin.transform.rotate).toBe(0);
+ });
+});