bstein-dev-home/testing/frontend/unit/components.spec.js

121 lines
4.0 KiB
JavaScript

import { RouterLinkStub, shallowMount } from "../../../frontend/node_modules/@vue/test-utils/dist/vue-test-utils.esm-bundler.mjs";
import { describe, expect, it } from "../../../frontend/node_modules/vitest/dist/index.js";
import MetricRow from "../../../frontend/src/components/MetricRow.vue";
import ServiceGrid from "../../../frontend/src/components/ServiceGrid.vue";
import StatsGrid from "../../../frontend/src/components/StatsGrid.vue";
import { fallbackHardware } from "../../../frontend/src/data/sample.js";
describe("shared dashboard components", () => {
it("renders metric cards", () => {
const wrapper = shallowMount(MetricRow, {
props: {
items: [
{ label: "Nodes", value: "26", note: "atlas + oceanus" },
{ label: "Storage", value: "80 TB", note: "Longhorn" },
],
},
});
expect(wrapper.text()).toContain("Nodes");
expect(wrapper.text()).toContain("26");
expect(wrapper.text()).toContain("Longhorn");
});
it("summarizes node state in the stats grid", () => {
const wrapper = shallowMount(StatsGrid, {
props: { hardware: fallbackHardware() },
});
expect(wrapper.text()).toContain("Control plane");
expect(wrapper.text()).toContain("3");
expect(wrapper.text()).toContain("offline");
expect(wrapper.text()).toContain("titan-16");
});
it("hides the attention card when every worker is healthy", () => {
const wrapper = shallowMount(StatsGrid, {
props: {
hardware: {
clusters: [
{
name: "atlas",
nodes: [{ name: "titan-0a", role: "control-plane", status: "ready" }],
},
],
specialty: [],
},
},
});
expect(wrapper.text()).not.toContain("Attention");
});
it("distinguishes internal and external service links", () => {
const wrapper = shallowMount(ServiceGrid, {
global: {
stubs: {
RouterLink: RouterLinkStub,
},
},
props: {
services: [
{ name: "Atlas AI", category: "ai", summary: "Chat", link: "/ai/chat", icon: "🤖" },
{ name: "Nextcloud", category: "productivity", summary: "Files", link: "https://cloud.example.dev", icon: "☁️" },
{ name: "Bad Link", category: "broken", summary: "invalid", link: "not a url", icon: "❓" },
],
},
});
expect(wrapper.text()).toContain("Atlas AI");
expect(wrapper.text()).toContain("cloud.example.dev");
expect(wrapper.text()).toContain("not a url");
expect(wrapper.findComponent(RouterLinkStub).exists()).toBe(true);
});
it("falls back to default service rendering when data is sparse", () => {
const wrapper = shallowMount(ServiceGrid, {
global: {
stubs: {
RouterLink: RouterLinkStub,
},
},
props: {
services: [
{ name: "Muted Service", category: "dev", summary: "planned", link: "", status: "planned" },
{ name: "Plain Service", category: "dev", summary: "fallback icon", link: "/apps" },
],
},
});
expect(wrapper.text()).toContain("Muted Service");
expect(wrapper.text()).toContain("fallback icon");
expect(wrapper.findAll(".service").length).toBe(2);
expect(wrapper.findComponent(RouterLinkStub).exists()).toBe(true);
});
it("renders empty and partial hardware states safely", () => {
const wrapper = shallowMount(StatsGrid, {
props: {
hardware: {
clusters: [{ name: "atlas", nodes: [{ name: "solo", role: "worker", status: "ready" }] }],
specialty: [{ name: "standalone", role: "Spare node", status: "ready" }],
},
},
});
expect(wrapper.text()).toContain("1 nodes total");
expect(wrapper.text()).toContain("0");
expect(wrapper.text()).toContain("standalone");
});
it("falls back cleanly when no hardware prop is provided", () => {
const wrapper = shallowMount(StatsGrid, {
props: {},
});
expect(wrapper.text()).toContain("0 nodes total");
expect(wrapper.text()).not.toContain("Attention");
});
});