|
1 | | -// fallow-ignore-file duplication |
| 1 | +// fallow-ignore-file code-duplication |
2 | 2 | /** |
3 | 3 | * T6d: parse-parity suite — runs the full gsapParser.test.ts parse scenarios |
4 | 4 | * against parseGsapScriptAcorn. Write-path tests are it.skip'd; those live |
@@ -912,3 +912,140 @@ describe("native GSAP keyframes parsing", () => { |
912 | 912 | expect(Object.keys(anim.properties)).toHaveLength(0); |
913 | 913 | }); |
914 | 914 | }); |
| 915 | + |
| 916 | +// ── motionPath parsing ──────────────────────────────────────────────────────── |
| 917 | + |
| 918 | +describe("motionPath parsing", () => { |
| 919 | + it("parses motionPath with waypoint array and curviness", () => { |
| 920 | + const script = ` |
| 921 | + const tl = gsap.timeline({ paused: true }); |
| 922 | + tl.to("#el", { |
| 923 | + motionPath: { |
| 924 | + path: [{x: 0, y: 0}, {x: 200, y: -100}, {x: 400, y: 50}], |
| 925 | + curviness: 1.5 |
| 926 | + }, |
| 927 | + duration: 2 |
| 928 | + }, 0); |
| 929 | + `; |
| 930 | + const result = parseGsapScript(script); |
| 931 | + expect(result.animations).toHaveLength(1); |
| 932 | + const anim = result.animations[0]; |
| 933 | + |
| 934 | + expect(anim.arcPath).toBeDefined(); |
| 935 | + expect(anim.arcPath!.enabled).toBe(true); |
| 936 | + expect(anim.arcPath!.segments).toHaveLength(2); |
| 937 | + expect(anim.arcPath!.segments[0].curviness).toBe(1.5); |
| 938 | + expect(anim.arcPath!.segments[1].curviness).toBe(1.5); |
| 939 | + |
| 940 | + expect(anim.keyframes).toBeDefined(); |
| 941 | + expect(anim.keyframes!.keyframes).toHaveLength(3); |
| 942 | + expect(anim.keyframes!.keyframes[0].properties.x).toBe(0); |
| 943 | + expect(anim.keyframes!.keyframes[0].properties.y).toBe(0); |
| 944 | + expect(anim.keyframes!.keyframes[1].properties.x).toBe(200); |
| 945 | + expect(anim.keyframes!.keyframes[1].properties.y).toBe(-100); |
| 946 | + expect(anim.keyframes!.keyframes[2].properties.x).toBe(400); |
| 947 | + expect(anim.keyframes!.keyframes[2].properties.y).toBe(50); |
| 948 | + }); |
| 949 | + |
| 950 | + it("parses motionPath with type cubic and explicit control points", () => { |
| 951 | + const script = ` |
| 952 | + const tl = gsap.timeline({ paused: true }); |
| 953 | + tl.to("#el", { |
| 954 | + motionPath: { |
| 955 | + path: [ |
| 956 | + {x: 0, y: 0}, |
| 957 | + {x: 50, y: -80}, {x: 150, y: -120}, |
| 958 | + {x: 200, y: -100}, |
| 959 | + {x: 250, y: -80}, {x: 350, y: 30}, |
| 960 | + {x: 400, y: 50} |
| 961 | + ], |
| 962 | + type: "cubic" |
| 963 | + }, |
| 964 | + duration: 2 |
| 965 | + }, 0); |
| 966 | + `; |
| 967 | + const result = parseGsapScript(script); |
| 968 | + const anim = result.animations[0]; |
| 969 | + |
| 970 | + expect(anim.arcPath).toBeDefined(); |
| 971 | + expect(anim.arcPath!.segments).toHaveLength(2); |
| 972 | + |
| 973 | + expect(anim.arcPath!.segments[0].cp1).toEqual({ x: 50, y: -80 }); |
| 974 | + expect(anim.arcPath!.segments[0].cp2).toEqual({ x: 150, y: -120 }); |
| 975 | + |
| 976 | + expect(anim.arcPath!.segments[1].cp1).toEqual({ x: 250, y: -80 }); |
| 977 | + expect(anim.arcPath!.segments[1].cp2).toEqual({ x: 350, y: 30 }); |
| 978 | + |
| 979 | + expect(anim.keyframes!.keyframes).toHaveLength(3); |
| 980 | + expect(anim.keyframes!.keyframes[0].properties).toEqual({ x: 0, y: 0 }); |
| 981 | + expect(anim.keyframes!.keyframes[1].properties).toEqual({ x: 200, y: -100 }); |
| 982 | + expect(anim.keyframes!.keyframes[2].properties).toEqual({ x: 400, y: 50 }); |
| 983 | + }); |
| 984 | + |
| 985 | + it("parses motionPath with autoRotate", () => { |
| 986 | + const script = ` |
| 987 | + const tl = gsap.timeline({ paused: true }); |
| 988 | + tl.to("#el", { |
| 989 | + motionPath: { |
| 990 | + path: [{x: 0, y: 0}, {x: 200, y: 100}], |
| 991 | + autoRotate: true |
| 992 | + }, |
| 993 | + duration: 1 |
| 994 | + }, 0); |
| 995 | + `; |
| 996 | + const result = parseGsapScript(script); |
| 997 | + const anim = result.animations[0]; |
| 998 | + expect(anim.arcPath!.autoRotate).toBe(true); |
| 999 | + }); |
| 1000 | + |
| 1001 | + it("merges motionPath waypoints into existing keyframes", () => { |
| 1002 | + const script = ` |
| 1003 | + const tl = gsap.timeline({ paused: true }); |
| 1004 | + tl.to("#el", { |
| 1005 | + motionPath: { |
| 1006 | + path: [{x: 0, y: 0}, {x: 200, y: 100}], |
| 1007 | + curviness: 2 |
| 1008 | + }, |
| 1009 | + keyframes: { |
| 1010 | + "0%": { opacity: 1 }, |
| 1011 | + "100%": { opacity: 0 } |
| 1012 | + }, |
| 1013 | + duration: 2 |
| 1014 | + }, 0); |
| 1015 | + `; |
| 1016 | + const result = parseGsapScript(script); |
| 1017 | + const anim = result.animations[0]; |
| 1018 | + |
| 1019 | + expect(anim.arcPath).toBeDefined(); |
| 1020 | + expect(anim.arcPath!.segments).toHaveLength(1); |
| 1021 | + expect(anim.arcPath!.segments[0].curviness).toBe(2); |
| 1022 | + |
| 1023 | + expect(anim.keyframes!.keyframes).toHaveLength(2); |
| 1024 | + expect(anim.keyframes!.keyframes[0].properties).toEqual({ opacity: 1, x: 0, y: 0 }); |
| 1025 | + expect(anim.keyframes!.keyframes[1].properties).toEqual({ opacity: 0, x: 200, y: 100 }); |
| 1026 | + }); |
| 1027 | + |
| 1028 | + it("skips motionPath with fewer than 2 waypoints", () => { |
| 1029 | + const script = ` |
| 1030 | + const tl = gsap.timeline({ paused: true }); |
| 1031 | + tl.to("#el", { |
| 1032 | + motionPath: { path: [{x: 0, y: 0}] }, |
| 1033 | + duration: 1 |
| 1034 | + }, 0); |
| 1035 | + `; |
| 1036 | + const result = parseGsapScript(script); |
| 1037 | + expect(result.animations[0].arcPath).toBeUndefined(); |
| 1038 | + }); |
| 1039 | + |
| 1040 | + it("tween without motionPath parses identically to before", () => { |
| 1041 | + const script = ` |
| 1042 | + const tl = gsap.timeline({ paused: true }); |
| 1043 | + tl.to("#el", { x: 100, y: 200, duration: 1 }, 0); |
| 1044 | + `; |
| 1045 | + const result = parseGsapScript(script); |
| 1046 | + const anim = result.animations[0]; |
| 1047 | + expect(anim.arcPath).toBeUndefined(); |
| 1048 | + expect(anim.properties.x).toBe(100); |
| 1049 | + expect(anim.properties.y).toBe(200); |
| 1050 | + }); |
| 1051 | +}); |
0 commit comments