@pagopa/dx-savemoney 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/azure/pricing/pricing-service.d.ts.map +1 -1
- package/dist/azure/pricing/pricing-service.js +6 -1
- package/dist/azure/pricing/pricing-service.js.map +1 -1
- package/dist/azure/pricing/schema.d.ts.map +1 -1
- package/dist/azure/pricing/schema.js +22 -14
- package/dist/azure/pricing/schema.js.map +1 -1
- package/dist/azure/resources/app-service.d.ts.map +1 -1
- package/dist/azure/resources/app-service.js +2 -2
- package/dist/azure/resources/app-service.js.map +1 -1
- package/dist/azure/resources/container-app.d.ts.map +1 -1
- package/dist/azure/resources/container-app.js +1 -1
- package/dist/azure/resources/container-app.js.map +1 -1
- package/dist/azure/resources/disk.js +3 -1
- package/dist/azure/resources/disk.js.map +1 -1
- package/dist/azure/resources/nic.js +3 -1
- package/dist/azure/resources/nic.js.map +1 -1
- package/dist/azure/resources/private-endpoint.d.ts.map +1 -1
- package/dist/azure/resources/private-endpoint.js +1 -1
- package/dist/azure/resources/private-endpoint.js.map +1 -1
- package/dist/azure/resources/public-ip.d.ts.map +1 -1
- package/dist/azure/resources/public-ip.js +4 -2
- package/dist/azure/resources/public-ip.js.map +1 -1
- package/dist/azure/resources/static-web-app.d.ts.map +1 -1
- package/dist/azure/resources/static-web-app.js +1 -1
- package/dist/azure/resources/static-web-app.js.map +1 -1
- package/dist/azure/resources/vm.js +6 -2
- package/dist/azure/resources/vm.js.map +1 -1
- package/dist/azure/utils.d.ts.map +1 -1
- package/dist/azure/utils.js +7 -2
- package/dist/azure/utils.js.map +1 -1
- package/package.json +1 -8
- package/src/azure/pricing/__tests__/schema.test.ts +30 -0
- package/src/azure/pricing/pricing-service.ts +6 -3
- package/src/azure/pricing/schema.ts +22 -14
- package/src/azure/resources/app-service.ts +4 -2
- package/src/azure/resources/container-app.ts +2 -1
- package/src/azure/resources/disk.ts +3 -3
- package/src/azure/resources/nic.ts +3 -3
- package/src/azure/resources/private-endpoint.ts +2 -1
- package/src/azure/resources/public-ip.ts +5 -4
- package/src/azure/resources/static-web-app.ts +2 -1
- package/src/azure/resources/vm.ts +6 -6
- package/src/azure/utils.ts +8 -2
- package/dist/__tests__/finding.test.d.ts +0 -17
- package/dist/__tests__/finding.test.d.ts.map +0 -1
- package/dist/__tests__/finding.test.js +0 -146
- package/dist/__tests__/finding.test.js.map +0 -1
- package/dist/azure/__tests__/analyzer-tags.test.d.ts +0 -8
- package/dist/azure/__tests__/analyzer-tags.test.d.ts.map +0 -1
- package/dist/azure/__tests__/analyzer-tags.test.js +0 -70
- package/dist/azure/__tests__/analyzer-tags.test.js.map +0 -1
- package/dist/azure/__tests__/azqr.test.d.ts +0 -13
- package/dist/azure/__tests__/azqr.test.d.ts.map +0 -1
- package/dist/azure/__tests__/azqr.test.js +0 -177
- package/dist/azure/__tests__/azqr.test.js.map +0 -1
- package/dist/azure/__tests__/config.test.d.ts +0 -9
- package/dist/azure/__tests__/config.test.d.ts.map +0 -1
- package/dist/azure/__tests__/config.test.js +0 -102
- package/dist/azure/__tests__/config.test.js.map +0 -1
- package/dist/azure/__tests__/report.test.d.ts +0 -9
- package/dist/azure/__tests__/report.test.d.ts.map +0 -1
- package/dist/azure/__tests__/report.test.js +0 -191
- package/dist/azure/__tests__/report.test.js.map +0 -1
- package/dist/azure/__tests__/utils.test.d.ts +0 -15
- package/dist/azure/__tests__/utils.test.d.ts.map +0 -1
- package/dist/azure/__tests__/utils.test.js +0 -181
- package/dist/azure/__tests__/utils.test.js.map +0 -1
- package/dist/azure/analyzers/__tests__/advisor.test.d.ts +0 -9
- package/dist/azure/analyzers/__tests__/advisor.test.d.ts.map +0 -1
- package/dist/azure/analyzers/__tests__/advisor.test.js +0 -314
- package/dist/azure/analyzers/__tests__/advisor.test.js.map +0 -1
- package/dist/azure/pricing/__tests__/cache.test.d.ts +0 -8
- package/dist/azure/pricing/__tests__/cache.test.d.ts.map +0 -1
- package/dist/azure/pricing/__tests__/cache.test.js +0 -56
- package/dist/azure/pricing/__tests__/cache.test.js.map +0 -1
- package/dist/azure/pricing/__tests__/client.test.d.ts +0 -9
- package/dist/azure/pricing/__tests__/client.test.d.ts.map +0 -1
- package/dist/azure/pricing/__tests__/client.test.js +0 -181
- package/dist/azure/pricing/__tests__/client.test.js.map +0 -1
- package/dist/azure/pricing/__tests__/pricing-service.test.d.ts +0 -6
- package/dist/azure/pricing/__tests__/pricing-service.test.d.ts.map +0 -1
- package/dist/azure/pricing/__tests__/pricing-service.test.js +0 -283
- package/dist/azure/pricing/__tests__/pricing-service.test.js.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.d.ts +0 -5
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.d.ts.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.js +0 -137
- package/dist/azure/pricing/resolvers/__tests__/app-service.test.js.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/disk.test.d.ts +0 -5
- package/dist/azure/pricing/resolvers/__tests__/disk.test.d.ts.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/disk.test.js +0 -160
- package/dist/azure/pricing/resolvers/__tests__/disk.test.js.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.d.ts +0 -5
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.d.ts.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.js +0 -113
- package/dist/azure/pricing/resolvers/__tests__/public-ip.test.js.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/vm.test.d.ts +0 -9
- package/dist/azure/pricing/resolvers/__tests__/vm.test.d.ts.map +0 -1
- package/dist/azure/pricing/resolvers/__tests__/vm.test.js +0 -204
- package/dist/azure/pricing/resolvers/__tests__/vm.test.js.map +0 -1
- package/dist/azure/resources/__tests__/app-service.test.d.ts +0 -5
- package/dist/azure/resources/__tests__/app-service.test.d.ts.map +0 -1
- package/dist/azure/resources/__tests__/app-service.test.js +0 -105
- package/dist/azure/resources/__tests__/app-service.test.js.map +0 -1
- package/dist/azure/resources/__tests__/storage.test.d.ts +0 -11
- package/dist/azure/resources/__tests__/storage.test.d.ts.map +0 -1
- package/dist/azure/resources/__tests__/storage.test.js +0 -99
- package/dist/azure/resources/__tests__/storage.test.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../../src/azure/__tests__/config.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for loadConfig() — verifies that:
|
|
3
|
-
* 1. Returns default thresholds and prompts for subscriptionIds when no file is given.
|
|
4
|
-
* 2. Loads subscriptionIds, location, timespanDays and thresholds from a YAML file.
|
|
5
|
-
* 3. Partial threshold overrides keep defaults for non-overridden fields.
|
|
6
|
-
* 4. Throws a clear error for a non-existent explicit path.
|
|
7
|
-
*/
|
|
8
|
-
import path from "path";
|
|
9
|
-
import { fileURLToPath } from "url";
|
|
10
|
-
import { afterEach, describe, expect, expectTypeOf, it, vi } from "vitest";
|
|
11
|
-
import { loadConfig } from "../../index.js";
|
|
12
|
-
import { ConfigSchema } from "../../schema.js";
|
|
13
|
-
import { DEFAULT_THRESHOLDS } from "../../types.js";
|
|
14
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
/** Absolute paths used in tests */
|
|
16
|
-
const FIXTURE_PARTIAL = path.resolve(__dirname, "fixtures/partial-override.yaml");
|
|
17
|
-
const FIXTURE_FULL = path.resolve(__dirname, "fixtures/full-override.yaml");
|
|
18
|
-
describe("loadConfig", () => {
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
vi.unstubAllEnvs();
|
|
21
|
-
});
|
|
22
|
-
it("throws when explicit path does not exist", async () => {
|
|
23
|
-
await expect(loadConfig("/nonexistent/config.yaml")).rejects.toThrow("Config file not found");
|
|
24
|
-
});
|
|
25
|
-
it("loads subscriptionIds and defaults from a partial YAML file", async () => {
|
|
26
|
-
const result = await loadConfig(FIXTURE_PARTIAL);
|
|
27
|
-
expectTypeOf().toEqualTypeOf();
|
|
28
|
-
expect(result.subscriptionIds).toEqual([
|
|
29
|
-
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
|
30
|
-
]);
|
|
31
|
-
expect(result.preferredLocation).toBe("italynorth");
|
|
32
|
-
expect(result.sources).toEqual(["advisor", "custom"]);
|
|
33
|
-
expect(result.timespanDays).toBe(30);
|
|
34
|
-
expect(result.azqrReportPath).toBeUndefined();
|
|
35
|
-
});
|
|
36
|
-
it("applies sources defaults when loading from the environment", async () => {
|
|
37
|
-
vi.stubEnv("ARM_SUBSCRIPTION_ID", "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
|
38
|
-
const result = await loadConfig();
|
|
39
|
-
expect(result.sources).toEqual(["advisor", "custom"]);
|
|
40
|
-
});
|
|
41
|
-
it("loads partial threshold overrides and keeps defaults for missing fields", async () => {
|
|
42
|
-
const result = await loadConfig(FIXTURE_PARTIAL);
|
|
43
|
-
// Overridden values
|
|
44
|
-
expect(result.thresholds?.vm.cpuPercent).toBe(5);
|
|
45
|
-
expect(result.thresholds?.storage.transactionsPerDay).toBe(50);
|
|
46
|
-
// Non-overridden vm field keeps default
|
|
47
|
-
expect(result.thresholds?.vm.networkInBytesPerDay).toBe(DEFAULT_THRESHOLDS.vm.networkInBytesPerDay);
|
|
48
|
-
// Entire non-overridden sections keep defaults
|
|
49
|
-
expect(result.thresholds?.appService).toEqual(DEFAULT_THRESHOLDS.appService);
|
|
50
|
-
expect(result.thresholds?.containerApp).toEqual(DEFAULT_THRESHOLDS.containerApp);
|
|
51
|
-
expect(result.thresholds?.publicIp).toEqual(DEFAULT_THRESHOLDS.publicIp);
|
|
52
|
-
expect(result.thresholds?.staticSite).toEqual(DEFAULT_THRESHOLDS.staticSite);
|
|
53
|
-
});
|
|
54
|
-
it("loads all values from a full YAML file", async () => {
|
|
55
|
-
const result = await loadConfig(FIXTURE_FULL);
|
|
56
|
-
expect(result.subscriptionIds).toHaveLength(2);
|
|
57
|
-
expect(result.preferredLocation).toBe("westeurope");
|
|
58
|
-
expect(result.sources).toEqual(["custom"]);
|
|
59
|
-
expect(result.timespanDays).toBe(60);
|
|
60
|
-
expect(result.azqrReportPath).toBe("./azqr_action_plan.json");
|
|
61
|
-
expect(result.thresholds?.vm.cpuPercent).toBe(5);
|
|
62
|
-
expect(result.thresholds?.vm.networkInBytesPerDay).toBe(10485760);
|
|
63
|
-
expect(result.thresholds?.appService.cpuPercent).toBe(10);
|
|
64
|
-
expect(result.thresholds?.appService.memoryPercent).toBe(20);
|
|
65
|
-
expect(result.thresholds?.appService.premiumCpuPercent).toBe(15);
|
|
66
|
-
expect(result.thresholds?.containerApp.cpuNanoCores).toBe(5000000);
|
|
67
|
-
expect(result.thresholds?.containerApp.memoryBytes).toBe(52428800);
|
|
68
|
-
expect(result.thresholds?.containerApp.networkBytes).toBe(100000);
|
|
69
|
-
expect(result.thresholds?.storage.transactionsPerDay).toBe(50);
|
|
70
|
-
expect(result.thresholds?.publicIp.bytesInDDoS).toBe(1048576);
|
|
71
|
-
expect(result.thresholds?.staticSite.siteHits).toBe(500);
|
|
72
|
-
expect(result.thresholds?.staticSite.bytesSent).toBe(5242880);
|
|
73
|
-
});
|
|
74
|
-
it("returns a complete Thresholds object (all required keys present)", async () => {
|
|
75
|
-
const result = await loadConfig(FIXTURE_PARTIAL);
|
|
76
|
-
expect(result.thresholds).toHaveProperty("vm");
|
|
77
|
-
expect(result.thresholds).toHaveProperty("appService");
|
|
78
|
-
expect(result.thresholds).toHaveProperty("containerApp");
|
|
79
|
-
expect(result.thresholds).toHaveProperty("storage");
|
|
80
|
-
expect(result.thresholds).toHaveProperty("publicIp");
|
|
81
|
-
expect(result.thresholds).toHaveProperty("staticSite");
|
|
82
|
-
});
|
|
83
|
-
it("rejects an empty sources list", () => {
|
|
84
|
-
const result = ConfigSchema.safeParse({
|
|
85
|
-
azure: {
|
|
86
|
-
sources: [],
|
|
87
|
-
subscriptionIds: ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
expect(result.success).toBe(false);
|
|
91
|
-
});
|
|
92
|
-
it("does not expose pricing settings in YAML config", () => {
|
|
93
|
-
const result = ConfigSchema.safeParse({
|
|
94
|
-
azure: {
|
|
95
|
-
pricing: { enabled: false },
|
|
96
|
-
subscriptionIds: ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
expect(result.success).toBe(false);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
//# sourceMappingURL=config.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../src/azure/__tests__/config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for generateReport() with the "lint" format.
|
|
3
|
-
*
|
|
4
|
-
* Since process.stdout.isTTY is false/undefined in test environments,
|
|
5
|
-
* ANSI color codes are empty strings (~no-ops), making the output
|
|
6
|
-
* easy to assert on plain text.
|
|
7
|
-
*/
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=report.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"report.test.d.ts","sourceRoot":"","sources":["../../../src/azure/__tests__/report.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for generateReport() with the "lint" format.
|
|
3
|
-
*
|
|
4
|
-
* Since process.stdout.isTTY is false/undefined in test environments,
|
|
5
|
-
* ANSI color codes are empty strings (~no-ops), making the output
|
|
6
|
-
* easy to assert on plain text.
|
|
7
|
-
*/
|
|
8
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
9
|
-
import { generateReport } from "../report.js";
|
|
10
|
-
// ── test fixtures ──────────────────────────────────────────────────────────
|
|
11
|
-
function makeEntry(id, costRisk, reason, suspectedUnused = true) {
|
|
12
|
-
return {
|
|
13
|
-
analysis: { costRisk, reason, suspectedUnused },
|
|
14
|
-
resource: {
|
|
15
|
-
id,
|
|
16
|
-
name: id.split("/").pop() ?? "unknown",
|
|
17
|
-
type: "Microsoft.Compute/virtualMachines",
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
const HIGH_ENTRY = makeEntry("/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm-high", "high", "VM is deallocated. No disk activity detected.");
|
|
22
|
-
const MEDIUM_ENTRY = makeEntry("/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm-medium", "medium", "Low CPU usage.");
|
|
23
|
-
const LOW_ENTRY = makeEntry("/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm-low", "low", "Possible idle resource.", false);
|
|
24
|
-
// ── helpers ────────────────────────────────────────────────────────────────
|
|
25
|
-
function allLogs(spy) {
|
|
26
|
-
return spy.mock.calls.map((c) => c[0]).join("\n");
|
|
27
|
-
}
|
|
28
|
-
// ── tests ──────────────────────────────────────────────────────────────────
|
|
29
|
-
describe("generateReport — lint format", () => {
|
|
30
|
-
let logSpy;
|
|
31
|
-
beforeEach(() => {
|
|
32
|
-
logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
33
|
-
});
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
vi.restoreAllMocks();
|
|
36
|
-
});
|
|
37
|
-
it("prints the resource ID for each entry", async () => {
|
|
38
|
-
await generateReport([HIGH_ENTRY], "lint");
|
|
39
|
-
const output = allLogs(logSpy);
|
|
40
|
-
expect(output).toContain(HIGH_ENTRY.resource.id);
|
|
41
|
-
});
|
|
42
|
-
it("uses ✖ icon for high-risk resources", async () => {
|
|
43
|
-
await generateReport([HIGH_ENTRY], "lint");
|
|
44
|
-
const output = allLogs(logSpy);
|
|
45
|
-
expect(output).toContain("✖");
|
|
46
|
-
});
|
|
47
|
-
it("uses ⚠ icon for medium-risk resources", async () => {
|
|
48
|
-
await generateReport([MEDIUM_ENTRY], "lint");
|
|
49
|
-
const output = allLogs(logSpy);
|
|
50
|
-
expect(output).toContain("⚠");
|
|
51
|
-
});
|
|
52
|
-
it("uses ℹ icon for low-risk resources", async () => {
|
|
53
|
-
await generateReport([LOW_ENTRY], "lint");
|
|
54
|
-
const output = allLogs(logSpy);
|
|
55
|
-
expect(output).toContain("ℹ");
|
|
56
|
-
});
|
|
57
|
-
it("splits a multi-sentence reason into separate findings", async () => {
|
|
58
|
-
// Reason has two sentences separated by '. '
|
|
59
|
-
await generateReport([HIGH_ENTRY], "lint");
|
|
60
|
-
const calls = logSpy.mock.calls.map((c) => c[0] ?? "");
|
|
61
|
-
const findingLines = calls.filter((l) => l.startsWith(" "));
|
|
62
|
-
// "VM is deallocated." and "No disk activity detected." → 2 findings
|
|
63
|
-
expect(findingLines.length).toBe(2);
|
|
64
|
-
});
|
|
65
|
-
it("prints a Summary line at the end", async () => {
|
|
66
|
-
await generateReport([HIGH_ENTRY, MEDIUM_ENTRY, LOW_ENTRY], "lint");
|
|
67
|
-
const output = allLogs(logSpy);
|
|
68
|
-
expect(output).toContain("Summary:");
|
|
69
|
-
});
|
|
70
|
-
it("summary reports correct total issue count", async () => {
|
|
71
|
-
await generateReport([HIGH_ENTRY, MEDIUM_ENTRY, LOW_ENTRY], "lint");
|
|
72
|
-
const output = allLogs(logSpy);
|
|
73
|
-
// HIGH has 2 findings (split reason), MEDIUM and LOW have 1 each → total 4
|
|
74
|
-
expect(output).toContain("4 issues found");
|
|
75
|
-
});
|
|
76
|
-
it("summary reports correctly with a single issue (no plural)", async () => {
|
|
77
|
-
await generateReport([MEDIUM_ENTRY], "lint");
|
|
78
|
-
const output = allLogs(logSpy);
|
|
79
|
-
// "1 issue found" (not "1 issues found")
|
|
80
|
-
expect(output).toContain("1 issue found");
|
|
81
|
-
});
|
|
82
|
-
it("shows risk level label in uppercase for each finding", async () => {
|
|
83
|
-
await generateReport([HIGH_ENTRY], "lint");
|
|
84
|
-
const output = allLogs(logSpy);
|
|
85
|
-
expect(output).toContain("HIGH");
|
|
86
|
-
});
|
|
87
|
-
it("prints nothing but the summary for an empty report", async () => {
|
|
88
|
-
await generateReport([], "lint");
|
|
89
|
-
const calls = logSpy.mock.calls.map((c) => c[0]);
|
|
90
|
-
expect(calls).toHaveLength(1);
|
|
91
|
-
expect(calls[0]).toContain("0 issues found");
|
|
92
|
-
});
|
|
93
|
-
describe("monetary annotations", () => {
|
|
94
|
-
const VM_WITH_COST = {
|
|
95
|
-
analysis: {
|
|
96
|
-
costRisk: "high",
|
|
97
|
-
estimatedMonthlySavings: { amount: 29.94, currency: "EUR" },
|
|
98
|
-
reason: "No tags found. VM is deallocated.",
|
|
99
|
-
suspectedUnused: true,
|
|
100
|
-
},
|
|
101
|
-
resource: {
|
|
102
|
-
id: "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Compute/virtualMachines/vm-x",
|
|
103
|
-
name: "vm-x",
|
|
104
|
-
type: "Microsoft.Compute/virtualMachines",
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
const ADVISOR_WITH_SAVINGS = {
|
|
108
|
-
analysis: {
|
|
109
|
-
costRisk: "medium",
|
|
110
|
-
reason: "Advisor recommends a reservation.",
|
|
111
|
-
suspectedUnused: true,
|
|
112
|
-
},
|
|
113
|
-
findings: [
|
|
114
|
-
{
|
|
115
|
-
category: "cost",
|
|
116
|
-
code: "advisor.reservation",
|
|
117
|
-
estimatedMonthlySavings: { amount: 12.34, currency: "EUR" },
|
|
118
|
-
reason: "Advisor recommends a reservation.",
|
|
119
|
-
resourceId: "/subscriptions/sub1/providers/Microsoft.Advisor/recommendations/rec-1",
|
|
120
|
-
severity: "medium",
|
|
121
|
-
source: "advisor",
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
resource: {
|
|
125
|
-
id: "/subscriptions/sub1/providers/Microsoft.Advisor/recommendations/rec-1",
|
|
126
|
-
name: "rec-1",
|
|
127
|
-
type: "Microsoft.Advisor/recommendations",
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
it("renders the resource monthly cost ONCE as a header annotation, not on each finding", async () => {
|
|
131
|
-
await generateReport([VM_WITH_COST], "lint");
|
|
132
|
-
const output = allLogs(logSpy);
|
|
133
|
-
// header line contains the cost-at-risk label
|
|
134
|
-
expect(output).toMatch(/cost at risk:.*29[.,]94/);
|
|
135
|
-
// exactly one occurrence — must NOT appear next to each finding
|
|
136
|
-
const matches = output.match(/29[.,]94/g) ?? [];
|
|
137
|
-
// 1× header + 1× summary trailer = 2 occurrences; the per-finding line must not carry it
|
|
138
|
-
expect(matches.length).toBe(2);
|
|
139
|
-
});
|
|
140
|
-
it("does not attach the resource cost to the 'No tags found' finding line", async () => {
|
|
141
|
-
await generateReport([VM_WITH_COST], "lint");
|
|
142
|
-
const findingLines = logSpy.mock.calls
|
|
143
|
-
.map((c) => String(c[0]))
|
|
144
|
-
.filter((l) => l.includes("No tags found"));
|
|
145
|
-
expect(findingLines).toHaveLength(1);
|
|
146
|
-
expect(findingLines[0]).not.toMatch(/29[.,]94/);
|
|
147
|
-
});
|
|
148
|
-
it("uses the 'Estimated monthly cost at risk' label in the summary trailer", async () => {
|
|
149
|
-
await generateReport([VM_WITH_COST], "lint");
|
|
150
|
-
const output = allLogs(logSpy);
|
|
151
|
-
expect(output).toContain("Estimated monthly cost at risk");
|
|
152
|
-
// The old, misleading "Estimated monthly savings (custom)" label is gone
|
|
153
|
-
expect(output).not.toMatch(/Estimated monthly savings:\s*€/);
|
|
154
|
-
});
|
|
155
|
-
it("renders Advisor savings separately from custom cost at risk", async () => {
|
|
156
|
-
await generateReport([VM_WITH_COST, ADVISOR_WITH_SAVINGS], "lint");
|
|
157
|
-
const output = allLogs(logSpy);
|
|
158
|
-
expect(output).toMatch(/cost at risk:.*29[.,]94/);
|
|
159
|
-
expect(output).toMatch(/saving:.*12[.,]34/);
|
|
160
|
-
expect(output).toContain("Estimated monthly cost at risk (custom)");
|
|
161
|
-
expect(output).toContain("Estimated monthly savings (advisor)");
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
describe("generateReport — table format", () => {
|
|
166
|
-
let logSpy;
|
|
167
|
-
beforeEach(() => {
|
|
168
|
-
logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
169
|
-
});
|
|
170
|
-
afterEach(() => {
|
|
171
|
-
vi.restoreAllMocks();
|
|
172
|
-
});
|
|
173
|
-
it("renders without throwing for an empty report", async () => {
|
|
174
|
-
await expect(generateReport([], "table")).resolves.toBeUndefined();
|
|
175
|
-
// Table is always printed; the summary line ("0 issues found") follows.
|
|
176
|
-
expect(logSpy.mock.calls.length).toBeGreaterThanOrEqual(1);
|
|
177
|
-
const output = logSpy.mock.calls
|
|
178
|
-
.map((c) => String(c[0]))
|
|
179
|
-
.join("\n");
|
|
180
|
-
expect(output).toContain("0 issues found");
|
|
181
|
-
});
|
|
182
|
-
it("includes resource name and reason in the rendered table", async () => {
|
|
183
|
-
await generateReport([HIGH_ENTRY], "table");
|
|
184
|
-
const output = logSpy.mock.calls
|
|
185
|
-
.map((c) => String(c[0]))
|
|
186
|
-
.join("\n");
|
|
187
|
-
expect(output).toContain("vm-high");
|
|
188
|
-
expect(output).toContain("VM is deallocated");
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
//# sourceMappingURL=report.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"report.test.js","sourceRoot":"","sources":["../../../src/azure/__tests__/report.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAIzE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,8EAA8E;AAE9E,SAAS,SAAS,CAChB,EAAU,EACV,QAAmC,EACnC,MAAc,EACd,eAAe,GAAG,IAAI;IAEtB,OAAO;QACL,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE;QAC/C,QAAQ,EAAE;YACR,EAAE;YACF,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS;YACtC,IAAI,EAAE,mCAAmC;SAC1C;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,GAAG,SAAS,CAC1B,4FAA4F,EAC5F,MAAM,EACN,+CAA+C,CAChD,CAAC;AAEF,MAAM,YAAY,GAAG,SAAS,CAC5B,8FAA8F,EAC9F,QAAQ,EACR,gBAAgB,CACjB,CAAC;AAEF,MAAM,SAAS,GAAG,SAAS,CACzB,2FAA2F,EAC3F,KAAK,EACL,yBAAyB,EACzB,KAAK,CACN,CAAC;AAEF,8EAA8E;AAE9E,SAAS,OAAO,CAAC,GAAgC;IAC/C,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,8EAA8E;AAE9E,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,IAAI,MAAmC,CAAC;IAExC,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,eAAe,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,cAAc,CAAC,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,cAAc,CAAC,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,6CAA6C;QAC7C,MAAM,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjE,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACrE,qEAAqE;QACrE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,cAAc,CAAC,CAAC,UAAU,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,cAAc,CAAC,CAAC,UAAU,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,2EAA2E;QAC3E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,cAAc,CAAC,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,yCAAyC;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,MAAM,YAAY,GAAgC;YAChD,QAAQ,EAAE;gBACR,QAAQ,EAAE,MAAM;gBAChB,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE;gBAC3D,MAAM,EAAE,mCAAmC;gBAC3C,eAAe,EAAE,IAAI;aACtB;YACD,QAAQ,EAAE;gBACR,EAAE,EAAE,yFAAyF;gBAC7F,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,mCAAmC;aAC1C;SACF,CAAC;QACF,MAAM,oBAAoB,GAAgC;YACxD,QAAQ,EAAE;gBACR,QAAQ,EAAE,QAAQ;gBAClB,MAAM,EAAE,mCAAmC;gBAC3C,eAAe,EAAE,IAAI;aACtB;YACD,QAAQ,EAAE;gBACR;oBACE,QAAQ,EAAE,MAAM;oBAChB,IAAI,EAAE,qBAAqB;oBAC3B,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3D,MAAM,EAAE,mCAAmC;oBAC3C,UAAU,EACR,uEAAuE;oBACzE,QAAQ,EAAE,QAAQ;oBAClB,MAAM,EAAE,SAAS;iBAClB;aACF;YACD,QAAQ,EAAE;gBACR,EAAE,EAAE,uEAAuE;gBAC3E,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,mCAAmC;aAC1C;SACF,CAAC;QAEF,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;YAClG,MAAM,cAAc,CAAC,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/B,8CAA8C;YAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;YAClD,gEAAgE;YAChE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAChD,yFAAyF;YACzF,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;YACrF,MAAM,cAAc,CAAC,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK;iBACnC,GAAG,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;iBACnC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;YACtF,MAAM,cAAc,CAAC,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;YAC3D,yEAAyE;YACzE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,cAAc,CAAC,CAAC,YAAY,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;YACnE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;YAClD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;YACpE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,IAAI,MAAmC,CAAC;IAExC,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,eAAe,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QACnE,wEAAwE;QACxE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK;aAC7B,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK;aAC7B,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for matchesTags() — verifies AND-logic tag filtering:
|
|
3
|
-
* 1. No filter (undefined/empty) → always include the resource.
|
|
4
|
-
* 2. Exact key-value match → include.
|
|
5
|
-
* 3. Key missing on resource → exclude.
|
|
6
|
-
* 4. Key present but wrong value → exclude.
|
|
7
|
-
* 5. Multiple tags: all match → include; any mismatch → exclude.
|
|
8
|
-
*
|
|
9
|
-
* Tests for getMetric() cache behaviour:
|
|
10
|
-
* 6. resetMetricsCache() clears state between runs.
|
|
11
|
-
* 7. Concurrent calls for the same key coalesce into one network call.
|
|
12
|
-
* 8. A failed call is cached as a fulfilled null result (not retried silently).
|
|
13
|
-
*/
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=utils.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../../src/azure/__tests__/utils.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for matchesTags() — verifies AND-logic tag filtering:
|
|
3
|
-
* 1. No filter (undefined/empty) → always include the resource.
|
|
4
|
-
* 2. Exact key-value match → include.
|
|
5
|
-
* 3. Key missing on resource → exclude.
|
|
6
|
-
* 4. Key present but wrong value → exclude.
|
|
7
|
-
* 5. Multiple tags: all match → include; any mismatch → exclude.
|
|
8
|
-
*
|
|
9
|
-
* Tests for getMetric() cache behaviour:
|
|
10
|
-
* 6. resetMetricsCache() clears state between runs.
|
|
11
|
-
* 7. Concurrent calls for the same key coalesce into one network call.
|
|
12
|
-
* 8. A failed call is cached as a fulfilled null result (not retried silently).
|
|
13
|
-
*/
|
|
14
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
15
|
-
import { _metricsCacheSize, getMetric, matchesTags, resetMetricsCache, } from "../utils.js";
|
|
16
|
-
function makeResource(tags) {
|
|
17
|
-
return { id: "r1", name: "res", tags };
|
|
18
|
-
}
|
|
19
|
-
describe("matchesTags", () => {
|
|
20
|
-
describe("when no filter is provided", () => {
|
|
21
|
-
it("returns true for undefined filterTags", () => {
|
|
22
|
-
expect(matchesTags(makeResource({ env: "prod" }), undefined)).toBe(true);
|
|
23
|
-
});
|
|
24
|
-
it("returns true for empty Map", () => {
|
|
25
|
-
expect(matchesTags(makeResource({ env: "prod" }), new Map())).toBe(true);
|
|
26
|
-
});
|
|
27
|
-
it("returns true even when resource has no tags", () => {
|
|
28
|
-
expect(matchesTags(makeResource(), undefined)).toBe(true);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
describe("single tag filter", () => {
|
|
32
|
-
it("returns true when tag key and value match exactly", () => {
|
|
33
|
-
expect(matchesTags(makeResource({ env: "prod" }), new Map([["env", "prod"]]))).toBe(true);
|
|
34
|
-
});
|
|
35
|
-
it("returns false when tag key is missing from resource", () => {
|
|
36
|
-
expect(matchesTags(makeResource({ app: "myapp" }), new Map([["env", "prod"]]))).toBe(false);
|
|
37
|
-
});
|
|
38
|
-
it("returns false when tag key exists but value differs", () => {
|
|
39
|
-
expect(matchesTags(makeResource({ env: "dev" }), new Map([["env", "prod"]]))).toBe(false);
|
|
40
|
-
});
|
|
41
|
-
it("returns false when resource has no tags at all", () => {
|
|
42
|
-
expect(matchesTags(makeResource(), new Map([["env", "prod"]]))).toBe(false);
|
|
43
|
-
});
|
|
44
|
-
it("is case-sensitive for tag values", () => {
|
|
45
|
-
expect(matchesTags(makeResource({ env: "Prod" }), new Map([["env", "prod"]]))).toBe(false);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
describe("multiple tag filters (AND logic)", () => {
|
|
49
|
-
it("returns true when all filter tags match", () => {
|
|
50
|
-
const resource = makeResource({
|
|
51
|
-
env: "prod",
|
|
52
|
-
region: "italy",
|
|
53
|
-
team: "dx",
|
|
54
|
-
});
|
|
55
|
-
expect(matchesTags(resource, new Map([
|
|
56
|
-
["env", "prod"],
|
|
57
|
-
["team", "dx"],
|
|
58
|
-
]))).toBe(true);
|
|
59
|
-
});
|
|
60
|
-
it("returns false when one of the filter tags is missing", () => {
|
|
61
|
-
const resource = makeResource({ env: "prod" });
|
|
62
|
-
expect(matchesTags(resource, new Map([
|
|
63
|
-
["env", "prod"],
|
|
64
|
-
["team", "dx"],
|
|
65
|
-
]))).toBe(false);
|
|
66
|
-
});
|
|
67
|
-
it("returns false when one of the filter tags has the wrong value", () => {
|
|
68
|
-
const resource = makeResource({ env: "prod", team: "backend" });
|
|
69
|
-
expect(matchesTags(resource, new Map([
|
|
70
|
-
["env", "prod"],
|
|
71
|
-
["team", "dx"],
|
|
72
|
-
]))).toBe(false);
|
|
73
|
-
});
|
|
74
|
-
it("returns false when both filter tags have wrong values", () => {
|
|
75
|
-
const resource = makeResource({ env: "dev", team: "backend" });
|
|
76
|
-
expect(matchesTags(resource, new Map([
|
|
77
|
-
["env", "prod"],
|
|
78
|
-
["team", "dx"],
|
|
79
|
-
]))).toBe(false);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
// ── metrics cache ──────────────────────────────────────────────────────────
|
|
84
|
-
function makeFailingMonitorClient(calls = []) {
|
|
85
|
-
return {
|
|
86
|
-
metrics: {
|
|
87
|
-
list: vi.fn().mockImplementation(async () => {
|
|
88
|
-
calls.push(1);
|
|
89
|
-
throw new Error("network error");
|
|
90
|
-
}),
|
|
91
|
-
},
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
function makeMonitorClient(returnValue, calls = []) {
|
|
95
|
-
return {
|
|
96
|
-
metrics: {
|
|
97
|
-
list: vi.fn().mockImplementation(async () => {
|
|
98
|
-
calls.push(1);
|
|
99
|
-
if (returnValue === null) {
|
|
100
|
-
return { value: [] };
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
value: [
|
|
104
|
-
{
|
|
105
|
-
timeseries: [{ data: [{ average: returnValue }] }],
|
|
106
|
-
},
|
|
107
|
-
],
|
|
108
|
-
};
|
|
109
|
-
}),
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
describe("getMetric — in-memory cache", () => {
|
|
114
|
-
beforeEach(() => {
|
|
115
|
-
resetMetricsCache();
|
|
116
|
-
});
|
|
117
|
-
afterEach(() => {
|
|
118
|
-
vi.restoreAllMocks();
|
|
119
|
-
});
|
|
120
|
-
it("resetMetricsCache clears all cached entries", async () => {
|
|
121
|
-
const calls = [];
|
|
122
|
-
const client = makeMonitorClient(42, calls);
|
|
123
|
-
await getMetric(client, "/res/1", "Percentage CPU", "Average", 7);
|
|
124
|
-
expect(_metricsCacheSize()).toBe(1);
|
|
125
|
-
resetMetricsCache();
|
|
126
|
-
expect(_metricsCacheSize()).toBe(0);
|
|
127
|
-
});
|
|
128
|
-
it("does not call the API a second time for the same key", async () => {
|
|
129
|
-
const calls = [];
|
|
130
|
-
const client = makeMonitorClient(10, calls);
|
|
131
|
-
await getMetric(client, "/res/1", "Percentage CPU", "Average", 7);
|
|
132
|
-
await getMetric(client, "/res/1", "Percentage CPU", "Average", 7);
|
|
133
|
-
expect(calls.length).toBe(1);
|
|
134
|
-
});
|
|
135
|
-
it("concurrent calls for the same key coalesce into one network call", async () => {
|
|
136
|
-
const calls = [];
|
|
137
|
-
const client = makeMonitorClient(5, calls);
|
|
138
|
-
await Promise.all([
|
|
139
|
-
getMetric(client, "/res/2", "Network In Total", "Average", 30),
|
|
140
|
-
getMetric(client, "/res/2", "Network In Total", "Average", 30),
|
|
141
|
-
getMetric(client, "/res/2", "Network In Total", "Average", 30),
|
|
142
|
-
]);
|
|
143
|
-
expect(calls.length).toBe(1);
|
|
144
|
-
});
|
|
145
|
-
it("different keys result in separate network calls", async () => {
|
|
146
|
-
const calls = [];
|
|
147
|
-
const client = makeMonitorClient(1, calls);
|
|
148
|
-
await getMetric(client, "/res/a", "Percentage CPU", "Average", 7);
|
|
149
|
-
await getMetric(client, "/res/b", "Percentage CPU", "Average", 7);
|
|
150
|
-
expect(calls.length).toBe(2);
|
|
151
|
-
});
|
|
152
|
-
it("returns null and caches the null result when no data points are available", async () => {
|
|
153
|
-
const calls = [];
|
|
154
|
-
const client = makeMonitorClient(null, calls);
|
|
155
|
-
const first = await getMetric(client, "/res/3", "Percentage CPU", "Average", 7);
|
|
156
|
-
const second = await getMetric(client, "/res/3", "Percentage CPU", "Average", 7);
|
|
157
|
-
expect(first).toBeNull();
|
|
158
|
-
expect(second).toBeNull();
|
|
159
|
-
expect(calls.length).toBe(1);
|
|
160
|
-
});
|
|
161
|
-
it("a failing call is cached and returns null on retry", async () => {
|
|
162
|
-
const calls = [];
|
|
163
|
-
const client = makeFailingMonitorClient(calls);
|
|
164
|
-
const first = await getMetric(client, "/res/4", "Percentage CPU", "Average", 7);
|
|
165
|
-
const second = await getMetric(client, "/res/4", "Percentage CPU", "Average", 7);
|
|
166
|
-
// Both calls return null (error is swallowed by getMetric)
|
|
167
|
-
expect(first).toBeNull();
|
|
168
|
-
expect(second).toBeNull();
|
|
169
|
-
// Only one actual network call despite two getMetric calls
|
|
170
|
-
expect(calls.length).toBe(1);
|
|
171
|
-
});
|
|
172
|
-
it("after resetMetricsCache the API is called again", async () => {
|
|
173
|
-
const calls = [];
|
|
174
|
-
const client = makeMonitorClient(7, calls);
|
|
175
|
-
await getMetric(client, "/res/5", "Percentage CPU", "Average", 7);
|
|
176
|
-
resetMetricsCache();
|
|
177
|
-
await getMetric(client, "/res/5", "Percentage CPU", "Average", 7);
|
|
178
|
-
expect(calls.length).toBe(2);
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
//# sourceMappingURL=utils.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../../src/azure/__tests__/utils.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the Azure Advisor subscription-level analyzer.
|
|
3
|
-
*
|
|
4
|
-
* We never touch a real Azure subscription: the analyzer is constructed
|
|
5
|
-
* with an injected client factory that returns a fake exposing only the
|
|
6
|
-
* `recommendations.list()` async iterator the analyzer relies on.
|
|
7
|
-
*/
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=advisor.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advisor.test.d.ts","sourceRoot":"","sources":["../../../../src/azure/analyzers/__tests__/advisor.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|