const { isPhishingDomain, loadConfig, getBlocklistSize, hostnameVariants, _reset, } = require("../src/shared/phishingDomains"); // Reset state before each test to avoid cross-test contamination. beforeEach(() => { _reset(); }); describe("phishingDomains", () => { describe("hostnameVariants", () => { test("returns exact hostname plus parent domains", () => { const variants = hostnameVariants("sub.evil.com"); expect(variants).toEqual(["sub.evil.com", "evil.com"]); }); test("returns just the hostname for a bare domain", () => { const variants = hostnameVariants("example.com"); expect(variants).toEqual(["example.com"]); }); test("handles deep subdomain chains", () => { const variants = hostnameVariants("a.b.c.d.com"); expect(variants).toEqual([ "a.b.c.d.com", "b.c.d.com", "c.d.com", "d.com", ]); }); test("lowercases hostnames", () => { const variants = hostnameVariants("Evil.COM"); expect(variants).toEqual(["evil.com"]); }); }); describe("loadConfig + isPhishingDomain", () => { test("detects exact blacklisted domain", () => { loadConfig({ blacklist: ["evil-phishing.com", "scam-swap.xyz"], whitelist: [], }); expect(isPhishingDomain("evil-phishing.com")).toBe(true); expect(isPhishingDomain("scam-swap.xyz")).toBe(true); }); test("returns false for clean domains", () => { loadConfig({ blacklist: ["evil-phishing.com"], whitelist: [], }); expect(isPhishingDomain("etherscan.io")).toBe(false); expect(isPhishingDomain("uniswap.org")).toBe(false); }); test("detects subdomain of blacklisted domain", () => { loadConfig({ blacklist: ["evil-phishing.com"], whitelist: [], }); expect(isPhishingDomain("app.evil-phishing.com")).toBe(true); expect(isPhishingDomain("sub.app.evil-phishing.com")).toBe(true); }); test("whitelist overrides blacklist", () => { loadConfig({ blacklist: ["metamask.io"], whitelist: ["metamask.io"], }); expect(isPhishingDomain("metamask.io")).toBe(false); }); test("whitelist on parent domain overrides blacklist", () => { loadConfig({ blacklist: ["sub.legit.com"], whitelist: ["legit.com"], }); expect(isPhishingDomain("sub.legit.com")).toBe(false); }); test("case-insensitive matching", () => { loadConfig({ blacklist: ["Evil-Phishing.COM"], whitelist: [], }); expect(isPhishingDomain("evil-phishing.com")).toBe(true); expect(isPhishingDomain("EVIL-PHISHING.COM")).toBe(true); }); test("returns false for empty/null hostname", () => { loadConfig({ blacklist: ["evil.com"], whitelist: [], }); expect(isPhishingDomain("")).toBe(false); expect(isPhishingDomain(null)).toBe(false); }); test("getBlocklistSize reflects loaded config", () => { loadConfig({ blacklist: ["a.com", "b.com", "c.com"], whitelist: ["d.com"], }); expect(getBlocklistSize()).toBe(3); }); test("handles config with no blacklist/whitelist keys", () => { loadConfig({}); expect(isPhishingDomain("anything.com")).toBe(false); expect(getBlocklistSize()).toBe(0); }); test("re-loading config replaces previous data", () => { loadConfig({ blacklist: ["old-scam.com"], whitelist: [], }); expect(isPhishingDomain("old-scam.com")).toBe(true); loadConfig({ blacklist: ["new-scam.com"], whitelist: [], }); expect(isPhishingDomain("old-scam.com")).toBe(false); expect(isPhishingDomain("new-scam.com")).toBe(true); }); }); describe("real-world MetaMask blocklist patterns", () => { test("detects known phishing domains from MetaMask list", () => { loadConfig({ blacklist: [ "uniswap-trade.web.app", "hopprotocol.pro", "blast-pools.pages.dev", ], whitelist: [], }); expect(isPhishingDomain("uniswap-trade.web.app")).toBe(true); expect(isPhishingDomain("hopprotocol.pro")).toBe(true); expect(isPhishingDomain("blast-pools.pages.dev")).toBe(true); }); test("does not flag legitimate domains whitelisted by MetaMask", () => { loadConfig({ blacklist: ["opensea.pro"], whitelist: [ "opensea.io", "metamask.io", "etherscan.io", "opensea.pro", ], }); expect(isPhishingDomain("opensea.io")).toBe(false); expect(isPhishingDomain("metamask.io")).toBe(false); expect(isPhishingDomain("etherscan.io")).toBe(false); // opensea.pro is both blacklisted and whitelisted — whitelist wins expect(isPhishingDomain("opensea.pro")).toBe(false); }); }); });