Skip to content

Commit

Permalink
add rollwright spec to cover motion+spring
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyraspopov committed Oct 17, 2024
1 parent 084e785 commit c910597
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 19 deletions.
3 changes: 3 additions & 0 deletions motion.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const MS_PER_FRAME = 1000 / 60;
const MAX_SKIP_FRAME = 10;

export function motion(defs, callback, options) {
let updt = updateOf(defs);
let intp = interpolateOf(defs);
Expand Down
121 changes: 121 additions & 0 deletions oscillation.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { test as base } from "rollwright";
import { expect } from "@playwright/test";

let test = base.extend({
advance: async ({ execute }, use) => {
let advance = await execute(() => {
let timestamp = 0;
window.performance = { now: () => timestamp };

let callbacks = {};
let id = 0;
window.requestAnimationFrame = (cb) => ((callbacks[id++] = cb), id);
window.cancelAnimationFrame = (id) => delete callbacks[id];

function step(ms) {
let cbs = callbacks;
callbacks = {};
timestamp += ms;
for (let k in cbs) cbs[k](timestamp);
}

return (steps, ms) => {
for (let i = 0; i < steps; i++) step(ms);
};
});

await use((steps, ms) =>
execute((advance, steps, ms) => advance(steps, ms), advance, steps, ms),
);
},
});

test("interpolation with ideal timer condition", async ({ execute, advance }) => {
let snapshots = await execute(async () => {
let { motion } = await import("./motion.js");
let { spring } = await import("./spring.js");
let snapshots = [];
let ctl = new AbortController();
motion(spring(0, 10), (x) => snapshots.push(x), { signal: ctl.signal });
return snapshots;
});

await advance(1, 0);
await advance(5, 1000 / 60);

expect(await snapshots.jsonValue()).toEqual([
0, 0.47241496285986795, 1.1901835641718526, 2.0130615470443205, 2.8566207208531145,
3.6720468997166984,
]);
});

test("eventual interpolation completeness", async ({ execute, advance }) => {
let snapshots = await execute(async () => {
let { motion } = await import("./motion.js");
let { spring } = await import("./spring.js");
let snapshots = [];
let ctl = new AbortController();
motion(spring(0, 10), (x) => snapshots.push(x), { signal: ctl.signal });
return snapshots;
});

await advance(1, 0);
await advance(69, 1000 / 60);

expect((await snapshots.jsonValue()).at(-1)).toBe(10);
});

test("interpolation with inconsistent timer condition", async ({ execute, advance }) => {
let snapshots = await execute(async () => {
let { motion } = await import("./motion.js");
let { spring } = await import("./spring.js");
let snapshots = [];
let ctl = new AbortController();
motion(spring(0, 10), (x) => snapshots.push(x), { signal: ctl.signal });
return snapshots;
});

await advance(1, 0);
expect(await snapshots.jsonValue()).toEqual([0]);

await advance(1, (1000 / 60) * 11);
expect(await snapshots.jsonValue()).toEqual([0]);

await advance(3, 0.1);
expect(await snapshots.jsonValue()).toEqual([
0, 0.0028344897771590463, 0.0056689795543180925, 0.008503469331477139,
]);

await advance(10, 999);
expect(await snapshots.jsonValue()).toEqual([
0, 0.0028344897771590463, 0.0056689795543180925, 0.008503469331477139,
]);

await advance(2, 36);
expect(await snapshots.jsonValue()).toEqual([
0, 0.0028344897771590463, 0.0056689795543180925, 0.008503469331477139, 1.3218440414314472,
3.117557098089461,
]);
});

test("explicit motion cancellation", async ({ execute, advance }) => {
let ctl = await execute(() => new AbortController());

let snapshots = await execute(async (ctl) => {
let { motion } = await import("./motion.js");
let { spring } = await import("./spring.js");
let snapshots = [];
motion(spring(-10, -100), (x) => snapshots.push(x), { signal: ctl.signal });
return snapshots;
}, ctl);

await advance(1, 0);
await advance(3, 1000 / 60);

await execute((ctl) => ctl.abort(), ctl);
await advance(2, 1000 / 60);

expect(await snapshots.jsonValue()).toEqual([
-10, -14.251734665738812, -20.711652077546674, -28.117553923398887,
]);
});
22 changes: 7 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
{
"workspaces": [
"packages/*"
],
"devDependencies": {
"@babel/preset-env": "^7.18.6",
"@babel/preset-react": "^7.18.6",
"@rollup/plugin-multi-entry": "^4.1.0",
"babel-jest": "^28.1.1",
"jest": "^28.1.1",
"prettier": "^2.7.1",
"rollup": "^2.55.1",
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-bundle-size": "^1.0.3",
"rollup-plugin-copy": "^3.4.0"
},
"type": "module",
"prettier": {
"printWidth": 100,
"trailingComma": "all",
"proseWrap": "always"
},
"devDependencies": {
"@playwright/test": "^1.48.1",
"prettier": "^3.3.3",
"rollup": "^4.24.0",
"rollwright": "^0.0.6"
}
}
7 changes: 7 additions & 0 deletions playwright.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from "@playwright/test";

export default defineConfig({
use: { headless: false },
testMatch: /.*\.spec\.js/,
reporter: [["list"], ["rollwright/coverage-reporter"]],
});
10 changes: 6 additions & 4 deletions spring.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const SEC_PER_FRAME = 1 / 60;

export let springs = {
noWobble: { damping: 0.997, frequency: 0.4818, precision: 0.01 },
gentle: { damping: 0.639, frequency: 0.5735, precision: 0.01 },
Expand Down Expand Up @@ -34,8 +36,8 @@ function singlespring(current, destination, damping, stiffness, precision) {
return true;
},
interpolate(t) {
let next = step(current, velocity, destination, damping, stiffness, precision);
return current + (next[0] - current) * t;
let tuple = step(current, velocity, destination, damping, stiffness, precision);
return current + (tuple[0] - current) * t;
},
};
}
Expand All @@ -58,11 +60,11 @@ function multispring(current, destination, damping, stiffness, precision) {
}
return true;
},
interpolate() {
interpolate(t) {
let tuple;
for (let i = 0; i < current.length; i++) {
tuple = step(current[i], velocity[i], destination[i], damping, stiffness, precision);
interpolated[i] = tuple[0];
interpolated[i] = current[i] + (tuple[0] - current[i]) * t;
}
return interpolated;
},
Expand Down

0 comments on commit c910597

Please sign in to comment.