test: fix impossible test scenarios

This commit is contained in:
Nicolas Meienberger
2026-02-16 23:20:33 +01:00
parent 11efe87b2e
commit 7bcf380198
5 changed files with 43 additions and 11 deletions

View File

@@ -12,6 +12,7 @@ import * as context from "~/server/core/request-context";
import * as spawnModule from "~/server/utils/spawn";
import { restic } from "~/server/utils/restic";
import { NotFoundError, BadRequestError } from "http-errors-enhanced";
import { scheduleQueries } from "../backups.queries";
const resticBackupMock = mock(() => Promise.resolve({ exitCode: 0, summary: generateBackupOutput(), error: "" }));
const resticForgetMock = mock(() => Promise.resolve({ success: true, data: null }));
@@ -55,12 +56,21 @@ describe("backup execution - validation failures", () => {
test("should fail backup when volume does not exist", async () => {
// arrange
const volume = await createTestVolume();
const repository = await createTestRepository();
const schedule = await createTestBackupSchedule({
volumeId: 99999,
volumeId: volume.id,
repositoryId: repository.id,
});
const hydratedSchedule = await scheduleQueries.findById(schedule.id, TEST_ORG_ID);
expect(hydratedSchedule).toBeDefined();
const scheduleWithoutVolume = {
...hydratedSchedule!,
volume: null,
} as unknown as NonNullable<Awaited<ReturnType<typeof scheduleQueries.findById>>>;
spyOn(scheduleQueries, "findById").mockResolvedValueOnce(scheduleWithoutVolume);
// act
const result = await backupsExecutionService.validateBackupExecution(schedule.id);
@@ -76,11 +86,20 @@ describe("backup execution - validation failures", () => {
test("should fail backup when repository does not exist", async () => {
// arrange
const volume = await createTestVolume();
const repository = await createTestRepository();
const schedule = await createTestBackupSchedule({
volumeId: volume.id,
repositoryId: "non-existent-repo",
repositoryId: repository.id,
});
const hydratedSchedule = await scheduleQueries.findById(schedule.id, TEST_ORG_ID);
expect(hydratedSchedule).toBeDefined();
const scheduleWithoutRepository = {
...hydratedSchedule!,
repository: null,
} as unknown as NonNullable<Awaited<ReturnType<typeof scheduleQueries.findById>>>;
spyOn(scheduleQueries, "findById").mockResolvedValueOnce(scheduleWithoutRepository);
// act
const result = await backupsExecutionService.validateBackupExecution(schedule.id);
@@ -216,14 +235,13 @@ describe("retention policy - runForget", () => {
test("should throw NotFoundError when repository does not exist", async () => {
// arrange
const schedule = await createTestBackupSchedule({
repositoryId: "non-existent-repo",
retentionPolicy: {
keepHourly: 24,
},
});
// act & assert
expect(backupsExecutionService.runForget(schedule.id)).rejects.toThrow("Repository not found");
expect(backupsExecutionService.runForget(schedule.id, "non-existent-repo")).rejects.toThrow("Repository not found");
});
});

View File

@@ -3,6 +3,7 @@ import { scheduleQueries } from "../backups.queries";
import { createTestBackupSchedule } from "~/test/helpers/backup";
import { createTestVolume } from "~/test/helpers/volume";
import { createTestRepository } from "~/test/helpers/repository";
import { createTestOrganization } from "~/test/helpers/organization";
import { TEST_ORG_ID } from "~/test/helpers/organization";
import { faker } from "@faker-js/faker";
@@ -140,6 +141,7 @@ describe("scheduleQueries.findExecutable", () => {
test("should not return schedules from other organizations", async () => {
// arrange
const otherOrgId = faker.string.uuid();
await createTestOrganization({ id: otherOrgId });
const schedule = await createTestBackupSchedule({
volumeId: volume.id,
repositoryId: repository.id,

View File

@@ -236,7 +236,7 @@ describe("listSchedules", () => {
});
describe("cleanupOrphanedSchedules", () => {
test("should delete orphaned schedules and their mirror assignments", async () => {
test("should return zero when cascades already removed orphaned schedules", async () => {
const healthyVolume = await createTestVolume();
const healthyRepository = await createTestRepository();
const healthySchedule = await createTestBackupSchedule({
@@ -262,7 +262,7 @@ describe("cleanupOrphanedSchedules", () => {
const cleanupResult = await backupsService.cleanupOrphanedSchedules();
expect(cleanupResult.deletedSchedules).toBeGreaterThanOrEqual(1);
expect(cleanupResult.deletedSchedules).toBe(0);
const deletedSchedule = await db.query.backupSchedulesTable.findFirst({
where: { id: orphanSchedule.id },

View File

@@ -1,18 +1,29 @@
import { db } from "~/server/db/db";
import { faker } from "@faker-js/faker";
import { backupSchedulesTable, type BackupScheduleInsert } from "~/server/db/schema";
import { ensureTestOrganization, TEST_ORG_ID } from "./organization";
import { createTestOrganization, ensureTestOrganization, TEST_ORG_ID } from "./organization";
import { createTestVolume } from "./volume";
import { createTestRepository } from "./repository";
export const createTestBackupSchedule = async (overrides: Partial<BackupScheduleInsert> = {}) => {
await ensureTestOrganization();
const organizationId = overrides.organizationId ?? TEST_ORG_ID;
if (organizationId === TEST_ORG_ID) {
await ensureTestOrganization();
} else {
await createTestOrganization({ id: organizationId });
}
const volumeId = overrides.volumeId ?? (await createTestVolume({ organizationId })).id;
const repositoryId = overrides.repositoryId ?? (await createTestRepository({ organizationId })).id;
const backup: BackupScheduleInsert = {
name: faker.system.fileName(),
cronExpression: "0 0 * * *",
repositoryId: "repo_123",
volumeId: 1,
repositoryId,
volumeId,
shortId: faker.string.uuid(),
organizationId: TEST_ORG_ID,
organizationId,
...overrides,
};

View File

@@ -25,4 +25,5 @@ void mock.module("~/server/utils/crypto", () => ({
beforeAll(async () => {
const migrationsFolder = path.join(cwd(), "app", "drizzle");
migrate(db, { migrationsFolder });
db.run("PRAGMA foreign_keys = ON;");
});