work on tests

This commit is contained in:
Skyler Lehmkuhl 2025-11-12 08:52:16 -05:00
parent a1e2368468
commit 3296d3ab6e
5 changed files with 190 additions and 72 deletions

View File

@ -2,12 +2,30 @@
* Canvas interaction utilities for UI testing
*/
/**
* Reset canvas scroll/pan to origin
*/
export async function resetCanvasView() {
await browser.execute(function() {
if (window.context && window.context.stageWidget) {
window.context.stageWidget.offsetX = 0;
window.context.stageWidget.offsetY = 0;
// Trigger redraw to apply the reset
if (window.context.updateUI) {
window.context.updateUI();
}
}
});
await browser.pause(100); // Wait for canvas to reset
}
/**
* Click at specific coordinates on the canvas
* @param {number} x - X coordinate relative to canvas
* @param {number} y - Y coordinate relative to canvas
*/
export async function clickCanvas(x, y) {
await resetCanvasView();
await browser.clickCanvas(x, y);
await browser.pause(100); // Wait for render
}
@ -20,6 +38,7 @@ export async function clickCanvas(x, y) {
* @param {number} toY - Ending Y coordinate
*/
export async function dragCanvas(fromX, fromY, toX, toY) {
await resetCanvasView();
await browser.dragCanvas(fromX, fromY, toX, toY);
await browser.pause(200); // Wait for render
}
@ -206,6 +225,11 @@ export async function setPlayheadTime(time) {
if (window.context.timelineWidget && window.context.timelineWidget.requestRedraw) {
window.context.timelineWidget.requestRedraw();
}
// Trigger stage redraw to show shapes at new time
if (window.context.updateUI) {
window.context.updateUI();
}
}
}, time);
await browser.pause(200);

View File

