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 }); }); }); });