/** * A graph is mostly looked at in parts (#292): a node outside the picture is left out of the drawing, * and what decides that is where its box, with what hangs over its edges, stands against the view. */ import { describe, expect, it } from 'vitest'; import { inView, NODE_OVERHANG } from '../../src/editor/graph/graphView'; const box = (x: number, y: number) => ({ x, y, w: 176, h: 80 }); const plain = { pan: { x: 0, y: 0 }, zoom: 1 }; describe('which nodes are in the picture', () => { it('keeps a node inside the view and drops one far outside it, on every side', () => { expect(inView(box(100, 100), plain, 800, 600)).toBe(true); expect(inView(box(-400, 100), plain, 800, 600)).toBe(false); expect(inView(box(1000, 100), plain, 800, 600)).toBe(false); expect(inView(box(100, -300), plain, 800, 600)).toBe(false); expect(inView(box(100, 800), plain, 800, 600)).toBe(false); }); it('keeps a node that only reaches into the view with a corner', () => { expect(inView(box(-170, -70), plain, 800, 600)).toBe(true); expect(inView(box(790, 590), plain, 800, 600)).toBe(true); }); it('keeps a node just outside for what it draws beyond its box', () => { // The pins sit on the edges and the shadow falls below: a box that ends right at the border // still has pixels inside it. expect(inView(box(-176 - NODE_OVERHANG + 1, 100), plain, 800, 600)).toBe(true); expect(inView(box(-176 - NODE_OVERHANG, 100), plain, 800, 600)).toBe(false); expect(inView(box(800 + NODE_OVERHANG - 1, 100), plain, 800, 600)).toBe(true); expect(inView(box(800 + NODE_OVERHANG, 100), plain, 800, 600)).toBe(false); expect(inView(box(100, -80 - NODE_OVERHANG + 1), plain, 800, 600)).toBe(true); expect(inView(box(100, -80 - NODE_OVERHANG), plain, 800, 600)).toBe(false); expect(inView(box(100, 600 + NODE_OVERHANG - 1), plain, 800, 600)).toBe(true); expect(inView(box(100, 600 + NODE_OVERHANG), plain, 800, 600)).toBe(false); }); it('follows the pan', () => { const far = box(2000, 1500); expect(inView(far, plain, 800, 600)).toBe(false); expect(inView(far, { pan: { x: -1800, y: -1300 }, zoom: 1 }, 800, 600)).toBe(true); expect(inView(box(100, 100), { pan: { x: -1800, y: -1300 }, zoom: 1 }, 800, 600)).toBe(false); // Each direction by itself: a node left behind on one axis is out, whatever the other says. expect(inView(box(100, 100), { pan: { x: -1800, y: 0 }, zoom: 1 }, 800, 600)).toBe(false); expect(inView(box(100, 100), { pan: { x: 0, y: -1300 }, zoom: 1 }, 800, 600)).toBe(false); expect(inView(box(-500, -400), { pan: { x: 600, y: 500 }, zoom: 1 }, 800, 600)).toBe(true); }); it('follows the zoom: zoomed out the view holds more, zoomed in less', () => { const node = box(1500, 100); expect(inView(node, plain, 800, 600)).toBe(false); expect(inView(node, { pan: { x: 0, y: 0 }, zoom: 0.5 }, 800, 600)).toBe(true); expect(inView(box(500, 100), { pan: { x: 0, y: 0 }, zoom: 2 }, 800, 600)).toBe(false); // Panned and zoomed at once, the view is the graph from 500 to 900 across and 500 to 800 down. const both = { pan: { x: -1000, y: -1000 }, zoom: 2 }; expect(inView(box(600, 560), both, 800, 600)).toBe(true); expect(inView(box(300, 560), both, 800, 600)).toBe(false); expect(inView(box(950, 560), both, 800, 600)).toBe(false); expect(inView(box(600, 380), both, 800, 600)).toBe(false); expect(inView(box(600, 900), both, 800, 600)).toBe(false); }); it('holds nothing while the canvas has no size', () => { expect(inView(box(100, 100), plain, 0, 0)).toBe(false); }); });