src/lib/chart-zoom.test.ts
Rama main · réplica de lectura del repositorio original.
import { describe, expect, it } from "vitest";
import {
type ChartView,
fullView,
isZoomed,
panView,
scaleView,
} from "./chart-zoom";
describe("scaleView", () => {
it("holds the instant under a wheel where it was", () => {
// A quarter of the way across 0-1000, zoomed 2x: 250 stays a quarter across.
expect(scaleView(fullView(1000), 2, 0.25, 0.25, 1000, 10)).toEqual({
start: 125,
end: 625,
});
});
it("carries the anchor along with fingers that slide while they pinch", () => {
// 500 was half-way; the fingers' midpoint ends a quarter across.
expect(scaleView(fullView(1000), 2, 0.5, 0.25, 1000, 10)).toEqual({
start: 375,
end: 875,
});
});
it("zooms no closer than the minimum span", () => {
const view = scaleView(fullView(1000), 1000, 0.5, 0.5, 1000, 100);
expect(view.end - view.start).toBe(100);
});
it("zooms no further out than the whole axis, and stays on it", () => {
expect(scaleView({ start: 800, end: 900 }, 0.01, 0, 0, 1000, 10)).toEqual(
fullView(1000),
);
expect(scaleView({ start: 800, end: 1000 }, 0.5, 1, 1, 1000, 10)).toEqual({
start: 600,
end: 1000,
});
});
it("comes back to the whole axis from a zoom in and out by the same factor", () => {
for (const anchor of [0, 0.25, 0.3, 0.5, 0.7, 1]) {
const zoomedIn = scaleView(
fullView(2_781_000),
Math.exp(0.5),
anchor,
anchor,
2_781_000,
60_000,
);
expect(
scaleView(zoomedIn, Math.exp(-0.5), anchor, anchor, 2_781_000, 60_000),
).toEqual(fullView(2_781_000));
}
});
it("comes back to the whole axis from wheel steps in and out", () => {
// A wheel zooms each step on the view the last one left.
const step = (view: ChartView, factor: number, anchor: number) =>
scaleView(view, factor, anchor, anchor, 3_600_000, 60_000);
for (const notches of [1, 2, 5, 8]) {
for (const anchor of [0.123, 0.5, 0.9]) {
let view = fullView(3_600_000);
for (let n = 0; n < notches; n++)
view = step(view, Math.exp(0.5), anchor);
for (let n = 0; n < notches; n++)
view = step(view, Math.exp(-0.5), anchor);
expect(view, `${notches} at ${anchor}`).toEqual(fullView(3_600_000));
}
}
});
it("does not zoom an axis shorter than the minimum span", () => {
expect(scaleView(fullView(50), 4, 0.5, 0.5, 50, 100)).toEqual(fullView(50));
});
});
describe("panView", () => {
it("moves the view and keeps its span", () => {
expect(panView({ start: 100, end: 300 }, 50, 1000)).toEqual({
start: 150,
end: 350,
});
});
it("stops at either end", () => {
expect(panView({ start: 100, end: 300 }, -500, 1000)).toEqual({
start: 0,
end: 200,
});
expect(panView({ start: 700, end: 900 }, 500, 1000)).toEqual({
start: 800,
end: 1000,
});
});
});
describe("isZoomed", () => {
it("is false only for the whole axis", () => {
expect(isZoomed(fullView(1000), 1000)).toBe(false);
expect(isZoomed({ start: 0, end: 999 }, 1000)).toBe(true);
});
});