import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { render } from "solid-js/web"; import { MetaProvider } from "@solidjs/meta"; import type { JSX } from "solid-js"; vi.mock("~/lib/api", () => ({ api: { correlation: { getStats: { query: vi.fn().mockResolvedValue({ threatScore: 25, totalAlerts: 5, bySeverity: {}, bySource: {}, activeGroups: 2, resolvedCount: 3, falsePositiveCount: 1, threatBreakdown: [] }) }, getAlerts: { query: vi.fn().mockResolvedValue({ items: [ { id: "1", title: "New credential leak detected", severity: "HIGH", source: "DARKWATCH", createdAt: new Date().toISOString() }, { id: "2", title: "Suspicious call", severity: "WARNING", source: "SPAMSHIELD", createdAt: new Date().toISOString() }, ], total: 2, page: 1, limit: 10, totalPages: 1 }) }, resolveAlert: { mutate: vi.fn().mockResolvedValue({}) }, }, darkwatch: { getExposures: { query: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 1, totalPages: 0 }) }, runScan: { mutate: vi.fn().mockResolvedValue({}) }, }, voiceprint: { getEnrollments: { query: vi.fn().mockResolvedValue([]) }, getAnalyses: { query: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 10, totalPages: 0 }) }, }, spamshield: { getStats: { query: vi.fn().mockResolvedValue({ period: "week", totalDetections: 10, spamCount: 8, notSpamCount: 2, accuracy: 80, activeRules: 3 }) }, getRules: { query: vi.fn().mockResolvedValue({ userRules: [], globalRules: [] }) }, }, hometitle: { getProperties: { query: vi.fn().mockResolvedValue([]) }, getAlerts: { query: vi.fn().mockResolvedValue([]) }, }, removebrokers: { getStats: { query: vi.fn().mockResolvedValue({ total: 0, byStatus: {}, totalListings: 0, listingsRemoved: 0, completionRate: 0 }) }, getBrokerRegistry: { query: vi.fn().mockResolvedValue([]) }, }, }, })); vi.mock("@solidjs/router", () => ({ A: (props: { href?: string; children?: JSX.Element; class?: string; onClick?: () => void }) => ( {props.children} ), useLocation: () => ({ pathname: "/dashboard" }), useParams: () => ({ slug: "ai-scam-trends-2026" }), useSearchParams: () => [new URLSearchParams(), vi.fn()], })); vi.mock("~/hooks", () => ({ useAuth: () => ({ user: () => ({ name: "Test User", email: "test@shieldai.app" }), isAuthenticated: () => true, isLoading: () => false, logout: vi.fn(), }), useSubscription: () => ({ subscription: () => ({ tier: "plus", status: "active" }), tier: () => "plus", isLoading: () => false, hasFeature: () => true, }), useNotifications: () => ({ alerts: () => [ { id: "1", title: "New credential leak detected", description: "Your email was found in a data breach", severity: "HIGH", createdAt: "5m ago" }, { id: "2", title: "VoicePrint scan completed", description: "No deepfake voice activity detected", severity: "INFO", createdAt: "1h ago" }, { id: "3", title: "RemoveBroker opt-out confirmed", description: "Your data has been removed from Whitepages", severity: "INFO", createdAt: "3h ago" }, { id: "4", title: "Suspicious call blocked", description: "SpamShield blocked a call", severity: "WARNING", createdAt: "6h ago" }, { id: "5", title: "HomeTitle alert", description: "A document was filed", severity: "CRITICAL", createdAt: "1d ago" }, ], unreadCount: () => 5, markRead: vi.fn(), isLoading: () => false, }), })); import BlogPage from "./blog"; import BlogPostPage from "./blog/[slug]"; import AdsPage from "./ads"; import DashboardPage from "./(webapp)/dashboard"; import StatCard from "~/components/dashboard/StatCard"; import ActivityFeed from "~/components/dashboard/ActivityFeed"; import QuickActions from "~/components/dashboard/QuickActions"; function mount(comp: () => JSX.Element): HTMLDivElement { const container = document.createElement("div"); document.body.appendChild(container); render(() => {comp()}, container); return container; } beforeEach(() => { document.body.innerHTML = ""; }); afterEach(() => { document.body.innerHTML = ""; }); describe("BlogPage (listing)", () => { it("renders hero section with blog headline", () => { mount(() => ); expect(document.body.textContent).toContain("ShieldAI Blog"); }); it("renders all 6 blog post cards", () => { mount(() => ); const cards = document.querySelectorAll(".gradient-card"); expect(cards.length).toBeGreaterThanOrEqual(4); }); it("renders tag filter buttons", () => { mount(() => ); expect(document.body.textContent).toContain("All"); expect(document.body.textContent).toContain("AI Safety"); expect(document.body.textContent).toContain("Privacy"); expect(document.body.textContent).toContain("Deepfakes"); }); it("renders Load More button when there are more posts to show", () => { mount(() => ); expect(document.body.textContent).toContain("Load More Posts"); }); it("renders post titles and excerpts", () => { mount(() => ); expect(document.body.textContent).toContain("AI Scam Trends to Watch in 2026"); expect(document.body.textContent).toContain("Sarah Chen"); expect(document.body.textContent).toContain("Mike Reynolds"); }); }); describe("BlogPostPage ([slug])", () => { it("renders post content for valid slug", () => { mount(() => ); expect(document.body.textContent).toContain("AI Scam Trends to Watch in 2026"); expect(document.body.textContent).toContain("Sarah Chen"); expect(document.body.textContent).toContain("Security Researcher"); expect(document.body.textContent).toContain("May 15, 2026"); expect(document.body.textContent).toContain("5 min read"); }); it("renders markdown content as HTML", () => { mount(() => ); expect(document.body.textContent).toContain("The Rise of AI-Powered Scams"); expect(document.body.textContent).toContain("Voice Cloning Scams"); expect(document.body.textContent).toContain("How to Protect Yourself"); }); it("renders social share buttons", () => { mount(() => ); const shareBtns = document.querySelectorAll("button[aria-label]"); const shareLabels = Array.from(shareBtns).map(b => b.getAttribute("aria-label")); expect(shareLabels).toContain("Share on Twitter"); expect(shareLabels).toContain("Share on LinkedIn"); expect(shareLabels).toContain("Copy link"); }); it("renders related posts section", () => { mount(() => ); expect(document.body.textContent).toContain("Related Posts"); }); it("renders author card in sidebar", () => { mount(() => ); expect(document.body.textContent).toContain("Security Researcher"); }); it("renders back to blog link", () => { mount(() => ); expect(document.body.textContent).toContain("Back to Blog"); }); }); describe("AdsPage", () => { it("renders conversion-focused headline", () => { mount(() => ); expect(document.body.textContent).toContain("Stop AI Scams Before"); expect(document.body.textContent).toContain("They Reach You"); }); it("renders pricing section with 3 plans", () => { mount(() => ); expect(document.body.textContent).toContain("Basic"); expect(document.body.textContent).toContain("Plus"); expect(document.body.textContent).toContain("Premium"); expect(document.body.textContent).toContain("$9"); expect(document.body.textContent).toContain("$19"); expect(document.body.textContent).toContain("$39"); }); it("marks Plus plan as Most Popular", () => { mount(() => ); const badges = document.body.querySelectorAll("span"); const popularBadge = Array.from(badges).find(b => b.textContent === "Most Popular"); expect(popularBadge).toBeTruthy(); }); it("renders FAQ section with toggle functionality", () => { mount(() => ); expect(document.body.textContent).toContain("Frequently Asked Questions"); expect(document.body.textContent).toContain("How does ShieldAI detect voice clones?"); expect(document.body.textContent).toContain("Is my data encrypted?"); }); it("renders trust badges", () => { mount(() => ); expect(document.body.textContent).toContain("14-day free trial"); expect(document.body.textContent).toContain("No credit card required"); expect(document.body.textContent).toContain("Cancel anytime"); }); it("renders trust metrics section", () => { mount(() => ); expect(document.body.textContent).toContain("99.7%"); expect(document.body.textContent).toContain("200+"); expect(document.body.textContent).toContain("50K+"); }); it("renders testimonials", () => { mount(() => ); expect(document.body.textContent).toContain("Trusted by Thousands"); }); it("renders CTA section with Get Started Free button", () => { mount(() => ); expect(document.body.textContent).toContain("Ready to protect your identity?"); expect(document.body.textContent).toContain("Get Started Free"); }); }); describe("DashboardPage", () => { it("renders dashboard title", () => { mount(() => ); expect(document.body.textContent).toContain("Dashboard"); }); it("renders sidebar with navigation links", () => { mount(() => ); expect(document.body.textContent).toContain("Overview"); expect(document.body.textContent).toContain("DarkWatch"); expect(document.body.textContent).toContain("VoicePrint"); expect(document.body.textContent).toContain("SpamShield"); expect(document.body.textContent).toContain("HomeTitle"); expect(document.body.textContent).toContain("RemoveBrokers"); expect(document.body.textContent).toContain("Settings"); }); it("renders widget headers", async () => { mount(() => ); await new Promise((r) => setTimeout(r, 0)); expect(document.body.textContent).toContain("Threat Score"); expect(document.body.textContent).toContain("Alert Feed"); expect(document.body.textContent).toContain("Quick Actions"); }); it("renders QuickActionsWidget with action buttons", () => { mount(() => ); expect(document.body.textContent).toContain("Quick Actions"); expect(document.body.textContent).toContain("Add to Watchlist"); expect(document.body.textContent).toContain("Upload Voice Sample"); expect(document.body.textContent).toContain("Check Number"); expect(document.body.textContent).toContain("Add Property"); expect(document.body.textContent).toContain("Start Removal"); }); }); describe("StatCard", () => { it("renders label and value", () => { mount(() => ( } /> )); expect(document.body.textContent).toContain("Test Metric"); expect(document.body.textContent).toContain("42"); }); it("renders up trend indicator", () => { mount(() => ( } /> )); expect(document.body.textContent).toContain("+5%"); }); it("renders down trend indicator", () => { mount(() => ( } /> )); expect(document.body.textContent).toContain("-3%"); }); }); describe("ActivityFeed", () => { it("renders activities", () => { const activities = [ { id: "1", title: "Test Alert", description: "Test description", timestamp: "5m ago", type: "alert" as const }, ]; mount(() => ); expect(document.body.textContent).toContain("Recent Activity"); expect(document.body.textContent).toContain("Test Alert"); expect(document.body.textContent).toContain("Test description"); expect(document.body.textContent).toContain("5m ago"); }); }); describe("QuickActions", () => { it("renders action buttons", () => { const actions = [ { label: "Action 1", href: "/test", icon: () => }, { label: "Action 2", href: "/test2", icon: () => }, ]; mount(() => ); expect(document.body.textContent).toContain("Quick Actions"); expect(document.body.textContent).toContain("Action 1"); expect(document.body.textContent).toContain("Action 2"); }); });