mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
120 lines
3.3 KiB
TypeScript
120 lines
3.3 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|||
|
|
|
||
|
|
const isFeatureEnabledMock = vi.hoisted(() => vi.fn());
|
||
|
|
const selectMock = vi.hoisted(() => vi.fn());
|
||
|
|
const deleteMock = vi.hoisted(() => vi.fn());
|
||
|
|
const upsertSettingMock = vi.hoisted(() => vi.fn());
|
||
|
|
const mkdirMock = vi.hoisted(() => vi.fn());
|
||
|
|
|
||
|
|
function queryChain<T>(result: T) {
|
||
|
|
const chain = {
|
||
|
|
from: vi.fn(() => chain),
|
||
|
|
where: vi.fn(() => Promise.resolve(result)),
|
||
|
|
};
|
||
|
|
return chain;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function loadAuditArchive() {
|
||
|
|
vi.resetModules();
|
||
|
|
isFeatureEnabledMock.mockReset();
|
||
|
|
selectMock.mockReset();
|
||
|
|
deleteMock.mockReset();
|
||
|
|
upsertSettingMock.mockReset();
|
||
|
|
mkdirMock.mockReset();
|
||
|
|
|
||
|
|
vi.doMock("node:fs/promises", () => ({
|
||
|
|
mkdir: mkdirMock,
|
||
|
|
stat: vi.fn(),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.doMock("node:fs", () => ({
|
||
|
|
createWriteStream: vi.fn(),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.doMock("node:stream/promises", () => ({
|
||
|
|
pipeline: vi.fn(),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.doMock("drizzle-orm", () => ({
|
||
|
|
eq: vi.fn(() => "eq"),
|
||
|
|
lt: vi.fn(() => "lt"),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.doMock("@snapotter/enterprise", () => ({
|
||
|
|
isFeatureEnabled: isFeatureEnabledMock,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.doMock("../../../../apps/api/src/config.js", () => ({
|
||
|
|
env: { FILES_STORAGE_PATH: "/data/files" },
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.doMock("../../../../apps/api/src/db/index.js", () => ({
|
||
|
|
db: {
|
||
|
|
select: selectMock,
|
||
|
|
delete: deleteMock,
|
||
|
|
},
|
||
|
|
schema: {
|
||
|
|
settings: {
|
||
|
|
key: "settings.key",
|
||
|
|
value: "settings.value",
|
||
|
|
},
|
||
|
|
auditLog: {
|
||
|
|
createdAt: "auditLog.createdAt",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.doMock("../../../../apps/api/src/lib/settings-helpers.js", () => ({
|
||
|
|
upsertSetting: upsertSettingMock,
|
||
|
|
}));
|
||
|
|
|
||
|
|
return import("../../../../apps/api/src/jobs/audit-archive.js");
|
||
|
|
}
|
||
|
|
|
||
|
|
describe("audit archive job behavior", () => {
|
||
|
|
afterEach(() => {
|
||
|
|
vi.restoreAllMocks();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns before reading archive settings when the enterprise feature is disabled", async () => {
|
||
|
|
const { runAuditArchive } = await loadAuditArchive();
|
||
|
|
isFeatureEnabledMock.mockReturnValue(false);
|
||
|
|
|
||
|
|
await runAuditArchive();
|
||
|
|
|
||
|
|
expect(selectMock).not.toHaveBeenCalled();
|
||
|
|
expect(upsertSettingMock).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns when archive months is missing or disabled", async () => {
|
||
|
|
const { runAuditArchive } = await loadAuditArchive();
|
||
|
|
isFeatureEnabledMock.mockReturnValue(true);
|
||
|
|
selectMock.mockReturnValueOnce(queryChain([{ value: "0" }]));
|
||
|
|
|
||
|
|
await runAuditArchive();
|
||
|
|
|
||
|
|
expect(mkdirMock).not.toHaveBeenCalled();
|
||
|
|
expect(upsertSettingMock).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("clears archival state when there are no rows older than the boundary", async () => {
|
||
|
|
const deleteWhere = vi.fn().mockResolvedValue(undefined);
|
||
|
|
const { runAuditArchive } = await loadAuditArchive();
|
||
|
|
deleteMock.mockReturnValue({ where: deleteWhere });
|
||
|
|
isFeatureEnabledMock.mockReturnValue(true);
|
||
|
|
selectMock
|
||
|
|
.mockReturnValueOnce(queryChain([{ value: "1" }]))
|
||
|
|
.mockReturnValueOnce(queryChain([]))
|
||
|
|
.mockReturnValueOnce(queryChain([]));
|
||
|
|
|
||
|
|
await runAuditArchive();
|
||
|
|
|
||
|
|
expect(upsertSettingMock).toHaveBeenCalledWith(
|
||
|
|
"audit_archival_state",
|
||
|
|
expect.stringContaining('"state":"EXPORTING"'),
|
||
|
|
);
|
||
|
|
expect(mkdirMock).toHaveBeenCalledWith("/data/audit-archives", { recursive: true });
|
||
|
|
expect(deleteWhere).toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|