Files
oneuptime/Common/Tests/Server/Utils/VM/VMAPI.test.ts
Nawaz Dhandala c309fafdb6 Remove IsolatedVM service and related configurations from the project
- Deleted package.json and tsconfig.json for IsolatedVM.
- Removed isolated-vm upstream configuration from Nginx default.conf.template.
- Removed ISOLATED_VM_PORT and telemetry settings from config.example.env.
- Cleaned up docker-compose.base.yml by removing isolated-vm service and its environment variables.
- Updated docker-compose.dev.yml to eliminate isolated-vm service and its associated volumes.
- Removed isolated-vm service from docker-compose.yml.
2026-03-03 12:25:31 +00:00

300 lines
8.8 KiB
TypeScript

// Mock all heavy dependencies so the test focuses on template logic only
jest.mock("../../../../Server/Utils/VM/VMRunner", () => {
return {
__esModule: true,
default: {
runCodeInSandbox: jest.fn(),
},
};
});
jest.mock("../../../../Server/Utils/Logger", () => {
return {
__esModule: true,
default: {
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
},
};
});
jest.mock("../../../../Server/Utils/Telemetry/CaptureSpan", () => {
return {
__esModule: true,
default: () => {
return (
_target: any,
_propertyKey: string,
descriptor: PropertyDescriptor,
) => {
return descriptor;
};
},
};
});
import VMUtil from "../../../../Server/Utils/VM/VMAPI";
import { describe, expect, it } from "@jest/globals";
import { JSONObject } from "../../../../Types/JSON";
describe("VMUtil", () => {
describe("deepFind", () => {
it("should find top-level keys", () => {
const obj: JSONObject = { status: "firing", receiver: "test" };
expect(VMUtil.deepFind(obj, "status")).toBe("firing");
});
it("should find nested keys with dot notation", () => {
const obj: JSONObject = { data: { nested: { value: 42 } } };
expect(VMUtil.deepFind(obj, "data.nested.value")).toBe(42);
});
it("should find array elements with bracket notation", () => {
const obj: JSONObject = { items: ["a", "b", "c"] };
expect(VMUtil.deepFind(obj, "items[0]")).toBe("a");
expect(VMUtil.deepFind(obj, "items[2]")).toBe("c");
});
it("should find last array element with [last]", () => {
const obj: JSONObject = { items: [1, 2, 3] };
expect(VMUtil.deepFind(obj, "items[last]")).toBe(3);
});
it("should return undefined for missing paths", () => {
const obj: JSONObject = { a: { b: 1 } };
expect(VMUtil.deepFind(obj, "a.c")).toBeUndefined();
expect(VMUtil.deepFind(obj, "x.y.z")).toBeUndefined();
});
});
describe("replaceValueInPlace", () => {
it("should replace simple variables", () => {
const storageMap: JSONObject = { name: "test", status: "firing" };
const result: string = VMUtil.replaceValueInPlace(
storageMap,
"Alert: {{name}} is {{status}}",
false,
);
expect(result).toBe("Alert: test is firing");
});
it("should replace nested dotted path variables", () => {
const storageMap: JSONObject = {
requestBody: { title: "My Alert", data: { severity: "high" } },
};
const result: string = VMUtil.replaceValueInPlace(
storageMap,
"Title: {{requestBody.title}}, Severity: {{requestBody.data.severity}}",
false,
);
expect(result).toBe("Title: My Alert, Severity: high");
});
it("should leave unresolved variables as-is", () => {
const storageMap: JSONObject = { name: "test" };
const result: string = VMUtil.replaceValueInPlace(
storageMap,
"{{name}} {{unknown}}",
false,
);
expect(result).toBe("test {{unknown}}");
});
});
describe("expandEachLoops", () => {
it("should expand a simple each loop over an array of objects", () => {
const storageMap: JSONObject = {
requestBody: {
alerts: [
{ labels: { label: "Coralpay" }, status: "firing" },
{ labels: { label: "capitecpay" }, status: "resolved" },
],
},
};
const template: string =
"Alerts:{{#each requestBody.alerts}} {{labels.label}}({{status}}){{/each}}";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("Alerts: Coralpay(firing) capitecpay(resolved)");
});
it("should support {{@index}} in loops", () => {
const storageMap: JSONObject = {
items: [{ name: "a" }, { name: "b" }, { name: "c" }],
};
const template: string = "{{#each items}}{{@index}}: {{name}} {{/each}}";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("0: a 1: b 2: c ");
});
it("should support {{this}} for primitive arrays", () => {
const storageMap: JSONObject = {
tags: ["critical", "production", "api"],
};
const template: string = "Tags:{{#each tags}} {{this}}{{/each}}";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("Tags: critical production api");
});
it("should remove the block if the path is not an array", () => {
const storageMap: JSONObject = { notAnArray: "hello" };
const template: string = "Before {{#each notAnArray}}body{{/each}} After";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("Before After");
});
it("should remove the block if the path does not exist", () => {
const storageMap: JSONObject = {};
const template: string =
"Before {{#each missing.path}}body{{/each}} After";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("Before After");
});
it("should handle empty arrays", () => {
const storageMap: JSONObject = { items: [] };
const template: string = "Before {{#each items}}item{{/each}} After";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("Before After");
});
it("should support nested each loops", () => {
const storageMap: JSONObject = {
groups: [
{ name: "G1", members: [{ id: 1 }, { id: 2 }] },
{ name: "G2", members: [{ id: 3 }] },
],
};
const template: string =
"{{#each groups}}Group {{name}}: {{#each members}}{{id}} {{/each}}| {{/each}}";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("Group G1: 1 2 | Group G2: 3 | ");
});
it("should allow fallback to parent variables inside loops", () => {
const storageMap: JSONObject = {
globalTitle: "My Dashboard",
items: [{ name: "item1" }, { name: "item2" }],
};
const template: string =
"{{#each items}}{{name}} in {{globalTitle}} {{/each}}";
const result: string = VMUtil.expandEachLoops(
storageMap,
template,
false,
);
expect(result).toBe("item1 in My Dashboard item2 in My Dashboard ");
});
});
describe("replaceValueInPlace with each loops (end-to-end)", () => {
it("should expand loops and then replace remaining variables", () => {
const storageMap: JSONObject = {
requestBody: {
receiver: "Fundsflow",
alerts: [
{
status: "firing",
labels: { label: "Coralpay", alertname: "File Drop" },
},
{
status: "firing",
labels: { label: "capitecpay", alertname: "File Drop" },
},
],
},
};
const template: string =
"Receiver: {{requestBody.receiver}}\n{{#each requestBody.alerts}}- {{labels.label}}: {{status}}\n{{/each}}";
const result: string = VMUtil.replaceValueInPlace(
storageMap,
template,
false,
);
expect(result).toBe(
"Receiver: Fundsflow\n- Coralpay: firing\n- capitecpay: firing\n",
);
});
it("should handle the Grafana alerts use case", () => {
const storageMap: JSONObject = {
requestBody: {
status: "firing",
alerts: [
{
status: "firing",
labels: {
alertname: "Fundsflow File Drop Update",
label: "Coralpay",
},
valueString: "A=0, C=1",
},
{
status: "firing",
labels: {
alertname: "Fundsflow File Drop Update",
label: "capitecpay",
},
valueString: "A=0, C=1",
},
{
status: "firing",
labels: {
alertname: "Fundsflow File Drop Update",
label: "capricorn",
},
valueString: "A=0, C=1",
},
],
},
};
const template: string =
"Alert Labels:\n{{#each requestBody.alerts}}- {{labels.label}}\n{{/each}}";
const result: string = VMUtil.replaceValueInPlace(
storageMap,
template,
false,
);
expect(result).toBe(
"Alert Labels:\n- Coralpay\n- capitecpay\n- capricorn\n",
);
});
});
});