@ -14,6 +14,7 @@ import {
clickCanvas
} from '../helpers/canvas.js';
import { assertShapeExists } from '../helpers/assertions.js';
import { verifyManually, logStep } from '../helpers/manual.js';
describe('Group Editing', () => {
before(async () => {
@ -71,6 +72,7 @@ describe('Group Editing', () => {
it('should handle nested group editing with correct positioning', async () => {
// Create first group with two shapes
await logStep('Drawing two rectangles for inner group');
await drawRectangle(400, 100, 60, 60);
await drawRectangle(480, 100, 60, 60);
await selectMultipleShapes([
@ -80,24 +82,47 @@ describe('Group Editing', () => {
await useKeyboardShortcut('g', true);
await browser.pause(300);
await verifyManually('VERIFY: Do you see two rectangles grouped together?\nClick OK if yes, Cancel if no');
// Verify both shapes exist
await assertShapeExists(430, 130, 'First shape should exist');
await assertShapeExists(510, 130, 'Second shape should exist');
// Create another shape and group everything together
await logStep('Drawing third rectangle and creating nested group');
await drawRectangle(400, 180, 60, 60);
await selectMultipleShapes([
{ x: 470, y: 130 }, // Center of first group
{ x: 430, y: 210 } // Center of new shape
]);
// Select both the group and the new shape by dragging a selection box
// We need to start from well outside the shapes to avoid hitting them
// The first group spans x=400-540, y=100-160
// The third shape spans x=400-460, y=180-240
await selectTool('select');
await dragCanvas(390, 90, 550, 250); // Start from outside all shapes
await browser.pause(200);
await useKeyboardShortcut('g', true);
await browser.pause(300);
await verifyManually('VERIFY: All three rectangles now grouped together (nested group)?\nClick OK if yes, Cancel if no');
// Double-click to enter outer group
await logStep('Double-clicking to enter outer group');
await doubleClickCanvas(470, 130);
await browser.pause(300);
await verifyManually('VERIFY: Are we now inside the outer group?\nClick OK if yes, Cancel if no');
// Double-click again to enter inner group
await logStep('Double-clicking again to enter inner group');
await doubleClickCanvas(470, 130);
await browser.pause(300);
await verifyManually(
'VERIFY: Are we now inside the inner group?\n' +
'Can you see the two original rectangles at their original positions?\n' +
'First at (430, 130), second at (510, 130)?\n\n' +
'Click OK if yes, Cancel if no'
);
// All shapes should still be at their original positions
await assertShapeExists(430, 130, 'First shape should maintain position in nested group');

View File

@ -10,7 +10,9 @@ import { waitForAppReady } from '../../helpers/app.js';
import {
drawRectangle,
selectMultipleShapes,
selectTool,
dragCanvas,
clickCanvas,
setPlayheadTime,
getPlayheadTime,
addKeyframe,
@ -42,7 +44,7 @@ describe('MANUAL: Timeline Animation', () => {
it('TEST 1: Group animation - draw, group, keyframe, move group', async () => {
await logStep('Drawing a RED rectangle at (100, 100) with size 100x100');
await drawRectangle(100, 100, 100, 100, true, '#ff0000');
await pauseAndDescribe('RED rectangle drawn', 2000);
await pauseAndDescribe('RED rectangle drawn', 200);
await verifyManually(
'VERIFY: Do you see a RED filled rectangle at the top-left area?\n' +
@ -52,7 +54,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Selecting the RED rectangle by dragging a selection box over it');
await selectMultipleShapes([{ x: 150, y: 150 }]);
await pauseAndDescribe('RED rectangle selected', 2000);
await pauseAndDescribe('RED rectangle selected', 200);
await verifyManually(
'VERIFY: Is the RED rectangle now selected? (Should have selection indicators)\n\n' +
@ -61,7 +63,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Grouping the selected rectangle (Ctrl+G)');
await useKeyboardShortcut('g', true);
await pauseAndDescribe('RED rectangle grouped', 2000);
await pauseAndDescribe('RED rectangle grouped', 200);
await verifyManually(
'VERIFY: Was the rectangle grouped? (May look similar but is now a group)\n\n' +
@ -70,11 +72,11 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Selecting the group by dragging a selection box over it');
await selectMultipleShapes([{ x: 150, y: 150 }]);
await pauseAndDescribe('Group selected', 2000);
await pauseAndDescribe('Group selected', 200);
await logStep('Moving playhead to time 0.333 (frame 10 at 30fps)');
await setPlayheadTime(0.333);
await pauseAndDescribe('Playhead moved to 0.333s - WAIT for UI to update', 3000);
await pauseAndDescribe('Playhead moved to 0.333s - WAIT for UI to update', 300);
await verifyManually(
'VERIFY: Did the playhead indicator move on the timeline?\n' +
@ -84,7 +86,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Adding a keyframe at current position');
await addKeyframe();
await pauseAndDescribe('Keyframe added', 2000);
await pauseAndDescribe('Keyframe added', 200);
await verifyManually(
'VERIFY: Was a keyframe added? (Should see a keyframe marker on timeline)\n\n' +
@ -93,7 +95,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Dragging the selected group to move it right (from x=150 to x=250)');
await dragCanvas(150, 150, 250, 150);
await pauseAndDescribe('Group moved to the right', 3000);
await pauseAndDescribe('Group moved to the right', 300);
await verifyManually(
'VERIFY: Did the RED rectangle move to the right?\n' +
@ -103,7 +105,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Moving playhead back to time 0 (frame 1)');
await setPlayheadTime(0);
await pauseAndDescribe('Playhead back at start', 3000);
await pauseAndDescribe('Playhead back at start', 300);
await verifyManually(
'VERIFY: Did the RED rectangle jump back to its original position (x=150)?\n' +
@ -113,7 +115,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Moving playhead to middle (time 0.166, frame 5)');
await setPlayheadTime(0.166);
await pauseAndDescribe('Playhead at middle frame', 3000);
await pauseAndDescribe('Playhead at middle frame', 300);
await verifyManually(
'VERIFY: Is the RED rectangle now between the two positions?\n' +
@ -123,13 +125,13 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Moving playhead back and forth to show animation');
await setPlayheadTime(0);
await browser.pause(1000);
await browser.pause(300);
await setPlayheadTime(0.333);
await browser.pause(1000);
await browser.pause(300);
await setPlayheadTime(0);
await browser.pause(1000);
await browser.pause(300);
await setPlayheadTime(0.333);
await browser.pause(1000);
await browser.pause(300);
await verifyManually(
'VERIFY: Did you see the RED rectangle animate back and forth?\n' +
@ -146,9 +148,13 @@ describe('MANUAL: Timeline Animation', () => {
});
it('TEST 2: Shape tween - draw shape, add keyframes, modify edges', async () => {
await logStep('Resetting playhead to time 0 at start of test');
await setPlayheadTime(0);
await pauseAndDescribe('Playhead reset to time 0', 200);
await logStep('Drawing a BLUE rectangle at (400, 100)');
await drawRectangle(400, 100, 80, 80, true, '#0000ff');
await pauseAndDescribe('BLUE rectangle drawn', 2000);
await pauseAndDescribe('BLUE rectangle drawn', 200);
await verifyManually(
'VERIFY: Do you see a BLUE filled rectangle?\n' +
@ -158,7 +164,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Selecting the BLUE rectangle');
await selectMultipleShapes([{ x: 440, y: 140 }]);
await pauseAndDescribe('BLUE rectangle selected', 2000);
await pauseAndDescribe('BLUE rectangle selected', 200);
await verifyManually(
'VERIFY: Is the BLUE rectangle selected?\n' +
@ -166,9 +172,9 @@ describe('MANUAL: Timeline Animation', () => {
'Click OK if yes, Cancel if no'
);
await logStep('Moving playhead to time 0.5');
await logStep('Moving playhead to time 0.5 (frame 12 at 24fps)');
await setPlayheadTime(0.5);
await pauseAndDescribe('Playhead moved to 0.5s - WAIT for UI to update', 3000);
await pauseAndDescribe('Playhead moved to 0.5s - WAIT for UI to update', 300);
await verifyManually(
'VERIFY: Did the playhead move to 0.5s on the timeline?\n\n' +
@ -177,16 +183,26 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Adding a keyframe at time 0.5');
await addKeyframe();
await pauseAndDescribe('Keyframe added at 0.5s', 2000);
await pauseAndDescribe('Keyframe added at 0.5s', 200);
await verifyManually(
'VERIFY: Was a keyframe added at 0.5s?\n\n' +
'Click OK if yes, Cancel if no'
);
await logStep('Clicking away from the shape to deselect it');
await clickCanvas(600, 300);
await pauseAndDescribe('Shape deselected', 100);
await verifyManually(
'VERIFY: Is the BLUE rectangle now deselected?\n' +
'(No selection indicators around it)\n\n' +
'Click OK if yes, Cancel if no'
);
await logStep('Dragging the right edge of the BLUE rectangle to curve/extend it');
await dragCanvas(480, 140, 530, 140);
await pauseAndDescribe('Dragged right edge of BLUE rectangle', 3000);
await pauseAndDescribe('Dragged right edge of BLUE rectangle', 300);
await verifyManually(
'VERIFY: Did the right edge of the BLUE rectangle get curved/pulled out?\n' +
@ -196,7 +212,7 @@ describe('MANUAL: Timeline Animation', () => {
await logStep('Moving playhead back to time 0');
await setPlayheadTime(0);
await pauseAndDescribe('Playhead back at start', 3000);
await pauseAndDescribe('Playhead back at start', 300);
await verifyManually(
'VERIFY: Did the BLUE rectangle return to its original rectangular shape?\n' +
@ -204,13 +220,14 @@ describe('MANUAL: Timeline Animation', () => {
'Click OK if yes, Cancel if no'
);
await logStep('Moving playhead to middle (time 0.25)');
await logStep('Moving playhead to middle between keyframes (time 0.25, frame 6)');
await setPlayheadTime(0.25);
await pauseAndDescribe('Playhead at middle (0.25s)', 3000);
await pauseAndDescribe('Playhead at middle (0.25s) - halfway between frame 0 and frame 12', 300);
await verifyManually(
'VERIFY: Is the BLUE rectangle shape somewhere between the two versions?\n' +
'It should be partially morphed (shape tween interpolation)\n\n' +
'It should be partially morphed (shape tween interpolation)\n' +
'Halfway between the original rectangle and the curved version\n\n' +
'Click OK if yes, Cancel if no'
);
@ -223,9 +240,13 @@ describe('MANUAL: Timeline Animation', () => {
});
it('TEST 3: Test dragging unselected shape edge', async () => {
await logStep('Resetting playhead to time 0');
await setPlayheadTime(0);
await pauseAndDescribe('Playhead reset to time 0', 100);
await logStep('Drawing a GREEN rectangle at (200, 250) WITHOUT selecting it');
await drawRectangle(200, 250, 100, 100, true, '#00ff00');
await pauseAndDescribe('GREEN rectangle drawn (not selected)', 2000);
await pauseAndDescribe('GREEN rectangle drawn (not selected)', 100);
await verifyManually(
'VERIFY: GREEN rectangle should be visible but NOT selected\n' +
@ -233,9 +254,13 @@ describe('MANUAL: Timeline Animation', () => {
'Click OK if yes, Cancel if no'
);
await logStep('Switching to select tool');
await selectTool('select');
await pauseAndDescribe('Select tool activated', 100);
await logStep('Dragging from the right edge (x=300) of GREEN rectangle to extend it');
await dragCanvas(300, 300, 350, 300);
await pauseAndDescribe('Dragged the right edge of GREEN rectangle', 3000);
await pauseAndDescribe('Dragged the right edge of GREEN rectangle', 200);
await verifyManually(
'VERIFY: What happened to the GREEN rectangle?\n\n' +

View File

@ -48,9 +48,9 @@ describe('Shape Drawing', () => {
});
it('should draw large rectangles', async () => {
// Draw a large rectangle
await drawRectangle(50, 300, 400, 200);
await assertShapeExists(250, 400, 'Large rectangle should exist at center');
// Draw a large rectangle (canvas is ~350px tall, so keep within bounds)
await drawRectangle(50, 50, 400, 250);
await assertShapeExists(250, 175, 'Large rectangle should exist at center');
});
});

View File

@ -19,6 +19,7 @@ import {
getPixelColor
} from '../helpers/canvas.js';
import { assertShapeExists } from '../helpers/assertions.js';
import { verifyManually, logStep } from '../helpers/manual.js';
describe('Timeline Animation', () => {
before(async () => {
@ -44,10 +45,19 @@ describe('Timeline Animation', () => {
await addKeyframe();
await browser.pause(200);
await logStep('About to drag selected shape - dragging selected shapes does not move them yet');
// Shape is selected, so dragging from its center will move it
await dragCanvas(150, 150, 250, 150);
await browser.pause(300);
await verifyManually(
'VERIFY: Did the shape move to x=250?\n' +
'Expected: Shape at x=250\n' +
'Note: Dragging selected shapes is not implemented yet\n\n' +
'Click OK if at x=250, Cancel if not'
);
// At frame 10, shape should be at the new position (moved 100px to the right)
await assertShapeExists(250, 150, 'Shape should be at new position at frame 10');
@ -55,6 +65,11 @@ describe('Timeline Animation', () => {
await setPlayheadTime(0);
await browser.pause(200);
await verifyManually(
'VERIFY: Did the shape return to original position (x=150)?\n\n' +
'Click OK if yes, Cancel if no'
);
// Shape should be at original position
await assertShapeExists(150, 150, 'Shape should be at original position at frame 1');
@ -62,6 +77,11 @@ describe('Timeline Animation', () => {
await setPlayheadTime(0.166);
await browser.pause(200);
await verifyManually(
'VERIFY: Is the shape interpolated at x=200 (halfway)?\n\n' +
'Click OK if yes, Cancel if no'
);
// Shape should be interpolated between the two positions
// At frame 5 (halfway), shape should be around x=200 (halfway between 150 and 250)
await assertShapeExists(200, 150, 'Shape should be interpolated at frame 5');
@ -91,74 +111,85 @@ describe('Timeline Animation', () => {
it('should handle multiple keyframes on the same shape', async () => {
// Draw a shape
await drawRectangle(100, 300, 80, 80);
await drawRectangle(100, 100, 80, 80);
// Select it
await selectMultipleShapes([{ x: 140, y: 340 }]);
await selectMultipleShapes([{ x: 140, y: 140 }]);
await browser.pause(200);
// Keyframe 1: time 0 (original position at x=140, y=340)
// Keyframe 1: time 0 (original position at x=140, y=140)
// Keyframe 2: time 0.333 (move right)
await setPlayheadTime(0.333);
await addKeyframe();
await browser.pause(200);
await logStep('Dragging selected shape (not implemented yet)');
// Shape should still be selected, drag to move
await dragCanvas(140, 340, 200, 340);
await dragCanvas(140, 140, 200, 140);
await browser.pause(300);
// Keyframe 3: time 0.666 (move down but stay within canvas)
await verifyManually('VERIFY: Did shape move to x=200? (probably not)\nClick OK if at x=200, Cancel if not');
// Keyframe 3: time 0.666 (move down)
await setPlayheadTime(0.666);
await addKeyframe();
await browser.pause(200);
// Drag to move down (y=380 instead of 400 to stay in canvas)
await dragCanvas(200, 340, 200, 380);
// Drag to move down
await dragCanvas(200, 140, 200, 180);
await browser.pause(300);
await verifyManually('VERIFY: Did shape move to y=180?\nClick OK if yes, Cancel if no');
// Verify positions at each keyframe
await setPlayheadTime(0);
await browser.pause(200);
await assertShapeExists(140, 340, 'Shape at keyframe 1 (x=140, y=340)');
await verifyManually('VERIFY: Shape at original position (x=140, y=140)?\nClick OK if yes, Cancel if no');
await assertShapeExists(140, 140, 'Shape at keyframe 1 (x=140, y=140)');
await setPlayheadTime(0.333);
await browser.pause(200);
await assertShapeExists(200, 340, 'Shape at keyframe 2 (x=200, y=340)');
await verifyManually('VERIFY: Shape at x=200, y=140?\nClick OK if yes, Cancel if no');
await assertShapeExists(200, 140, 'Shape at keyframe 2 (x=200, y=140)');
await setPlayheadTime(0.666);
await browser.pause(200);
await assertShapeExists(200, 380, 'Shape at keyframe 3 (x=200, y=380)');
await verifyManually('VERIFY: Shape at x=200, y=180?\nClick OK if yes, Cancel if no');
await assertShapeExists(200, 180, 'Shape at keyframe 3 (x=200, y=180)');
// Check interpolation between keyframe 1 and 2 (at t=0.166, halfway)
await setPlayheadTime(0.166);
await browser.pause(200);
await assertShapeExists(170, 340, 'Shape interpolated between kf1 and kf2');
await verifyManually('VERIFY: Shape interpolated at x=170, y=140?\nClick OK if yes, Cancel if no');
await assertShapeExists(170, 140, 'Shape interpolated between kf1 and kf2');
// Check interpolation between keyframe 2 and 3 (at t=0.5, halfway)
await setPlayheadTime(0.5);
await browser.pause(200);
await assertShapeExists(200, 360, 'Shape interpolated between kf2 and kf3');
await verifyManually('VERIFY: Shape interpolated at x=200, y=160?\nClick OK if yes, Cancel if no');
await assertShapeExists(200, 160, 'Shape interpolated between kf2 and kf3');
});
});
describe('Group/Object Animation', () => {
it('should animate group position across keyframes', async () => {
// Create a group with two shapes
await drawRectangle(300, 300, 60, 60);
await drawRectangle(380, 300, 60, 60);
await drawRectangle(300, 100, 60, 60);
await drawRectangle(380, 100, 60, 60);
await selectMultipleShapes([
{ x: 330, y: 330 },
{ x: 410, y: 330 }
{ x: 330, y: 130 },
{ x: 410, y: 130 }
]);
await useKeyboardShortcut('g', true);
await browser.pause(300);
// Verify both shapes exist at frame 1
await assertShapeExists(330, 330, 'First shape at frame 1');
await assertShapeExists(410, 330, 'Second shape at frame 1');
await assertShapeExists(330, 130, 'First shape at frame 1');
await assertShapeExists(410, 130, 'Second shape at frame 1');
// Select the group by dragging a selection box over it
await selectMultipleShapes([{ x: 370, y: 330 }]);
await selectMultipleShapes([{ x: 370, y: 130 }]);
await browser.pause(200);
// Move to frame 10 and add keyframe
@ -166,30 +197,37 @@ describe('Timeline Animation', () => {
await addKeyframe();
await browser.pause(200);
await logStep('Dragging group down');
// Group is selected, so dragging will move it
// Drag from center of group down (but keep it within canvas bounds)
await dragCanvas(370, 330, 370, 380);
// Drag from center of group down
await dragCanvas(370, 130, 370, 200);
await browser.pause(300);
// At frame 10, group should be at new position (moved 50px down)
await assertShapeExists(330, 380, 'First shape at new position at frame 10');
await assertShapeExists(410, 380, 'Second shape at new position at frame 10');
await verifyManually('VERIFY: Did the group move down to y=200?\nClick OK if yes, Cancel if no');
// At frame 10, group should be at new position (moved down)
await assertShapeExists(330, 200, 'First shape at new position at frame 10');
await assertShapeExists(410, 200, 'Second shape at new position at frame 10');
// Go to frame 1
await setPlayheadTime(0);
await browser.pause(200);
await verifyManually('VERIFY: Did group return to original position (y=130)?\nClick OK if yes, Cancel if no');
// Group should be at original position
await assertShapeExists(330, 330, 'First shape at original position at frame 1');
await assertShapeExists(410, 330, 'Second shape at original position at frame 1');
await assertShapeExists(330, 130, 'First shape at original position at frame 1');
await assertShapeExists(410, 130, 'Second shape at original position at frame 1');
// Go to frame 5 (middle, t=0.166)
await setPlayheadTime(0.166);
await browser.pause(200);
// Group should be interpolated (halfway between y=330 and y=380, so y=355)
await assertShapeExists(330, 355, 'First shape interpolated at frame 5');
await assertShapeExists(410, 355, 'Second shape interpolated at frame 5');
await verifyManually('VERIFY: Is group interpolated at y=165 (halfway)?\nClick OK if yes, Cancel if no');
// Group should be interpolated (halfway between y=130 and y=200, so y=165)
await assertShapeExists(330, 165, 'First shape interpolated at frame 5');
await assertShapeExists(410, 165, 'Second shape interpolated at frame 5');
});
it('should maintain relative positions of shapes within animated group', async () => {
@ -233,41 +271,47 @@ describe('Timeline Animation', () => {
describe('Interpolation', () => {
it('should smoothly interpolate between keyframes', async () => {
// Draw a simple shape
await drawRectangle(500, 100, 50, 50);
await drawRectangle(100, 100, 50, 50);
// Select it
await selectMultipleShapes([{ x: 525, y: 125 }]);
await selectMultipleShapes([{ x: 125, y: 125 }]);
await browser.pause(200);
// Keyframe at start (x=525)
// Keyframe at start (x=125)
await setPlayheadTime(0);
await browser.pause(100);
// Keyframe at end (1 second = frame 30, move to x=725)
// Keyframe at end (1 second = frame 30, move to x=325)
await setPlayheadTime(1.0);
await addKeyframe();
await browser.pause(200);
await dragCanvas(525, 125, 725, 125);
await logStep('Dragging shape (selected shapes cannot be dragged yet)');
await dragCanvas(125, 125, 325, 125);
await browser.pause(300);
await verifyManually('VERIFY: Did shape move to x=325? (probably not)\nClick OK if at x=325, Cancel if not');
// Check multiple intermediate frames for smooth interpolation
// Total movement: 200px over 1 second
// At 25% (0.25s), x should be 525 + 50 = 575
// At 25% (0.25s), x should be 125 + 50 = 175
await setPlayheadTime(0.25);
await browser.pause(200);
await assertShapeExists(575, 125, 'Shape at 25% interpolation');
await verifyManually('VERIFY: Shape at x=175 (25% interpolation)?\nClick OK if yes, Cancel if no');
await assertShapeExists(175, 125, 'Shape at 25% interpolation');
// At 50% (0.5s), x should be 525 + 100 = 625
// At 50% (0.5s), x should be 125 + 100 = 225
await setPlayheadTime(0.5);
await browser.pause(200);
await assertShapeExists(625, 125, 'Shape at 50% interpolation');
await verifyManually('VERIFY: Shape at x=225 (50% interpolation)?\nClick OK if yes, Cancel if no');
await assertShapeExists(225, 125, 'Shape at 50% interpolation');
// At 75% (0.75s), x should be 525 + 150 = 675
// At 75% (0.75s), x should be 125 + 150 = 275
await setPlayheadTime(0.75);
await browser.pause(200);
await assertShapeExists(675, 125, 'Shape at 75% interpolation');
await verifyManually('VERIFY: Shape at x=275 (75% interpolation)?\nClick OK if yes, Cancel if no');
await assertShapeExists(275, 125, 'Shape at 75% interpolation');
});
});
});