198 lines
13 KiB
JavaScript
198 lines
13 KiB
JavaScript
import { readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const root = process.cwd();
|
|
const managerSource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayManager.vue"), "utf8");
|
|
const overviewSource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayOverviewPage.vue"), "utf8");
|
|
const inventorySource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayInventoryPage.vue"), "utf8");
|
|
const tasksSource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayTasksPage.vue"), "utf8");
|
|
const logsSource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayLogsPage.vue"), "utf8");
|
|
const statisticsSource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayStatisticsPage.vue"), "utf8");
|
|
const terminalSource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayTerminalPage.vue"), "utf8");
|
|
const liveSessionsSource = readFileSync(join(root, "src/features/edgeGateways/edgeGatewayLiveSessions.js"), "utf8");
|
|
const manageSource = readFileSync(join(root, "src/features/edgeGateways/EdgeGatewayManagePage.vue"), "utf8");
|
|
const routerSource = readFileSync(join(root, "src/router.js"), "utf8");
|
|
const edgeGatewaysPageSource = readFileSync(
|
|
join(root, "src/views/dashboards/superUserDashboard/EdgeGatewaysWorkspacePage.vue"),
|
|
"utf8"
|
|
);
|
|
const edgeAgentsSource = readFileSync(
|
|
join(root, "src/views/dashboards/superUserDashboard/selfserve/EdgeAgents.vue"),
|
|
"utf8"
|
|
);
|
|
const selfServeTabsSource = readFileSync(
|
|
join(root, "src/views/dashboards/superUserDashboard/selfserve/SelfServeSuperUserTabs.vue"),
|
|
"utf8"
|
|
);
|
|
const departmentWorkspaceSource = readFileSync(
|
|
join(root, "src/features/edgeGateways/EdgeGatewayDepartmentWorkspace.vue"),
|
|
"utf8"
|
|
);
|
|
const departmentGatewaysPageSource = readFileSync(
|
|
join(root, "src/views/dashboards/superUserDashboard/department/DepartmentGatewaysWorkspacePage.vue"),
|
|
"utf8"
|
|
);
|
|
const navigationSource = readFileSync(
|
|
join(root, "src/components/models/navigation/items/NavigationMenuItemsSuperUser.vue"),
|
|
"utf8"
|
|
);
|
|
const configurationNavigationSource = readFileSync(
|
|
join(root, "src/views/dashboards/superUserDashboard/configuration/SuperUserDashboardConfigurationNavigation.vue"),
|
|
"utf8"
|
|
);
|
|
|
|
describe("edge gateway workspace contract", () => {
|
|
it("splits the module UI into route-aligned overview, tasks, logs, statistics, terminal, inventory, and settings pages", () => {
|
|
expect(managerSource).toContain('data-testid="edge-gateway-workspace"');
|
|
expect(managerSource).toContain('data-testid="gateway-summary-strip"');
|
|
expect(managerSource).toContain('data-testid="gateway-fleet-usage"');
|
|
expect(managerSource).toContain('data-testid="gateway-onboarding"');
|
|
expect(managerSource).toContain('data-testid="gateway-installer-status"');
|
|
expect(managerSource).toContain('data-testid="gateway-installer-status-step"');
|
|
expect(managerSource).toContain('data-testid="gateway-installer-status-state"');
|
|
expect(managerSource).toContain('data-testid="gateway-installer-status-diagnostics"');
|
|
expect(managerSource).toContain('id: "tasks"');
|
|
expect(managerSource).toContain('id: "logs"');
|
|
expect(managerSource).toContain('id: "statistics"');
|
|
expect(managerSource).toContain('id: "terminal"');
|
|
expect(managerSource).toContain('id: "settings"');
|
|
expect(managerSource).toContain("import EdgeGatewayOverviewPage");
|
|
expect(managerSource).toContain("import EdgeGatewayInventoryPage");
|
|
expect(managerSource).toContain("import EdgeGatewayTasksPage");
|
|
expect(managerSource).toContain("import EdgeGatewayLogsPage");
|
|
expect(managerSource).toContain("import EdgeGatewayStatisticsPage");
|
|
expect(managerSource).toContain("import EdgeGatewayTerminalPage");
|
|
expect(managerSource).toContain("import EdgeGatewayManagePage");
|
|
|
|
expect(overviewSource).toContain('data-testid="gateway-overview-page"');
|
|
expect(overviewSource).toContain('data-testid="gateway-open-full-page"');
|
|
expect(overviewSource).toContain('data-testid="gateway-overview-container-health"');
|
|
expect(overviewSource).toContain('data-testid="gateway-overview-container-services"');
|
|
expect(overviewSource).toContain('data-testid="gateway-overview-outbox"');
|
|
expect(overviewSource).toContain('data-testid="gateway-overview-update-window"');
|
|
expect(overviewSource).toContain('data-testid="gateway-overview-rollout"');
|
|
expect(inventorySource).toContain('data-testid="gateway-inventory-page"');
|
|
expect(tasksSource).toContain('data-testid="gateway-tasks-page"');
|
|
expect(tasksSource).toContain('data-testid="gateway-operation-cancel"');
|
|
expect(tasksSource).toContain('data-testid="gateway-operation-retry"');
|
|
expect(logsSource).toContain('data-testid="gateway-logs-page"');
|
|
expect(logsSource).toContain('data-testid="gateway-relay-logs"');
|
|
expect(logsSource).toContain('<option value="relay">Relay</option>');
|
|
expect(logsSource).toContain("const relayDescription = (entry = {}) =>");
|
|
expect(logsSource).toContain('MACHINE_PROGRAM_PICKER: "PROGRAM_PICKER"');
|
|
expect(managerSource).toContain(':relay-logs="logRelayLogs"');
|
|
expect(statisticsSource).toContain('data-testid="gateway-statistics-page"');
|
|
expect(terminalSource).toContain('data-testid="gateway-terminal-page"');
|
|
expect(terminalSource).toContain('data-testid="gateway-terminal-status"');
|
|
expect(manageSource).toContain('data-testid="gateway-settings-page"');
|
|
expect(manageSource).toContain('data-testid="gateway-rotate-confirmation"');
|
|
expect(manageSource).toContain('data-testid="gateway-delete-confirmation"');
|
|
expect(managerSource).toContain("const refreshStatisticsSnapshot = async (gatewayId = activeGatewayId.value) =>");
|
|
expect(managerSource).toContain(
|
|
'statisticsSnapshot.value = statisticsWithLiveSnapshot(payload && typeof payload === "object" ? payload : {});'
|
|
);
|
|
expect(managerSource).toContain("if (statisticsSnapshot.value?.gateway) {");
|
|
expect(managerSource).toContain("setSelectedGatewaySnapshot(statisticsSnapshot.value.gateway);");
|
|
expect(managerSource).toContain("import { createGatewayShellClient, createGatewayStreamClient }");
|
|
expect(managerSource).toContain("const applyGatewayTelemetry = (message = {}) =>");
|
|
expect(managerSource).toContain("const gatewayWithLiveSnapshot = (gateway) =>");
|
|
expect(managerSource).toContain("statisticsWithLiveSnapshot(payload");
|
|
expect(managerSource).toContain(
|
|
'createGatewayStreamClient(normalizedGatewayId, ["overview", "tasks", "logs", "statistics"]'
|
|
);
|
|
expect(managerSource).toContain("createGatewayShellClient(");
|
|
expect(managerSource).toContain('message.type === "output" || message.type === "raw"');
|
|
expect(managerSource).toContain("const normalizeTerminalClosePayload = (message = {}) =>");
|
|
expect(managerSource).toContain("const terminalErrorDetails = ref([]);");
|
|
expect(managerSource).toContain("const terminalBrokerReadinessBlock = (gateway = selectedGatewayView.value) =>");
|
|
expect(managerSource).toContain("const terminalCloseDiagnostics = (message = {}) =>");
|
|
expect(managerSource).toContain("const terminalCloseMessage = (message = {}, status = terminalStatus.value) =>");
|
|
expect(managerSource).toContain("Gateway agent is not connected to the broker.");
|
|
expect(managerSource).toContain(':diagnostics="terminalErrorDetails"');
|
|
expect(managerSource).toContain("applyTerminalClosed(message);");
|
|
expect(managerSource).toContain("onClose: (closeEvent = {}) =>");
|
|
expect(managerSource).toContain("applyTerminalClosed(closeEvent);");
|
|
expect(managerSource).toContain("WebSocket ${code}");
|
|
expect(terminalSource).toContain('data-testid="gateway-terminal-diagnostics"');
|
|
expect(managerSource).toContain("terminalClient.sendInput(`${commandText}\\n`)");
|
|
expect(managerSource).not.toContain("terminalMockResponse");
|
|
expect(managerSource).not.toContain("createEdgeGatewayShellSession");
|
|
expect(liveSessionsSource).toContain("export async function createGatewayShellClient");
|
|
expect(liveSessionsSource).toContain("normalizeGatewayWebSocketClose");
|
|
expect(liveSessionsSource).toContain("mock_close_before_open");
|
|
expect(liveSessionsSource).toContain('reason: event.reason || "socket_closed"');
|
|
expect(liveSessionsSource).toContain("if (connection.readyState === 1)");
|
|
expect(liveSessionsSource).toContain('connection.close("shell_closed")');
|
|
expect(managerSource).toContain('currentView.value === "terminal"');
|
|
expect(managerSource).toContain(':stream-status="gatewayStreamStatus"');
|
|
});
|
|
|
|
it("keeps module configuration separate from the Edge Agents fleet workspace", () => {
|
|
expect(edgeGatewaysPageSource).toContain('data-testid="edge-gateway-module-config"');
|
|
expect(edgeGatewaysPageSource).toContain("gateway-module-disabled-state");
|
|
expect(edgeGatewaysPageSource).toContain("validatePublicBrokerUrl");
|
|
expect(edgeGatewaysPageSource).toContain("sanitizeBrokerAuthMode");
|
|
expect(edgeGatewaysPageSource).toContain("redactBrokerSharedSecret()");
|
|
expect(edgeGatewaysPageSource).toContain("stub (development only)");
|
|
expect(edgeGatewaysPageSource).toContain("Leave blank to keep the existing secret");
|
|
expect(edgeGatewaysPageSource).not.toContain("broker_shared_secret: response?.data?.config?.broker_shared_secret");
|
|
expect(edgeGatewaysPageSource).not.toContain("broker_shared_secret: moduleConfigMap.value.broker_shared_secret ||");
|
|
expect(edgeGatewaysPageSource).not.toContain("EdgeGatewayManager");
|
|
expect(edgeGatewaysPageSource).not.toContain("EdgeGatewayFleetLanding");
|
|
expect(edgeAgentsSource).toContain('data-testid="edge-agents-page"');
|
|
expect(edgeAgentsSource).toContain("EdgeGatewayFleetLanding");
|
|
expect(edgeAgentsSource).toContain("EdgeGatewayManager");
|
|
expect(edgeAgentsSource).toContain(':route-driven="true"');
|
|
expect(edgeAgentsSource).toContain(':allow-destructive="true"');
|
|
expect(edgeAgentsSource).toContain("/superuser/selfserve/edge-agents");
|
|
expect(selfServeTabsSource).toContain("Edge Agents");
|
|
expect(selfServeTabsSource).toContain("/superuser/selfserve/edge-agents");
|
|
expect(departmentGatewaysPageSource).toContain("EdgeGatewayDepartmentWorkspace");
|
|
expect(departmentWorkspaceSource).toContain(':route-driven="false"');
|
|
expect(departmentWorkspaceSource).toContain(':allow-destructive="false"');
|
|
expect(departmentWorkspaceSource).toContain('@open-gateway-page="openGatewayPage"');
|
|
});
|
|
|
|
it("registers canonical module routes and keeps legacy redirects", () => {
|
|
expect(routerSource).toContain("path: '/superuser/configuration/edgegateway'");
|
|
expect(routerSource).toContain("component: EdgeGatewaysWorkspacePage");
|
|
expect(routerSource).toContain("name: 'edgeagents'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents'");
|
|
expect(routerSource).toContain("name: 'edgeagentoverview'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/overview'");
|
|
expect(routerSource).toContain("name: 'edgeagenttasks'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/tasks'");
|
|
expect(routerSource).toContain("name: 'edgeagentlogs'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/logs'");
|
|
expect(routerSource).toContain("name: 'edgeagentstatistics'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/statistics'");
|
|
expect(routerSource).toContain("name: 'edgeagentterminal'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/terminal'");
|
|
expect(routerSource).toContain("name: 'edgeagentinventory'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/inventory'");
|
|
expect(routerSource).toContain("name: 'edgeagentoperations'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/operations'");
|
|
expect(routerSource).toContain("/tasks`");
|
|
expect(routerSource).toContain("name: 'edgeagentsettings'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/settings'");
|
|
expect(routerSource).toContain("name: 'edgeagentmanage'");
|
|
expect(routerSource).toContain("path: '/superuser/selfserve/edge-agents/:id/manage'");
|
|
expect(routerSource).toContain("/settings`");
|
|
expect(routerSource).toContain("name: 'edgegatewayoverview'");
|
|
expect(routerSource).toContain(
|
|
"redirect: (to) => `/superuser/selfserve/edge-agents/${encodeURIComponent(String(to.params.id))}/overview`"
|
|
);
|
|
expect(routerSource).toContain("path: '/superuser/gateways'");
|
|
expect(routerSource).toContain("configure: 'inventory'");
|
|
expect(routerSource).toContain("assess: 'overview'");
|
|
});
|
|
|
|
it("surfaces the module in superuser navigation and configuration tabs", () => {
|
|
expect(navigationSource).toContain("/superuser/selfserve/edge-agents");
|
|
expect(navigationSource).toContain("/superuser/configuration/edgegateway");
|
|
expect(configurationNavigationSource).toContain("Edge Gateway");
|
|
expect(configurationNavigationSource).toContain("/superuser/configuration/edgegateway");
|
|
});
|
|
});
|