import { afterEach, expect, test } from "bun:test"; import { MobileUnavailableError, PushNotifications, SecureStorage, invoke, isNative, platform, plugin, registerPlugin, whenNative, } from "../src/index.ts"; const root = globalThis as typeof globalThis & { Capacitor?: unknown }; const original = root.Capacitor; afterEach(() => { if (original === undefined) delete root.Capacitor; else root.Capacitor = original; }); test("falls back safely without Capacitor", async () => { delete root.Capacitor; expect(isNative()).toBe(false); expect(platform()).toBe("web"); expect(plugin("Camera")).toBeUndefined(); expect( await whenNative( () => "native", () => "browser", ), ).toBe("browser"); }); test("exposes and invokes injected plugins", async () => { root.Capacitor = { isNativePlatform: () => true, getPlatform: () => "android", Plugins: { Haptics: { impact: async (options: unknown) => ({ options, completed: true }) } }, }; expect(isNative()).toBe(true); expect(platform()).toBe("android"); expect(plugin("Haptics")).toBeDefined(); expect( await invoke<{ options: { style: string }; completed: boolean }>("Haptics", "impact", { style: "MEDIUM", }), ).toEqual({ options: { style: "MEDIUM" }, completed: true, }); }); test("registered JavaScript plugin proxies take precedence", async () => { root.Capacitor = { isNativePlatform: () => true, Plugins: {} }; registerPlugin("Device", { getInfo: async () => ({ model: "test" }) }); expect(await invoke<{ model: string }>("Device", "getInfo")).toEqual({ model: "test" }); }); test("explains missing plugins", async () => { root.Capacitor = { isNativePlatform: () => true, Plugins: {} }; expect(invoke("Camera", "getPhoto")).rejects.toBeInstanceOf(MobileUnavailableError); }); test("normalizes push permission and rejects empty registrations", async () => { const push = new PushNotifications({ permission: async () => "prompt", requestPermission: async () => "granted", register: async () => ({ token: "device-token", platform: "ios" }), }); expect(await push.register()).toEqual({ token: "device-token", platform: "ios" }); }); test("namespaces and validates secure-storage keys", async () => { const values = new Map(); const storage = new SecureStorage({ get: async (key) => values.get(key) ?? null, set: async (key, value) => void values.set(key, value), remove: async (key) => void values.delete(key), }); await storage.set("session", "encrypted-value"); expect(values.get("wrnexus:session")).toBe("encrypted-value"); expect(() => storage.get("bad key")).toThrow(TypeError); });