import { describe, test, expect } from "bun:test"; import { isLikelyMobile, shouldWarnBeforeLoad } from "../src/lib/mobileMemoryGuard"; // Pure UA/heuristic logic (D-027) — no browser, no navigator. const ANDROID_UA = "Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Mobile Safari/537.36"; const IPHONE_UA = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1"; const IPAD_DESKTOP_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15"; const DESKTOP_MAC_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"; const DESKTOP_WINDOWS_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"; describe("isLikelyMobile", () => { test("detects Android and iPhone user agents", () => { expect(isLikelyMobile({ userAgent: ANDROID_UA, maxTouchPoints: 5 })).toBe(true); expect(isLikelyMobile({ userAgent: IPHONE_UA, maxTouchPoints: 5 })).toBe(true); }); test("detects iPadOS's desktop-Safari UA via touch points", () => { expect(isLikelyMobile({ userAgent: IPAD_DESKTOP_UA, maxTouchPoints: 5 })).toBe(true); // Same UA, no touch support reported — treat as a real desktop Mac. expect(isLikelyMobile({ userAgent: IPAD_DESKTOP_UA, maxTouchPoints: 0 })).toBe(false); expect(isLikelyMobile({ userAgent: IPAD_DESKTOP_UA, maxTouchPoints: undefined })).toBe( false, ); }); test("does not flag real desktop browsers", () => { expect(isLikelyMobile({ userAgent: DESKTOP_MAC_UA, maxTouchPoints: 0 })).toBe(false); expect(isLikelyMobile({ userAgent: DESKTOP_WINDOWS_UA, maxTouchPoints: 0 })).toBe(false); }); test("undefined userAgent (SSR/tests) is never mobile", () => { expect(isLikelyMobile({ userAgent: undefined, maxTouchPoints: 5 })).toBe(false); }); }); describe("shouldWarnBeforeLoad", () => { const MEDIUM_PEAK_BYTES = 555_000_000; // ~medium q4's estimated peak test("never warns on desktop regardless of size or reported memory", () => { expect( shouldWarnBeforeLoad( { userAgent: DESKTOP_WINDOWS_UA, maxTouchPoints: 0, deviceMemoryGB: 0.5 }, MEDIUM_PEAK_BYTES, ), ).toBe(false); }); test("warns on mobile with low reported deviceMemory", () => { // Safe budget = 1 GB * 0.5 = 500 MB, below the ~555 MB medium peak. expect( shouldWarnBeforeLoad( { userAgent: ANDROID_UA, maxTouchPoints: 5, deviceMemoryGB: 1 }, MEDIUM_PEAK_BYTES, ), ).toBe(true); }); test("does not warn on mobile with ample reported deviceMemory", () => { expect( shouldWarnBeforeLoad( { userAgent: ANDROID_UA, maxTouchPoints: 5, deviceMemoryGB: 8 }, MEDIUM_PEAK_BYTES, ), ).toBe(false); }); // D-029: deviceMemoryGB 2-4 is the ordinary (not just budget) Android // range today — these must still warn for Medium+, the exact class of // phone the original D-027 crash report was about. test("warns on mobile mid-range devices (deviceMemory 2-4) for Medium+", () => { for (const deviceMemoryGB of [2, 4]) { expect( shouldWarnBeforeLoad( { userAgent: ANDROID_UA, maxTouchPoints: 5, deviceMemoryGB }, MEDIUM_PEAK_BYTES, ), ).toBe(true); } }); test("falls back to a flat threshold when deviceMemory is unreported (iOS)", () => { expect( shouldWarnBeforeLoad( { userAgent: IPHONE_UA, maxTouchPoints: 5, deviceMemoryGB: undefined }, MEDIUM_PEAK_BYTES, ), ).toBe(true); expect( shouldWarnBeforeLoad( { userAgent: IPHONE_UA, maxTouchPoints: 5, deviceMemoryGB: undefined }, 50_000_000, // tiny model — well under the fallback threshold ), ).toBe(false); }); });