Skip to content

Commit 7547d1d

Browse files
committed
update tests
1 parent 24d7ead commit 7547d1d

2 files changed

Lines changed: 100 additions & 18 deletions

File tree

server/test/helpers/InMemoryMonitorsRepository.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { IMonitorsRepository, TeamQueryConfig, SummaryConfig } from "../../src/repositories/monitors/IMonitorsRepository.ts";
2-
import type { Monitor, MonitorsSummary } from "../../src/types/index.ts";
2+
import type { Monitor, MonitorsSummary, CheckSnapshot } from "../../src/types/index.ts";
33

44
export class InMemoryMonitorsRepository implements IMonitorsRepository {
55
private monitors: Monitor[] = [];
@@ -49,6 +49,37 @@ export class InMemoryMonitorsRepository implements IMonitorsRepository {
4949
return { ...updated };
5050
}
5151

52+
async updateStatusWindowAndChecks(
53+
monitorId: string,
54+
teamId: string,
55+
status: boolean,
56+
checkSnapshot: CheckSnapshot,
57+
windowSize: number,
58+
maxRecentChecks: number,
59+
statusPatch?: Partial<Monitor>
60+
): Promise<Monitor> {
61+
const index = this.monitors.findIndex((m) => m.id === monitorId && m.teamId === teamId);
62+
if (index === -1) {
63+
throw new Error(`Monitor ${monitorId} not found`);
64+
}
65+
const monitor = this.monitors[index];
66+
monitor.statusWindow = monitor.statusWindow || [];
67+
monitor.statusWindow.push(status);
68+
while (monitor.statusWindow.length > windowSize) {
69+
monitor.statusWindow.shift();
70+
}
71+
monitor.recentChecks = monitor.recentChecks || [];
72+
monitor.recentChecks.push(checkSnapshot);
73+
while (monitor.recentChecks.length > maxRecentChecks) {
74+
monitor.recentChecks.shift();
75+
}
76+
if (statusPatch) {
77+
Object.assign(monitor, statusPatch);
78+
}
79+
this.monitors[index] = monitor;
80+
return { ...monitor };
81+
}
82+
5283
async togglePauseById(monitorId: string, teamId: string): Promise<Monitor> {
5384
const monitor = await this.findById(monitorId, teamId);
5485
const newStatus = monitor.status === "paused" ? "up" : "paused";

server/test/unit/services/statusService.test.ts

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,49 @@ const createBuffer = (): jest.Mocked<Pick<IBufferService, "addToBuffer">> => ({
1111
addToBuffer: jest.fn(),
1212
});
1313

14-
const createMonitorsRepo = () =>
15-
({
16-
findById: jest.fn(),
14+
const createMonitorsRepo = () => {
15+
const findById = jest.fn();
16+
const updateStatusWindowAndChecks = jest
17+
.fn()
18+
.mockImplementation(
19+
(
20+
_id: unknown,
21+
_tid: unknown,
22+
status: boolean,
23+
checkSnapshot: unknown,
24+
windowSize: number,
25+
maxRecentChecks: number,
26+
statusPatch?: Partial<Monitor>
27+
) => {
28+
// Grab the monitor that findById was configured to resolve with
29+
const monitor = findById.mock.results.at(-1)?.value;
30+
if (monitor && typeof monitor.then === "function") {
31+
return monitor.then((m: any) => {
32+
m.statusWindow = m.statusWindow || [];
33+
m.statusWindow.push(status);
34+
while (m.statusWindow.length > windowSize) {
35+
m.statusWindow.shift();
36+
}
37+
m.recentChecks = m.recentChecks || [];
38+
m.recentChecks.push(checkSnapshot);
39+
while (m.recentChecks.length > maxRecentChecks) {
40+
m.recentChecks.shift();
41+
}
42+
if (statusPatch) {
43+
Object.assign(m, statusPatch);
44+
}
45+
return { ...m };
46+
});
47+
}
48+
return Promise.reject(new Error("findById not mocked"));
49+
}
50+
);
51+
return {
52+
findById,
1753
updateById: jest.fn(),
18-
}) as unknown as jest.Mocked<IMonitorsRepository>;
54+
updateStatusWindowAndChecks,
55+
} as unknown as jest.Mocked<IMonitorsRepository>;
56+
};
1957

2058
const createMonitorStatsRepo = () =>
2159
({
@@ -233,11 +271,18 @@ describe("StatusService", () => {
233271
(monitorsRepository.findById as jest.Mock).mockResolvedValue(monitor);
234272
(monitorsRepository.updateById as jest.Mock).mockImplementation((_id: unknown, _tid: unknown, m: unknown) => Promise.resolve(m));
235273

236-
await service.updateMonitorStatus(makeStatusResponse({ status: false }), makeCheck());
274+
await service.updateMonitorStatus(makeStatusResponse({ status: false }), makeCheck({ status: false }));
237275

238-
// Window should have shifted: [true, true, true, true, false]
239-
expect(monitor.statusWindow).toHaveLength(5);
240-
expect(monitor.statusWindow[4]).toBe(false);
276+
// Atomic push should have been called with the correct status and window size
277+
expect(monitorsRepository.updateStatusWindowAndChecks).toHaveBeenCalledWith(
278+
"mon-1",
279+
"team-1",
280+
false,
281+
expect.any(Object),
282+
5,
283+
25,
284+
expect.objectContaining({ status: expect.any(String) })
285+
);
241286
});
242287

243288
it("pushes check snapshot to recentChecks and trims to 25", async () => {
@@ -542,7 +587,8 @@ describe("StatusService", () => {
542587

543588
expect(result.thresholdBreaches?.cpu).toBe(true);
544589
expect(result.thresholdBreaches?.memory).toBe(false);
545-
expect(monitor.cpuAlertCounter).toBe(0);
590+
const patch = (monitorsRepository.updateStatusWindowAndChecks as jest.Mock).mock.calls.at(-1)?.[6];
591+
expect(patch.cpuAlertCounter).toBe(0);
546592
expect(result.statusChanged).toBe(true);
547593
expect(result.monitor.status).toBe("breached");
548594
});
@@ -557,7 +603,8 @@ describe("StatusService", () => {
557603
const result = await service.updateMonitorStatus(response, makeCheck());
558604

559605
expect(result.thresholdBreaches?.memory).toBe(true);
560-
expect(monitor.memoryAlertCounter).toBe(0);
606+
const patch = (monitorsRepository.updateStatusWindowAndChecks as jest.Mock).mock.calls.at(-1)?.[6];
607+
expect(patch.memoryAlertCounter).toBe(0);
561608
expect(result.monitor.status).toBe("breached");
562609
});
563610

@@ -573,7 +620,8 @@ describe("StatusService", () => {
573620
const result = await service.updateMonitorStatus(response, makeCheck());
574621

575622
expect(result.thresholdBreaches?.disk).toBe(true);
576-
expect(monitor.diskAlertCounter).toBe(0);
623+
const patch = (monitorsRepository.updateStatusWindowAndChecks as jest.Mock).mock.calls.at(-1)?.[6];
624+
expect(patch.diskAlertCounter).toBe(0);
577625
expect(result.monitor.status).toBe("breached");
578626
});
579627

@@ -589,7 +637,8 @@ describe("StatusService", () => {
589637
const result = await service.updateMonitorStatus(response, makeCheck());
590638

591639
expect(result.thresholdBreaches?.temp).toBe(true);
592-
expect(monitor.tempAlertCounter).toBe(0);
640+
const patch = (monitorsRepository.updateStatusWindowAndChecks as jest.Mock).mock.calls.at(-1)?.[6];
641+
expect(patch.tempAlertCounter).toBe(0);
593642
expect(result.monitor.status).toBe("breached");
594643
});
595644

@@ -609,10 +658,11 @@ describe("StatusService", () => {
609658
} as any);
610659
await service.updateMonitorStatus(response, makeCheck());
611660

612-
expect(monitor.cpuAlertCounter).toBe(5);
613-
expect(monitor.memoryAlertCounter).toBe(5);
614-
expect(monitor.diskAlertCounter).toBe(5);
615-
expect(monitor.tempAlertCounter).toBe(5);
661+
const patch = (monitorsRepository.updateStatusWindowAndChecks as jest.Mock).mock.calls.at(-1)?.[6];
662+
expect(patch.cpuAlertCounter).toBe(5);
663+
expect(patch.memoryAlertCounter).toBe(5);
664+
expect(patch.diskAlertCounter).toBe(5);
665+
expect(patch.tempAlertCounter).toBe(5);
616666
});
617667

618668
it("stays breached without statusChanged when already breached and counter still at 0", async () => {
@@ -841,7 +891,8 @@ describe("StatusService", () => {
841891
const response = makeHardwareResponse({ data: { cpu: { usage_percent: 0.9 }, memory: { usage_percent: 0.1 }, disk: [], host: {} } } as any);
842892
const result = await service.updateMonitorStatus(response, makeCheck());
843893

844-
expect(monitor.cpuAlertCounter).toBe(2);
894+
const patch = (monitorsRepository.updateStatusWindowAndChecks as jest.Mock).mock.calls.at(-1)?.[6];
895+
expect(patch.cpuAlertCounter).toBe(2);
845896
expect(result.thresholdBreaches?.cpu).toBe(true);
846897
expect(result.statusChanged).toBe(false);
847898
expect(result.monitor.status).toBe("up");

0 commit comments

Comments
 (0)