UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

386 lines (384 loc) 12.8 kB
"use strict"; var import_vitest = require("vitest"); var import_prefetchIntent = require("./prefetchIntent.native.js"); var rect = function (x, y) { var w = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 100, h = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 40; return { left: x, top: y, right: x + w, bottom: y + h, width: w, height: h, x, y, toJSON: function () { return {}; } }; }; (0, import_vitest.describe)("prefetchIntent", function () { var prefetched; var intent; (0, import_vitest.beforeEach)(function () { prefetched = []; intent = (0, import_prefetchIntent.createPrefetchIntent)({ onPrefetch: function (href) { return prefetched.push(href); } }); }); (0, import_vitest.describe)("basic targeting", function () { (0, import_vitest.it)("prefetches when moving directly toward a link", function () { intent.setRects([{ r: rect(500, 300), h: "/about" }]); intent.move(100, 300, 0, 0); intent.move(140, 300, 40, 0); intent.move(200, 300, 60, 0); (0, import_vitest.expect)(prefetched).toEqual(["/about"]); }); (0, import_vitest.it)("does not prefetch when moving away from a link", function () { intent.setRects([{ r: rect(500, 300), h: "/about" }]); intent.move(400, 300, 0, 0); intent.move(380, 300, -20, 0); intent.move(350, 300, -30, 0); (0, import_vitest.expect)(prefetched).toEqual([]); }); (0, import_vitest.it)("does not prefetch when moving perpendicular to a link", function () { intent.setRects([{ r: rect(500, 300), h: "/about" }]); intent.move(200, 300, 0, 0); intent.move(200, 330, 0, 30); intent.move(200, 370, 0, 40); (0, import_vitest.expect)(prefetched).toEqual([]); }); (0, import_vitest.it)("prefetches link at long distance with good aim", function () { intent.setRects([{ r: rect(500, 280), h: "/far" }]); intent.move(100, 300, 0, 0); intent.move(140, 300, 40, 0); intent.move(200, 300, 60, 0); (0, import_vitest.expect)(prefetched).toEqual(["/far"]); }); (0, import_vitest.it)("does not prefetch when aim is slightly off at long distance", function () { intent.setRects([{ r: rect(600, 300), h: "/far" }]); intent.move(100, 300, 0, 0); intent.move(140, 320, 40, 20); intent.move(200, 360, 60, 40); (0, import_vitest.expect)(prefetched).toEqual([]); }); }); (0, import_vitest.describe)("prevents over-fetching", function () { (0, import_vitest.it)("only prefetches each href once", function () { intent.setRects([{ r: rect(500, 300), h: "/about" }]); intent.move(100, 300, 0, 0); intent.move(140, 300, 40, 0); intent.move(200, 300, 60, 0); (0, import_vitest.expect)(prefetched).toEqual(["/about"]); intent.move(100, 300, -100, 0); intent.move(140, 300, 40, 0); intent.move(200, 300, 60, 0); (0, import_vitest.expect)(prefetched).toEqual(["/about"]); }); (0, import_vitest.it)("removes prefetched links from future consideration", function () { intent.setRects([{ r: rect(400, 300), h: "/first" }, { r: rect(600, 300), h: "/second" }]); intent.move(100, 300, 0, 0); intent.move(150, 300, 50, 0); (0, import_vitest.expect)(prefetched).toEqual(["/first"]); intent.move(250, 300, 100, 0); intent.move(350, 300, 100, 0); (0, import_vitest.expect)(prefetched).toEqual(["/first", "/second"]); }); }); (0, import_vitest.describe)("winner-takes-all with clustered links", function () { (0, import_vitest.it)("only prefetches the best target when multiple links are in path", function () { intent.setRects([{ r: rect(500, 280), h: "/top" }, { r: rect(500, 320), h: "/middle" }, { r: rect(500, 360), h: "/bottom" }]); intent.move(100, 340, 0, 0); intent.move(150, 340, 50, 0); (0, import_vitest.expect)(prefetched.length).toBe(1); (0, import_vitest.expect)(prefetched[0]).toBe("/middle"); }); (0, import_vitest.it)("handles dense nav with 20 links", function () { var links = Array.from({ length: 20 }, function (_, i) { return { r: rect(100 + i * 60, 50, 50, 30), h: `/nav-${i}` }; }); intent.setRects(links); intent.move(700, 200, 0, 0); intent.move(700, 150, 0, -50); intent.move(700, 100, 0, -50); (0, import_vitest.expect)(prefetched.length).toBe(1); (0, import_vitest.expect)(prefetched[0]).toBe("/nav-10"); }); (0, import_vitest.it)("picks closer link when two are roughly aligned", function () { intent.setRects([{ r: rect(300, 300), h: "/near" }, { r: rect(600, 300), h: "/far" }]); intent.move(100, 320, 0, 0); intent.move(150, 320, 50, 0); (0, import_vitest.expect)(prefetched).toEqual(["/near"]); }); (0, import_vitest.it)("picks better-aimed link over closer link", function () { intent.setRects([{ r: rect(200, 400), h: "/close-but-off" }, // closer but significantly off-axis { r: rect(400, 300), h: "/far-but-aimed" }]); intent.move(100, 300, 0, 0); intent.move(150, 300, 50, 0); (0, import_vitest.expect)(prefetched).toEqual(["/far-but-aimed"]); }); }); (0, import_vitest.describe)("velocity and smoothing", function () { (0, import_vitest.it)("does not prefetch when mouse is stationary", function () { intent.setRects([{ r: rect(500, 300), h: "/about" }]); intent.move(400, 300, 0, 0); intent.move(400, 300, 0, 0); intent.move(400, 300, 0, 0); (0, import_vitest.expect)(prefetched).toEqual([]); }); (0, import_vitest.it)("does not prefetch when mouse is moving slowly", function () { intent.setRects([{ r: rect(500, 300), h: "/about" }]); intent.move(400, 300, 0, 0); intent.move(401, 300, 1, 0); intent.move(402, 300, 1, 0); (0, import_vitest.expect)(prefetched).toEqual([]); }); (0, import_vitest.it)("smooths velocity to avoid jitter false positives", function () { intent.setRects([{ r: rect(500, 300), h: "/about" }]); intent.move(100, 300, 0, 0); intent.move(130, 305, 30, 5); intent.move(160, 298, 30, -7); intent.move(195, 303, 35, 5); (0, import_vitest.expect)(prefetched).toEqual(["/about"]); }); }); (0, import_vitest.describe)("diagonal movement", function () { (0, import_vitest.it)("prefetches with diagonal approach", function () { intent.setRects([{ r: rect(500, 500), h: "/corner" }]); intent.move(200, 200, 0, 0); intent.move(240, 240, 40, 40); intent.move(290, 290, 50, 50); (0, import_vitest.expect)(prefetched).toEqual(["/corner"]); }); (0, import_vitest.it)("handles angled approach to horizontal nav", function () { intent.setRects([{ r: rect(400, 50), h: "/link1" }, { r: rect(500, 50), h: "/link2" }, { r: rect(600, 50), h: "/link3" }]); intent.move(300, 300, 0, 0); intent.move(340, 260, 40, -40); intent.move(390, 210, 50, -50); (0, import_vitest.expect)(prefetched.length).toBe(1); }); }); (0, import_vitest.describe)("edge cases", function () { (0, import_vitest.it)("handles empty rect list", function () { intent.setRects([]); intent.move(100, 100, 0, 0); intent.move(150, 100, 50, 0); (0, import_vitest.expect)(prefetched).toEqual([]); }); (0, import_vitest.it)("handles link at cursor position", function () { intent.setRects([{ r: rect(100, 100), h: "/here" }]); intent.move(150, 120, 0, 0); intent.move(160, 120, 10, 0); (0, import_vitest.expect)(prefetched.length).toBeLessThanOrEqual(1); }); (0, import_vitest.it)("cleans up when observe returns cleanup function", function () { var cleanup = intent.observe({ getBoundingClientRect: function () { return rect(500, 300); } }, "/test"); cleanup(); intent.move(100, 300, 0, 0); intent.move(150, 300, 50, 0); (0, import_vitest.expect)(prefetched).toEqual([]); }); (0, import_vitest.it)("re-enables prefetch for href after cleanup", function () { var el = { getBoundingClientRect: function () { return rect(500, 300); } }; var cleanup = intent.observe(el, "/test"); intent.setRects([{ r: rect(500, 300), h: "/test" }]); intent.move(100, 300, 0, 0); intent.move(140, 300, 40, 0); intent.move(200, 300, 60, 0); (0, import_vitest.expect)(prefetched).toEqual(["/test"]); cleanup(); prefetched.length = 0; intent.observe(el, "/test"); intent.setRects([{ r: rect(500, 300), h: "/test" }]); intent.move(100, 300, 0, 0); intent.move(140, 300, 40, 0); intent.move(200, 300, 60, 0); (0, import_vitest.expect)(prefetched).toEqual(["/test"]); }); }); (0, import_vitest.describe)("reach configuration", function () { (0, import_vitest.it)("respects maxReach option", function () { var shortReach = (0, import_prefetchIntent.createPrefetchIntent)({ onPrefetch: function (href) { return prefetched.push(href); }, maxReach: 200 }); shortReach.setRects([{ r: rect(500, 300), h: "/far" }]); shortReach.move(100, 300, 0, 0); shortReach.move(150, 300, 50, 0); (0, import_vitest.expect)(prefetched).toEqual([]); }); (0, import_vitest.it)("respects perpWeight option for aim strictness", function () { var strictAim = (0, import_prefetchIntent.createPrefetchIntent)({ onPrefetch: function (href) { return prefetched.push(href); }, perpWeight: 10 }); strictAim.setRects([{ r: rect(400, 350), h: "/off" }]); strictAim.move(100, 300, 0, 0); strictAim.move(150, 300, 50, 0); (0, import_vitest.expect)(prefetched).toEqual([]); }); }); (0, import_vitest.describe)("memory and performance", function () { (0, import_vitest.it)("does not leak elements after cleanup", function () { var cleanups = []; for (var i = 0; i < 100; i++) { var el = {}; cleanups.push(intent.observe(el, `/page-${i}`)); } (0, import_vitest.expect)(intent.nodes.size).toBe(100); cleanups.forEach(function (c) { return c(); }); (0, import_vitest.expect)(intent.nodes.size).toBe(0); (0, import_vitest.expect)(intent.done.size).toBe(0); }); (0, import_vitest.it)("handles rapid observe/unobserve cycles", function () { var el = {}; for (var i = 0; i < 100; i++) { var cleanup = intent.observe(el, "/test"); cleanup(); } (0, import_vitest.expect)(intent.nodes.size).toBe(0); }); (0, import_vitest.it)("processes 100 links efficiently", function () { var links = []; for (var row = 0; row < 10; row++) { for (var col = 0; col < 10; col++) { links.push({ r: rect(100 + col * 80, 100 + row * 50, 60, 30), h: `/link-${row}-${col}` }); } } intent.setRects(links); var start = performance.now(); for (var i = 0; i < 100; i++) { intent.move(50 + i * 5, 300, 5, 0); } var elapsed = performance.now() - start; (0, import_vitest.expect)(elapsed).toBeLessThan(50); }); (0, import_vitest.it)("removes prefetched links from rects to speed up future checks", function () { var links = Array.from({ length: 10 }, function (_, i) { return { r: rect(200 + i * 100, 300), h: `/link-${i}` }; }); intent.setRects(links); intent.move(100, 320, 0, 0); intent.move(150, 320, 50, 0); (0, import_vitest.expect)(prefetched.length).toBe(1); intent.move(100, 320, -50, 0); intent.move(150, 320, 50, 0); intent.move(200, 320, 50, 0); (0, import_vitest.expect)(prefetched.length).toBe(2); (0, import_vitest.expect)(prefetched[0]).not.toBe(prefetched[1]); }); }); }); //# sourceMappingURL=prefetchIntent.test.native.js.map