- Introduced live smoke tests for Edge Gateways, verifying gateway routes and destructive-action prevention. - Added e2e scenarios for deep-link navigation, unavailable gateway recovery, token rotation, and background page refresh. - Refactored test helpers for streamlined functional validation in gateway scenarios. - Updated `EdgeGatewayTerminal.vue` with test IDs for enhanced testability. - Added and configured Husky pre-commit hooks for automated test file formatting and validation.
117 lines
6.7 KiB
JavaScript
117 lines
6.7 KiB
JavaScript
import { readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const workspaceSource = readFileSync(
|
|
join(process.cwd(), "src/components/displays/edgeGateway/EdgeGatewayWorkspace.vue"),
|
|
"utf8"
|
|
);
|
|
const routerSource = readFileSync(join(process.cwd(), "src/router.js"), "utf8");
|
|
const navSource = readFileSync(
|
|
join(process.cwd(), "src/views/dashboards/superUserDashboard/department/SuperUserDashboardDepartmentNavigation.vue"),
|
|
"utf8"
|
|
);
|
|
const edgeGatewaysViewSource = readFileSync(
|
|
join(process.cwd(), "src/views/dashboards/superUserDashboard/EdgeGateways.vue"),
|
|
"utf8"
|
|
);
|
|
const departmentGatewaysViewSource = readFileSync(
|
|
join(process.cwd(), "src/views/dashboards/superUserDashboard/department/DepartmentGateways.vue"),
|
|
"utf8"
|
|
);
|
|
|
|
describe("edge gateway workspace contract", () => {
|
|
it("renders the redesigned workflow sections and delegates root shell UI to the terminal component", () => {
|
|
expect(workspaceSource).toContain("Valgt gateway");
|
|
expect(workspaceSource).toContain("Overblik");
|
|
expect(workspaceSource).toContain("Installation");
|
|
expect(workspaceSource).toContain("Shelly-enheder");
|
|
expect(workspaceSource).toContain("Bindinger");
|
|
expect(workspaceSource).toContain("Opdateringer");
|
|
expect(workspaceSource).toContain("Historik");
|
|
expect(workspaceSource).toContain('import EdgeGatewayTerminal from "./EdgeGatewayTerminal.vue";');
|
|
expect(workspaceSource).toContain("<EdgeGatewayTerminal");
|
|
expect(workspaceSource).toContain('@session-approved="handleShellSessionApproved"');
|
|
});
|
|
|
|
it("renders queued discovery/update flows and the API polling control channel", () => {
|
|
expect(workspaceSource).toContain("Generér installer");
|
|
expect(workspaceSource).toContain('aria-label="Installer afdeling"');
|
|
expect(workspaceSource).toContain("Kør discovery");
|
|
expect(workspaceSource).toContain("Styringskanal");
|
|
expect(workspaceSource).toContain("Latens");
|
|
expect(workspaceSource).toContain("CPU");
|
|
expect(workspaceSource).toContain("RAM");
|
|
expect(workspaceSource).toContain("Disk");
|
|
expect(workspaceSource).toContain("getControlChannelMeta");
|
|
expect(workspaceSource).toContain("buildGatewayMetricView");
|
|
expect(workspaceSource).toContain("system_metrics");
|
|
expect(workspaceSource).toContain("startGatewayRefreshLoop");
|
|
expect(workspaceSource).toContain("stopGatewayRefreshLoop");
|
|
expect(workspaceSource).toContain("BACKGROUND_GATEWAY_REFRESH_INTERVAL_MS = 5_000");
|
|
expect(workspaceSource).toContain("startBackgroundGatewayRefreshLoop");
|
|
expect(workspaceSource).toContain("refreshWorkspaceDataInBackground");
|
|
expect(workspaceSource).toContain("Discovery er køet");
|
|
expect(workspaceSource).toContain("Opdatering er køet.");
|
|
expect(workspaceSource).toContain("resolveEdgeGatewayErrorMessage");
|
|
expect(workspaceSource).toContain("normalizeDisplayText");
|
|
expect(workspaceSource).toContain("decodeMojibakeText");
|
|
expect(workspaceSource).toContain(
|
|
"const displayErrorMessage = computed(() => decodeMojibakeText(normalizeDisplayText(errorMessage.value)));"
|
|
);
|
|
expect(workspaceSource).toContain("{{ displayErrorMessage }}");
|
|
expect(workspaceSource).toContain("Gateway-agenten er offline og kan ikke hente nye kommandoer lige nu.");
|
|
expect(workspaceSource).toContain("Gatewayen henter kommandoer og shell-events via API'et.");
|
|
expect(workspaceSource).toContain("Gem bindinger");
|
|
expect(workspaceSource).toContain("Planlæg opdatering");
|
|
expect(workspaceSource).toContain("Verificerer genstart");
|
|
expect(workspaceSource).toContain("Rullet tilbage");
|
|
expect(workspaceSource).toContain("Transporttilstand");
|
|
expect(workspaceSource).toContain("Break-glass adgang");
|
|
expect(workspaceSource).toContain("Gateway transport");
|
|
expect(workspaceSource).toContain("Afdelingens cutover");
|
|
expect(workspaceSource).toContain('data-testid="gateway-detail-header"');
|
|
expect(workspaceSource).toContain('data-testid="gateway-fleet-rail"');
|
|
expect(workspaceSource).toContain('data-testid="gateway-update-timeline"');
|
|
expect(workspaceSource).toContain('data-testid="gateway-rotation-confirmation"');
|
|
expect(workspaceSource).toContain('data-testid="gateway-rotation-result"');
|
|
expect(workspaceSource).toContain('data-testid="gateway-open-full-page"');
|
|
expect(workspaceSource).toContain("align-self: start;");
|
|
expect(workspaceSource).toContain(".edge-form-grid--installer");
|
|
});
|
|
|
|
it("builds richer binding device options and keeps stale selections editable", () => {
|
|
expect(workspaceSource).toContain("const inventoryDeviceOptions = computed(() =>");
|
|
expect(workspaceSource).toContain("const buildInventoryOptionLabel =");
|
|
expect(workspaceSource).toContain("const getBindingInventoryDevice = (binding) =>");
|
|
expect(workspaceSource).toContain("const getBindingDeviceOptions = (binding) =>");
|
|
expect(workspaceSource).toContain("Mangler i discovery");
|
|
expect(workspaceSource).toContain("{{ bindingHelperText }}");
|
|
expect(workspaceSource).toContain("{{ emptyBindingStateDescription }}");
|
|
expect(workspaceSource).toContain('binding.local_ip = device.local_ip ?? "";');
|
|
expect(workspaceSource).toContain("binding.channel = channelOptions[0];");
|
|
});
|
|
|
|
it("registers fleet, canonical detail, and department gateway routes in the router and navigation", () => {
|
|
expect(routerSource).toContain("path: '/superuser/gateways'");
|
|
expect(routerSource).toContain("name: 'edgegatewaydetail'");
|
|
expect(routerSource).toContain("path: '/superuser/gateways/:id'");
|
|
expect(routerSource).toContain("path: '/superuser/departments/:departmentId/gateways'");
|
|
expect(navSource).toContain("'/superuser/departments/' + departmentId.value + '/gateways'");
|
|
});
|
|
|
|
it("keeps route selection in the page layer and lets the department page deep-link into the canonical detail page", () => {
|
|
expect(workspaceSource).toContain("selectedGatewayId: {");
|
|
expect(workspaceSource).toContain('defineEmits(["open-gateway-page", "select-gateway"])');
|
|
expect(workspaceSource).toContain(
|
|
"const routeSelectedGatewayId = computed(() => normalizeGatewayId(props.selectedGatewayId));"
|
|
);
|
|
expect(workspaceSource).toContain('data-testid="gateway-unavailable-state"');
|
|
expect(edgeGatewaysViewSource).toContain('route.name === "edgegatewaydetail"');
|
|
expect(edgeGatewaysViewSource).toContain(':selected-gateway-id="selectedGatewayId"');
|
|
expect(edgeGatewaysViewSource).toContain('@select-gateway="handleGatewaySelection"');
|
|
expect(departmentGatewaysViewSource).toContain('@open-gateway-page="openGatewayPage"');
|
|
expect(departmentGatewaysViewSource).toContain('name: "edgegatewaydetail"');
|
|
});
|
|
});
|