mirror of
https://github.com/captbaritone/webamp.git
synced 2026-01-23 18:25:30 +00:00
477 lines
17 KiB
TypeScript
477 lines
17 KiB
TypeScript
import {
|
|
top,
|
|
bottom,
|
|
left,
|
|
right,
|
|
near,
|
|
snap,
|
|
overlapY,
|
|
overlapX,
|
|
snapWithin,
|
|
applySnap,
|
|
snapDiff,
|
|
boundingBox,
|
|
applyMultipleDiffs
|
|
} from "./snapUtils";
|
|
|
|
describe("side functions", () => {
|
|
const box = { x: 10, y: 15, width: 50, height: 100 };
|
|
it("can find the top of a box", () => {
|
|
const actual = top(box);
|
|
const expected = 15;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("can find the bottom of a box", () => {
|
|
const actual = bottom(box);
|
|
const expected = 115;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("can find the left of a box", () => {
|
|
const actual = left(box);
|
|
const expected = 10;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("can find the right of a box", () => {
|
|
const actual = right(box);
|
|
const expected = 60;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("near function", () => {
|
|
it("can tell if A is near B", () => {
|
|
const actual = near(10, 20);
|
|
const expected = true;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("can tell if A is near B", () => {
|
|
const actual = near(10, 30);
|
|
const expected = false;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("overlap functions", () => {
|
|
it("overlapY detects when the boxes overlap in the Y axis", () => {
|
|
const a = { y: 10, height: 50, width: 100, x: 0 };
|
|
const b = { y: 40, height: 50, width: 100, x: 0 };
|
|
const actual = overlapY(a, b);
|
|
const expected = true;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("overlapY detects when the boxes are within SNAP_DISTANCE on the Y axis", () => {
|
|
const a = { y: 10, height: 50, width: 100, x: 0 };
|
|
const b = { y: 70, height: 50, width: 100, x: 0 };
|
|
const actual = overlapY(a, b);
|
|
const expected = true;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("overlapY detects when the boxes do not overlap in the Y axis", () => {
|
|
const a = { y: 10, height: 50, width: 100, x: 0 };
|
|
const b = { y: 90, height: 50, width: 100, x: 0 };
|
|
const actual = overlapY(a, b);
|
|
const expected = false;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("overlapX detects when the boxes overlap in the X axis", () => {
|
|
const a = { x: 10, width: 50, height: 100, y: 0 };
|
|
const b = { x: 40, width: 50, height: 100, y: 0 };
|
|
const actual = overlapX(a, b);
|
|
const expected = true;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("overlapX detects when the boxes are within SNAP_DISTANCE on the X axis", () => {
|
|
const a = { x: 10, width: 50, height: 100, y: 0 };
|
|
const b = { x: 70, width: 50, height: 100, y: 0 };
|
|
const actual = overlapX(a, b);
|
|
const expected = true;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("overlapX detects when the boxes do not overlap in the X axis", () => {
|
|
const a = { x: 10, width: 50, height: 100, y: 0 };
|
|
const b = { x: 90, width: 50, height: 100, y: 0 };
|
|
const actual = overlapX(a, b);
|
|
const expected = false;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("snap function", () => {
|
|
it("does not snap if A and B are obviously far apart", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 200, y: 200, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = {};
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the left of A to the right of B", () => {
|
|
const a = { x: 120, y: 30, width: 100, height: 100 };
|
|
const b = { x: 10, y: 10, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 110 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the right of A to the left of B", () => {
|
|
const a = { x: 10, y: 30, width: 100, height: 100 };
|
|
const b = { x: 120, y: 10, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 20 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top of A to the bottom of B", () => {
|
|
const a = { x: 30, y: 10, width: 100, height: 100 };
|
|
const b = { x: 10, y: 120, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { y: 20 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the bottom of A to the top of B", () => {
|
|
const a = { x: 30, y: 120, width: 100, height: 100 };
|
|
const b = { x: 10, y: 10, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { y: 110 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("does not snap to the X axis if A is below B", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 110, y: 150, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = {};
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps in both axis if the corners are within SNAP_DISTANCE", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 120, y: 120, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 20, y: 20 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the left of A to the left of B", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 15, y: 110, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 15, y: 10 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top of A to the bottom of B", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 110, y: 15, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 10, y: 15 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top left corner of A to the bottom right corner of B", () => {
|
|
const a = { x: 110, y: 110, width: 100, height: 100 };
|
|
const b = { x: 0, y: 0, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 100, y: 100 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top of A down to the bottom of B, if A slighterly overlaps B", () => {
|
|
const a = { x: 0, y: 90, width: 100, height: 100 };
|
|
const b = { x: 0, y: 0, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 0, y: 100 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top of A down to the bottom of B, if A slighterly overlaps B", () => {
|
|
const a = { x: 0, y: 90, width: 100, height: 100 };
|
|
const b = { x: 0, y: 0, width: 100, height: 100 };
|
|
const actual = snap(a, b);
|
|
const expected = { x: 0, y: 100 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("snapWithin function", () => {
|
|
it("snaps the inner box to the top of the outer box", () => {
|
|
const inner = { x: 120, y: 10, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the bottom of the outer box", () => {
|
|
const inner = { x: 120, y: 910, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { y: 900 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the right of the outer box", () => {
|
|
const inner = { x: 910, y: 120, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { x: 900 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the left of the outer box", () => {
|
|
const inner = { x: 10, y: 120, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { x: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the top-left of the outer box", () => {
|
|
const inner = { x: 10, y: 10, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { x: 0, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("applySnap function", () => {
|
|
it("does not apply undefined values", () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped = { x: undefined, y: undefined };
|
|
const actual = applySnap(original, snapped);
|
|
const expected = original;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("preserves other values on original", () => {
|
|
const original = { x: 10, y: 10, foo: "bar" };
|
|
const snapped = { x: 50, y: 50 };
|
|
const actual = applySnap(original, snapped);
|
|
const expected = { x: 50, y: 50, foo: "bar" };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it('will clobber original with falsy "0" values', () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped = { x: 0, y: 0 };
|
|
const actual = applySnap(original, snapped);
|
|
expect(actual).toEqual(snapped);
|
|
});
|
|
it('will clobber original with falsy "0" values', () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped = { x: 0, y: 0 };
|
|
const actual = applySnap(original, snapped);
|
|
expect(actual).toEqual(snapped);
|
|
});
|
|
it("can apply multiple snaps", () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped1 = { x: 0 };
|
|
const snapped2 = { y: 0 };
|
|
const actual = applySnap(original, snapped1, snapped2);
|
|
const expected = { x: 0, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("the last snap wins", () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped1 = { x: 50, y: 20 };
|
|
const snapped2 = { x: 60, y: 60 };
|
|
const actual = applySnap(original, snapped1, snapped2);
|
|
const expected = { x: 60, y: 60 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("snap diff", () => {
|
|
it("does not snap if A and B are obviously far apart", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 200, y: 200, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 0, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the left of A to the right of B", () => {
|
|
const a = { x: 120, y: 30, width: 100, height: 100 };
|
|
const b = { x: 10, y: 10, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: -10, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the right of A to the left of B", () => {
|
|
const a = { x: 10, y: 30, width: 100, height: 100 };
|
|
const b = { x: 120, y: 10, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 10, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top of A to the bottom of B", () => {
|
|
const a = { x: 30, y: 10, width: 100, height: 100 };
|
|
const b = { x: 10, y: 120, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 0, y: 10 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the bottom of A to the top of B", () => {
|
|
const a = { x: 30, y: 120, width: 100, height: 100 };
|
|
const b = { x: 10, y: 10, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 0, y: -10 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("does not snap to the X axis if A is below B", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 110, y: 150, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 0, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps in both axis if the corners are within SNAP_DISTANCE", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 120, y: 120, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 10, y: 10 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the left of A to the left of B", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 15, y: 110, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 5, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top of A to the bottom of B", () => {
|
|
const a = { x: 10, y: 10, width: 100, height: 100 };
|
|
const b = { x: 110, y: 15, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: 0, y: 5 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the top left corner of A to the bottom right corner of B", () => {
|
|
const a = { x: 110, y: 110, width: 100, height: 100 };
|
|
const b = { x: 0, y: 0, width: 100, height: 100 };
|
|
const actual = snapDiff(a, b);
|
|
const expected = { x: -10, y: -10 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("snapWithin function", () => {
|
|
it("snaps the inner box to the top of the outer box", () => {
|
|
const inner = { x: 120, y: 10, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the bottom of the outer box", () => {
|
|
const inner = { x: 120, y: 910, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { y: 900 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the right of the outer box", () => {
|
|
const inner = { x: 910, y: 120, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { x: 900 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the left of the outer box", () => {
|
|
const inner = { x: 10, y: 120, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { x: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("snaps the inner box to the top-left of the outer box", () => {
|
|
const inner = { x: 10, y: 10, width: 100, height: 100 };
|
|
const outer = { width: 1000, height: 1000 };
|
|
const actual = snapWithin(inner, outer);
|
|
const expected = { x: 0, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe("boundingBox function", () => {
|
|
it("does not mutate the given array", () => {
|
|
const box = { x: 10, y: 10, width: 100, height: 100 };
|
|
const boxesA = [box];
|
|
const boxesB = [box];
|
|
boundingBox(boxesA);
|
|
expect(boxesA).toEqual(boxesB);
|
|
});
|
|
it("returns iteself when called on a single box", () => {
|
|
const box = { x: 10, y: 10, width: 100, height: 100 };
|
|
expect(boundingBox([box])).toEqual(box);
|
|
});
|
|
it("returns the larger box when one fits entire within another", () => {
|
|
const boxes = [
|
|
{ x: 10, y: 10, width: 100, height: 100 },
|
|
{ x: 20, y: 20, width: 80, height: 80 }
|
|
];
|
|
expect(boundingBox(boxes)).toEqual(boxes[0]);
|
|
});
|
|
it("returns countaing box of two boxes", () => {
|
|
const boxes = [
|
|
{ x: 10, y: 10, width: 100, height: 100 },
|
|
{ x: 120, y: 220, width: 100, height: 100 }
|
|
];
|
|
expect(boundingBox(boxes)).toEqual({
|
|
x: 10,
|
|
y: 10,
|
|
width: 210,
|
|
height: 310
|
|
});
|
|
});
|
|
it("returns countaing box of three boxes", () => {
|
|
const boxes = [
|
|
{ x: 10, y: 10, width: 100, height: 100 },
|
|
{ x: 120, y: 220, width: 100, height: 100 },
|
|
{ x: 3, y: 220, width: 100, height: 100 }
|
|
];
|
|
expect(boundingBox(boxes)).toEqual({
|
|
x: 3,
|
|
y: 10,
|
|
width: 217,
|
|
height: 310
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("applySnap function", () => {
|
|
it("does not apply undefined values", () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped = { x: undefined, y: undefined };
|
|
const actual = applySnap(original, snapped);
|
|
const expected = original;
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("preserves other values on original", () => {
|
|
const original = { x: 10, y: 10, foo: "bar" };
|
|
const snapped = { x: 50, y: 50 };
|
|
const actual = applySnap(original, snapped);
|
|
const expected = { x: 50, y: 50, foo: "bar" };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it('will clobber original with falsy "0" values', () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped = { x: 0, y: 0 };
|
|
const actual = applySnap(original, snapped);
|
|
expect(actual).toEqual(snapped);
|
|
});
|
|
it('will clobber original with falsy "0" values', () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped = { x: 0, y: 0 };
|
|
const actual = applySnap(original, snapped);
|
|
expect(actual).toEqual(snapped);
|
|
});
|
|
it("can apply multiple snaps", () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped1 = { x: 0 };
|
|
const snapped2 = { y: 0 };
|
|
const actual = applySnap(original, snapped1, snapped2);
|
|
const expected = { x: 0, y: 0 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
it("the last snap wins", () => {
|
|
const original = { x: 10, y: 10 };
|
|
const snapped1 = { x: 50, y: 20 };
|
|
const snapped2 = { x: 60, y: 60 };
|
|
const actual = applySnap(original, snapped1, snapped2);
|
|
const expected = { x: 60, y: 60 };
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
describe("applyMultipleDiffs", () => {
|
|
it("uses the smallest non-zero value for each axis", () => {
|
|
expect(
|
|
applyMultipleDiffs({ x: 31, y: -8 }, { x: 0, y: 8 }, { x: 0, y: 0 })
|
|
).toEqual({ x: 31, y: 0 });
|
|
});
|
|
});
|
|
});
|