Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
/* @vitest-environment jsdom */
import { render } from "lit";
import { describe, expect, it } from "vitest";
import { renderNodes, type NodesProps } from "./nodes.ts";
function baseProps(overrides: Partial<NodesProps> = {}): NodesProps {
return {
loading: false,
nodes: [],
devicesLoading: false,
devicesError: null,
devicesList: {
pending: [],
paired: [],
},
configForm: null,
configLoading: false,
configSaving: false,
configDirty: false,
configFormMode: "form",
execApprovalsLoading: false,
execApprovalsSaving: false,
execApprovalsDirty: false,
execApprovalsSnapshot: null,
execApprovalsForm: null,
execApprovalsSelectedAgent: null,
execApprovalsTarget: "gateway",
execApprovalsTargetNodeId: null,
onRefresh: () => undefined,
onDevicesRefresh: () => undefined,
onDeviceApprove: () => undefined,
onDeviceReject: () => undefined,
onDeviceRotate: () => undefined,
onDeviceRevoke: () => undefined,
onLoadConfig: () => undefined,
onLoadExecApprovals: () => undefined,
onBindDefault: () => undefined,
onBindAgent: () => undefined,
onSaveBindings: () => undefined,
onExecApprovalsTargetChange: () => undefined,
onExecApprovalsSelectAgent: () => undefined,
onExecApprovalsPatch: () => undefined,
onExecApprovalsRemove: () => undefined,
onSaveExecApprovals: () => undefined,
...overrides,
};
}
function renderNodesText(overrides: Partial<NodesProps>): string {
const container = document.createElement("div");
render(renderNodes(baseProps(overrides)), container);
return container.textContent ?? "";
}
describe("nodes devices pending rendering", () => {
it("shows requested and approved access for a scope upgrade", () => {
const text = renderNodesText({
devicesList: {
pending: [
{
requestId: "req-1",
deviceId: "device-1",
displayName: "Device One",
role: "operator",
scopes: ["operator.admin", "operator.read"],
ts: Date.now(),
},
],
paired: [
{
deviceId: "device-1",
displayName: "Device One",
roles: ["operator"],
scopes: ["operator.read"],
},
],
},
});
expect(text).toContain("scope upgrade requires approval");
expect(text).toContain("requested: roles: operator");
expect(text).toContain("approved now: roles: operator");
expect(text).toContain("operator.admin, operator.read");
});
it("normalizes pending device ids before matching paired access", () => {
const text = renderNodesText({
devicesList: {
pending: [
{
requestId: "req-1",
deviceId: " device-1 ",
displayName: "Device One",
role: "operator",
scopes: ["operator.admin", "operator.read"],
ts: Date.now(),
},
],
paired: [
{
deviceId: "device-1",
displayName: "Device One",
roles: ["operator"],
scopes: ["operator.read"],
},
],
},
});
expect(text).toContain("scope upgrade requires approval");
expect(text).toContain("approved now: roles: operator");
});
it("does not show upgrade context for key-mismatched pending requests", () => {
const text = renderNodesText({
devicesList: {
pending: [
{
requestId: "req-1",
deviceId: "device-1",
publicKey: "new-key",
displayName: "Device One",
role: "operator",
scopes: ["operator.admin"],
ts: Date.now(),
},
],
paired: [
{
deviceId: "device-1",
publicKey: "old-key",
displayName: "Device One",
roles: ["operator"],
scopes: ["operator.read"],
},
],
},
});
expect(text).toContain("new device pairing request");
expect(text).not.toContain("scope upgrade requires approval");
expect(text).not.toContain("approved now:");
});
it("falls back to roles when role is absent", () => {
const text = renderNodesText({
devicesList: {
pending: [
{
requestId: "req-2",
deviceId: "device-2",
roles: ["node", "operator"],
scopes: ["operator.read"],
ts: Date.now(),
},
],
paired: [],
},
});
expect(text).toContain("requested: roles: node, operator");
expect(text).toContain("scopes: operator.read");
});
});
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-04-27)
¤
*© Formatika GbR, Deutschland
|
|