151 lines
5.3 KiB
JavaScript
151 lines
5.3 KiB
JavaScript
import SettingsService from "@/services/system/SettingsService.js";
|
|
import ApiError from "@/utils/ApiError.js";
|
|
|
|
// Mock models and mongoose db
|
|
jest.mock("@/db/models/index.js", () => ({
|
|
SystemSettings: {
|
|
findById: jest.fn(),
|
|
create: jest.fn(),
|
|
findOneAndUpdate: jest.fn(),
|
|
},
|
|
}));
|
|
import { SystemSettings } from "@/db/models/index.js";
|
|
|
|
jest.mock("mongoose", () => ({
|
|
connection: { db: null },
|
|
}));
|
|
import mongoose from "mongoose";
|
|
|
|
// Mock EmailService used via setEmailService
|
|
class MockEmailService {
|
|
rebuildTransport = jest.fn();
|
|
}
|
|
|
|
describe("SettingsService", () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe("get", () => {
|
|
it("creates default settings when missing and returns settings", async () => {
|
|
const select = (v) => ({ select: jest.fn().mockResolvedValue(v) });
|
|
SystemSettings.findById
|
|
.mockReturnValueOnce(select(null)) // initial check
|
|
.mockReturnValueOnce(select({ _id: "global", systemEmailHost: "" })); // after create
|
|
SystemSettings.create.mockResolvedValue({ _id: "global" });
|
|
|
|
const svc = new SettingsService();
|
|
const res = await svc.get();
|
|
expect(SystemSettings.create).toHaveBeenCalledWith({ _id: "global" });
|
|
expect(res).toEqual({ _id: "global", systemEmailHost: "" });
|
|
});
|
|
|
|
it("throws when settings cannot be loaded after create", async () => {
|
|
const select = (v) => ({ select: jest.fn().mockResolvedValue(v) });
|
|
SystemSettings.findById
|
|
.mockReturnValueOnce(select(null))
|
|
.mockReturnValueOnce(select(null));
|
|
SystemSettings.create.mockResolvedValue({ _id: "global" });
|
|
|
|
const svc = new SettingsService();
|
|
await expect(svc.get()).rejects.toMatchObject({
|
|
message: "Unable to load system settings",
|
|
status: 500,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("updateEmailSettings", () => {
|
|
it("sets provided fields, unsets others, rebuilds transport and returns settings", async () => {
|
|
const incoming = {
|
|
systemEmailHost: "smtp.example.com",
|
|
systemEmailPort: 587,
|
|
systemEmailSecure: false,
|
|
};
|
|
const updated = { _id: "global", ...incoming };
|
|
SystemSettings.findOneAndUpdate.mockResolvedValue(updated);
|
|
|
|
const svc = new SettingsService();
|
|
const email = new MockEmailService();
|
|
svc.setEmailService(email);
|
|
const res = await svc.updateEmailSettings(incoming);
|
|
|
|
expect(SystemSettings.findOneAndUpdate).toHaveBeenCalledWith(
|
|
{ _id: "global" },
|
|
expect.objectContaining({ $set: expect.any(Object), $unset: expect.any(Object) }),
|
|
expect.objectContaining({ new: true, upsert: true, setDefaultsOnInsert: true })
|
|
);
|
|
expect(email.rebuildTransport).toHaveBeenCalledWith(updated);
|
|
expect(res).toBe(updated);
|
|
});
|
|
|
|
it("throws when update returns no settings", async () => {
|
|
SystemSettings.findOneAndUpdate.mockResolvedValue(null);
|
|
const svc = new SettingsService();
|
|
const email = new MockEmailService();
|
|
svc.setEmailService(email);
|
|
await expect(svc.updateEmailSettings({})).rejects.toMatchObject({
|
|
message: "Unable to update system settings",
|
|
status: 500,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("updateRetentionPolicy", () => {
|
|
it("updates TTL via db.command and verifies expireAfterSeconds", async () => {
|
|
SystemSettings.findOneAndUpdate.mockResolvedValue({ _id: "global" });
|
|
const mockDb = {
|
|
command: jest
|
|
.fn()
|
|
// collMod
|
|
.mockResolvedValueOnce({ ok: 1 })
|
|
// listCollections
|
|
.mockResolvedValueOnce({ cursor: { firstBatch: [{ options: { expireAfterSeconds: 86400 } }] }, ok: 1 }),
|
|
};
|
|
mongoose.connection.db = mockDb;
|
|
|
|
const svc = new SettingsService();
|
|
const result = await svc.updateRetentionPolicy(1); // 1 day
|
|
expect(mockDb.command).toHaveBeenCalledWith({ collMod: "checks", expireAfterSeconds: 86400 });
|
|
expect(result).toBe(1);
|
|
});
|
|
|
|
it("throws when db not initialized", async () => {
|
|
SystemSettings.findOneAndUpdate.mockResolvedValue({ _id: "global" });
|
|
mongoose.connection.db = null;
|
|
const svc = new SettingsService();
|
|
await expect(svc.updateRetentionPolicy(1)).rejects.toMatchObject({
|
|
message: "Database not initialized",
|
|
status: 500,
|
|
});
|
|
});
|
|
|
|
it("throws when collMod fails", async () => {
|
|
SystemSettings.findOneAndUpdate.mockResolvedValue({ _id: "global" });
|
|
const mockDb = { command: jest.fn().mockResolvedValueOnce({ ok: 0 }) };
|
|
mongoose.connection.db = mockDb;
|
|
const svc = new SettingsService();
|
|
await expect(svc.updateRetentionPolicy(1)).rejects.toMatchObject({
|
|
message: "Failed to apply TTL to checks collection",
|
|
status: 500,
|
|
});
|
|
});
|
|
|
|
it("throws when TTL verification fails", async () => {
|
|
SystemSettings.findOneAndUpdate.mockResolvedValue({ _id: "global" });
|
|
const mockDb = {
|
|
command: jest
|
|
.fn()
|
|
.mockResolvedValueOnce({ ok: 1 })
|
|
.mockResolvedValueOnce({ cursor: { firstBatch: [{ options: { expireAfterSeconds: 30 } }] }, ok: 1 }),
|
|
};
|
|
mongoose.connection.db = mockDb;
|
|
const svc = new SettingsService();
|
|
await expect(svc.updateRetentionPolicy(1)).rejects.toMatchObject({
|
|
message: "TTL verification failed: expireAfterSeconds not applied",
|
|
status: 500,
|
|
});
|
|
});
|
|
});
|
|
});
|