mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
test: expand coverage across jobs and tools (#380)
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
async function loadWorker() {
|
||||
vi.resetModules();
|
||||
|
||||
vi.doMock("node:fs/promises", () => ({
|
||||
mkdir: vi.fn(),
|
||||
readFile: vi.fn(),
|
||||
rm: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("@snapotter/shared", () => ({
|
||||
ANALYTICS_EVENTS: {},
|
||||
TOOLS: [],
|
||||
getBundleForTool: vi.fn(() => null),
|
||||
}));
|
||||
|
||||
vi.doMock("bullmq", () => ({
|
||||
UnrecoverableError: class UnrecoverableError extends Error {},
|
||||
Worker: vi.fn(() => ({
|
||||
on: vi.fn(),
|
||||
close: vi.fn().mockResolvedValue(undefined),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.doMock("drizzle-orm", () => ({
|
||||
eq: vi.fn(() => "eq"),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/config.js", () => ({
|
||||
env: {
|
||||
SCRATCH_PATH: "",
|
||||
JOB_TIMEOUT_LONG_S: 60,
|
||||
JOB_TIMEOUT_FAST_S: 15,
|
||||
},
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/db/index.js", () => ({
|
||||
db: {},
|
||||
schema: { jobs: {} },
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/lib/analytics.js", () => ({
|
||||
captureException: vi.fn(),
|
||||
trackEvent: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/lib/analytics-gate.js", () => ({
|
||||
analyticsEnabled: vi.fn(() => false),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/lib/env.js", () => ({
|
||||
resolveConcurrency: vi.fn(() => 2),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/lib/errors.js", () => ({
|
||||
friendlyError: vi.fn((message: string) => message),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/lib/logger.js", () => ({
|
||||
logger: {
|
||||
error: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/lib/metrics.js", () => ({
|
||||
jobDuration: { observe: vi.fn() },
|
||||
jobsTotal: { inc: vi.fn() },
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/lib/object-storage.js", () => ({
|
||||
getObjectBuffer: vi.fn(),
|
||||
putObject: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/routes/progress.js", () => ({
|
||||
publishEphemeral: vi.fn(),
|
||||
updateSingleFileProgress: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/routes/tool-factory.js", () => ({
|
||||
getToolConfig: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/jobs/ai-handlers.js", () => ({
|
||||
hasAiJobHandler: vi.fn(() => false),
|
||||
runAiToolJob: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/jobs/batch-progress.js", () => ({
|
||||
recordChildOutcome: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/jobs/cancel.js", () => ({
|
||||
registerCancelable: vi.fn(() => new AbortController()),
|
||||
unregisterCancelable: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/jobs/connection.js", () => ({
|
||||
createBullMQConnection: vi.fn(() => ({})),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/jobs/postprocess.js", () => ({
|
||||
autoSaveToLibrary: vi.fn(),
|
||||
buildOutputName: vi.fn(),
|
||||
generatePreview: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.doMock("../../../../apps/api/src/jobs/system-jobs.js", () => ({
|
||||
runSystemJob: vi.fn(),
|
||||
}));
|
||||
|
||||
return import("../../../../apps/api/src/jobs/worker.js");
|
||||
}
|
||||
|
||||
describe("worker result payload behavior", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("builds legacy download, preview, saved-file, and tool payload fields", async () => {
|
||||
const { buildLegacyResultPayload } = await loadWorker();
|
||||
|
||||
expect(
|
||||
buildLegacyResultPayload(
|
||||
{
|
||||
outputRefs: ["outputs/job-1/report final.pdf"],
|
||||
filename: "report final.pdf",
|
||||
contentType: "application/pdf",
|
||||
originalSize: 100,
|
||||
processedSize: 80,
|
||||
previewRef: "outputs/job-1/preview.png",
|
||||
savedFileId: "file-2",
|
||||
resultPayload: { pageCount: 3 },
|
||||
},
|
||||
"job-1",
|
||||
),
|
||||
).toEqual({
|
||||
jobId: "job-1",
|
||||
downloadUrl: "/api/v1/download/job-1/report%20final.pdf",
|
||||
previewUrl: "/api/v1/download/job-1/preview.png",
|
||||
originalSize: 100,
|
||||
processedSize: 80,
|
||||
savedFileId: "file-2",
|
||||
pageCount: 3,
|
||||
});
|
||||
});
|
||||
|
||||
it("omits optional legacy payload fields when the job result does not include them", async () => {
|
||||
const { buildLegacyResultPayload } = await loadWorker();
|
||||
|
||||
expect(
|
||||
buildLegacyResultPayload(
|
||||
{
|
||||
outputRefs: ["outputs/job-2/out.png"],
|
||||
filename: "out.png",
|
||||
contentType: "image/png",
|
||||
originalSize: 10,
|
||||
processedSize: 8,
|
||||
},
|
||||
"job-2",
|
||||
),
|
||||
).toEqual({
|
||||
jobId: "job-2",
|
||||
downloadUrl: "/api/v1/download/job-2/out.png",
|
||||
originalSize: 10,
|
||||
processedSize: 8,
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user