import { afterEach, beforeEach, describe, expect, it, jest } from "@jest/globals"; import { RouterLinkStub, flushPromises, shallowMount } from "@vue/test-utils"; import PlatformSection from "../../../frontend/src/components/PlatformSection.vue"; import { auth } from "../../../frontend/src/auth.js"; import HomeView from "../../../frontend/src/views/HomeView.vue"; function resetAuth() { auth.ready = true; auth.enabled = true; auth.authenticated = false; auth.username = ""; auth.email = ""; auth.emailVerified = null; auth.groups = []; auth.resetUrl = "https://sso.example.dev/reset"; } describe("HomeView", () => { beforeEach(() => { global.fetch = jest.fn(async (resource) => { const url = typeof resource === "string" ? resource : resource?.url || ""; if (url.includes("/api/account/member-state")) { return new Response( JSON.stringify({ status: "ready", onboarding_url: "/onboarding?code=ada~CODE", dashboard_url: "/apps", account_url: "/account", }), { status: 200, headers: { "content-type": "application/json" } }, ); } return new Response("{}", { status: 200, headers: { "content-type": "application/json" } }); }); }); afterEach(() => { resetAuth(); jest.restoreAllMocks(); }); it("renders the professional homepage while logged out", () => { resetAuth(); const wrapper = shallowMount(HomeView, { global: { stubs: { RouterLink: RouterLinkStub, PlatformSection: true, }, }, props: { labStatus: { connected: true, atlas: { up: true, known: true }, active_service: { known: true, label: "Nextcloud", url: "https://cloud.example.dev", window: "15m" }, dedicated_hosts: { known: true, up: true, up_count: 2, total: 2, hosts: [ { label: "Database node", known: true, up: true }, { label: "Jumphost", known: true, up: true }, ], }, checked_at: 1000, }, loading: false, error: "", }, }); expect(wrapper.text()).toContain("Brad Stein"); expect(wrapper.text()).toContain("DevOps Automation Engineer / Senior SDET"); expect(wrapper.text()).toContain("Discuss a Project"); expect(wrapper.text()).toContain("View Résumé"); expect(wrapper.text()).toContain("Explore the Live Platform"); expect(wrapper.text()).toContain("From 0 to 100"); expect(wrapper.text()).toContain("Platform Showcase"); expect(wrapper.text()).toContain("Atlas operator tools"); expect(wrapper.text()).toContain("Veles"); expect(wrapper.text()).not.toContain("TaskWatcher"); expect(wrapper.text()).toContain("family, friends, and the lucky few"); expect(wrapper.text()).toContain("Register"); expect(wrapper.text()).toContain("Request Lab Access"); expect(wrapper.find("[aria-label='Keycloak: Use one account to sign in across bstein.dev.']").exists()).toBe(true); expect(wrapper.find("[title='Nextcloud: Keep files, photos, office docs, and personal cloud data in sync.']").exists()).toBe(true); expect(wrapper.find("a[href='https://bstein.dev/ai/chat']").exists()).toBe(true); expect(wrapper.find("a[href='https://bstein.dev/monero']").exists()).toBe(true); expect(wrapper.find("a[href='https://chat.ai.bstein.dev']").exists()).toBe(false); expect(wrapper.find("a[href='https://monero.bstein.dev:443']").exists()).toBe(false); expect(wrapper.find("a[href='/ai/chat']").exists()).toBe(false); expect(wrapper.find("a[href='/monero']").exists()).toBe(false); expect(wrapper.text()).not.toContain("Existing registration, verification, onboarding"); expect(wrapper.text()).not.toContain("Looking for hosted services or an existing Titan Lab account"); expect(wrapper.find("a[href^='mailto:brad@bstein.dev']").exists()).toBe(true); expect(wrapper.findComponent(PlatformSection).exists()).toBe(true); expect(wrapper.text()).toContain("Atlas platform"); expect(wrapper.text()).toContain("Most active service"); expect(wrapper.text()).toContain("Nextcloud"); expect(wrapper.text()).toContain("Dedicated hosts"); expect(wrapper.text()).toContain("2 of 2 responding"); expect(wrapper.text()).toContain("Responding"); }); it("shows a calm fallback when public status is unavailable", () => { resetAuth(); const wrapper = shallowMount(HomeView, { global: { stubs: { RouterLink: RouterLinkStub, PlatformSection: true, }, }, props: { labStatus: null, loading: false, error: "Live data unavailable", }, }); expect(wrapper.text()).toContain("Live status is temporarily unavailable"); expect(wrapper.text()).not.toContain("status 500"); }); it("shows authenticated member actions without exposing service secrets", async () => { resetAuth(); auth.authenticated = true; auth.username = "ada"; auth.email = "ada@example.dev"; const wrapper = shallowMount(HomeView, { global: { stubs: { RouterLink: RouterLinkStub, PlatformSection: true, }, }, props: { labStatus: { connected: true, atlas: { up: true, known: true } }, loading: false, error: "", }, }); await flushPromises(); expect(wrapper.text()).toContain("Open Services"); expect(wrapper.text()).toContain("Account"); expect(wrapper.text()).not.toContain("app_password"); expect(wrapper.text()).not.toContain("mailu_app_password"); }); }); describe("PlatformSection", () => { it("preserves platform service, status, metric, and diagram behavior", () => { const wrapper = shallowMount(PlatformSection, { global: { stubs: { MetricRow: true, ServiceGrid: true, MermaidCard: true, }, }, props: { labStatus: { connected: true, atlas: { up: true, known: true }, dedicated_hosts: { known: true, up: false, up_count: 1, total: 2, hosts: [ { label: "Database node", known: true, up: true }, { label: "Jumphost", known: true, up: false }, ], }, }, serviceData: { services: [ { name: "Nextcloud", summary: "Storage", link: "https://cloud.example.dev" }, { name: "Monero", summary: "Node", link: "/monero", host: "monerod.crypto.svc.cluster.local:18081" }, { name: "Mystery", summary: "Default", link: "https://default.example.dev" }, ], }, loading: true, error: "", }, }); expect(wrapper.vm.atlasPillClass).toBe("pill-ok"); expect(wrapper.vm.dedicatedHostsPillClass).toBe("pill-bad"); expect(wrapper.vm.dedicatedHostsLabel).toBe("1/2 responding"); expect(wrapper.vm.dedicatedHostItems.map((host) => host.value)).toEqual(["Responding", "Needs attention"]); expect(wrapper.get(".status").text()).toBe("Loading..."); expect(wrapper.vm.displayServices.map((service) => service.icon)).toEqual(["NC", "XM", "TL"]); expect(wrapper.vm.displayServices.find((service) => service.name === "Monero").host).toBe("/monero"); expect(wrapper.vm.hardwareDiagram).toContain("Titan Lab"); expect(wrapper.vm.hardwareDiagram).toContain("Dedicated non-cluster hosts"); expect(wrapper.vm.networkDiagram).toContain("oauth2-proxy"); expect(wrapper.vm.pipelineDiagram).toContain("Flux"); expect(wrapper.text()).toContain("IaC source"); expect(wrapper.text()).toContain("Titan Lab: Live Platform"); }); it("shows public status errors without raw API detail", () => { const wrapper = shallowMount(PlatformSection, { global: { stubs: { MetricRow: true, ServiceGrid: true, MermaidCard: true, }, }, props: { labStatus: { connected: false, atlas: { up: false, known: false } }, serviceData: { services: [] }, metricsData: { items: [{ label: "Custom", value: "1", note: "" }] }, loading: false, error: "Live data unavailable", }, }); expect(wrapper.vm.atlasPillClass).toBe("pill-bad"); expect(wrapper.get(".status").text()).toBe("Live data unavailable"); expect(wrapper.vm.metricItems[0].note).toBe(""); expect(wrapper.text()).toContain("The platform overview remains available below"); }); });