From c473a911c40209bbf9f07ac5bac5446fd44fb28b Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Wed, 23 Sep 2026 12:17:28 +0100 Subject: [PATCH] fix(yucca sdk): tsconfig for api tests (#706) fix(yucca sdk): tsconfig for api test: update lint issues in tests --- eslint.config.mjs | 1 + .../repositories/config.repository.spec.ts | 6 ++--- .../test/bootstrap.integration-spec.ts | 3 ++- .../test/database.integration-spec.ts | 2 ++ .../test/integrations.integration-spec.ts | 25 +++++++++++-------- .../yucca-sdk/orchestration-api/test/mocks.ts | 10 ++++++++ .../test/schedule.integration-spec.ts | 17 ++++++------- .../orchestration-api/test/testUtils.ts | 4 +-- .../orchestration-api/tsconfig.build.json | 3 +++ .../yucca-sdk/orchestration-api/tsconfig.json | 3 ++- 10 files changed, 48 insertions(+), 26 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index d1bc147c..f56af74c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -50,6 +50,7 @@ export default typescriptEslint.config([ 'unicorn/import-style': 'off', 'unicorn/prefer-structured-clone': 'off', 'unicorn/no-for-loop': 'off', + 'unicorn/no-useless-undefined': ['error', { checkArguments: false }], '@typescript-eslint/await-thenable': 'error', '@typescript-eslint/no-misused-promises': 'error', 'require-await': 'off', diff --git a/packages/yucca-sdk/orchestration-api/src/repositories/config.repository.spec.ts b/packages/yucca-sdk/orchestration-api/src/repositories/config.repository.spec.ts index 8c673aa8..8cf46c64 100644 --- a/packages/yucca-sdk/orchestration-api/src/repositories/config.repository.spec.ts +++ b/packages/yucca-sdk/orchestration-api/src/repositories/config.repository.spec.ts @@ -8,7 +8,7 @@ describe(ConfigRepository.name, () => { selectFrom: jest.fn(() => ({ where: jest.fn(() => ({ select: jest.fn(() => ({ - executeTakeFirst: jest.fn().mockResolvedValue(), + executeTakeFirst: jest.fn(), })), })), })), @@ -32,8 +32,8 @@ describe(ConfigRepository.name, () => { }); it('falls back to global config and core count without placement', async () => { - const connections = jest.spyOn(yuccaWellKnown, 'getConnections').mockResolvedValue(); - const packSize = jest.spyOn(yuccaWellKnown, 'getPackSizeMib').mockResolvedValue(); + const connections = jest.spyOn(yuccaWellKnown, 'getConnections').mockResolvedValue(undefined); + const packSize = jest.spyOn(yuccaWellKnown, 'getPackSizeMib').mockResolvedValue(undefined); const repository = new ConfigRepository(db as never, { statePath: '/state' }, LoggingRepository.create()); await expect(repository.getResticOptions({ siteCode: null, storageClusterCode: null })).resolves.toEqual({ diff --git a/packages/yucca-sdk/orchestration-api/test/bootstrap.integration-spec.ts b/packages/yucca-sdk/orchestration-api/test/bootstrap.integration-spec.ts index 5323cdfc..23adc9ab 100644 --- a/packages/yucca-sdk/orchestration-api/test/bootstrap.integration-spec.ts +++ b/packages/yucca-sdk/orchestration-api/test/bootstrap.integration-spec.ts @@ -7,6 +7,7 @@ import { BootstrapRepository } from 'src/repositories/bootstrap.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; import { RepositoryRepository } from 'src/repositories/repository.repository'; import { RunHistoryRepository } from 'src/repositories/runHistory.repository'; +import { type RunType } from 'src/schema/tables/runHistory.table'; import { BootstrapService } from 'src/services/bootstrap.service'; import { createTestingModule, TestContext, waitFor } from './testUtils'; @@ -15,7 +16,7 @@ const apiSubmitStructuredLog = submitStructuredLog as jest.Mock; let ctx: TestContext; -const createInterruptedRun = async (type = TaskType.Backup) => { +const createInterruptedRun = async (type: RunType = TaskType.Backup) => { const repositoryId = randomUUID(); const remoteId = `remote-${repositoryId}`; diff --git a/packages/yucca-sdk/orchestration-api/test/database.integration-spec.ts b/packages/yucca-sdk/orchestration-api/test/database.integration-spec.ts index 3f604a2d..49d637e5 100644 --- a/packages/yucca-sdk/orchestration-api/test/database.integration-spec.ts +++ b/packages/yucca-sdk/orchestration-api/test/database.integration-spec.ts @@ -31,6 +31,7 @@ describe('Database', () => { const { schedule } = await scheduleService.createSchedule({ name: 'Snapshot Schedule', + paused: false, cron: '0 0 * * *', repositories: [repository.id], }); @@ -43,6 +44,7 @@ describe('Database', () => { await scheduleService.createSchedule({ name: 'Post-Snapshot Schedule', + paused: false, cron: '0 6 * * *', repositories: [], }); diff --git a/packages/yucca-sdk/orchestration-api/test/integrations.integration-spec.ts b/packages/yucca-sdk/orchestration-api/test/integrations.integration-spec.ts index 74a501c2..2c6772b0 100644 --- a/packages/yucca-sdk/orchestration-api/test/integrations.integration-spec.ts +++ b/packages/yucca-sdk/orchestration-api/test/integrations.integration-spec.ts @@ -4,7 +4,8 @@ import { RepositoryPathRepository } from 'src/repositories/repositoryPath.reposi import { IntegrationsService } from 'src/services/integrations.service'; import { RepositoryService } from 'src/services/repository.service'; import { ScheduleService } from 'src/services/schedule.service'; -import { createRemoteRepository, createTestingModule, TestContext } from './testUtils'; +import { newImmichHooksMock } from './mocks'; +import { createTestingModule, TestContext } from './testUtils'; let ctx: TestContext; @@ -42,6 +43,7 @@ describe('Integrations', () => { dataPath: '/data/immich', dataFolders: ['upload', 'library'], libraries: [], + hooks: newImmichHooksMock(), }, }); @@ -79,6 +81,7 @@ describe('Integrations', () => { { id: 'lib-1', name: 'Photos', importPaths: ['/mnt/photos'], exclusionPatterns: [] }, { id: 'lib-2', name: 'Videos', importPaths: ['/mnt/videos'], exclusionPatterns: [] }, ], + hooks: newImmichHooksMock(), }, }); @@ -119,6 +122,7 @@ describe('Integrations', () => { dataPath: '/data/immich', dataFolders: ['upload'], libraries: [], + hooks: newImmichHooksMock(), }, }); @@ -155,10 +159,7 @@ describe('Integrations', () => { moduleConfig.update({ immichIntegration: undefined }); }); - const hooks = { - getImmichDatabaseDumpConfig: jest.fn().mockResolvedValue({ enabled: true, keepLastAmount: 14 }), - configureImmichDatabaseDump: jest.fn(), - }; + const hooks = newImmichHooksMock(); it('pauses and resumes the managed schedule', async () => { const moduleConfig = ctx.module.get(ModuleConfigRepository); const integrationsService = ctx.module.get(IntegrationsService); @@ -170,7 +171,7 @@ describe('Integrations', () => { dataPath: '/data/immich', dataFolders: ['upload'], libraries: [], - hooks: hooks as never, + hooks, }, }); @@ -192,7 +193,8 @@ describe('Integrations', () => { return schedules.find((entry) => entry.id === integration?.scheduleId); }; - expect((await getSchedule())?.paused).toBe(false); + const initialSchedule = await getSchedule(); + expect(initialSchedule?.paused).toBe(false); const status = await integrationsService.getImmichBackupStatus(); expect(status.databaseDump).toEqual({ enabled: true, keepLastAmount: 14 }); @@ -202,15 +204,18 @@ describe('Integrations', () => { expect(status.databaseDumpWarningIgnored).toBe(false); await integrationsService.ignoreImmichDatabaseDumpWarning(); - expect((await integrationsService.getImmichBackupStatus()).databaseDumpWarningIgnored).toBe(true); + const ignoredStatus = await integrationsService.getImmichBackupStatus(); + expect(ignoredStatus.databaseDumpWarningIgnored).toBe(true); await integrationsService.configureImmichIntegration({ ...configuration, paused: true }); - expect((await getSchedule())?.paused).toBe(true); + const pausedSchedule = await getSchedule(); + expect(pausedSchedule?.paused).toBe(true); await integrationsService.configureImmichIntegration({ ...configuration, paused: false }); - expect((await getSchedule())?.paused).toBe(false); + const resumedSchedule = await getSchedule(); + expect(resumedSchedule?.paused).toBe(false); await immichRepository.delete(); moduleConfig.update({ immichIntegration: undefined }); diff --git a/packages/yucca-sdk/orchestration-api/test/mocks.ts b/packages/yucca-sdk/orchestration-api/test/mocks.ts index 27b05e92..4a30631e 100644 --- a/packages/yucca-sdk/orchestration-api/test/mocks.ts +++ b/packages/yucca-sdk/orchestration-api/test/mocks.ts @@ -1,3 +1,4 @@ +import type { ImmichIntegration } from 'src/moduleConfig'; import type { ResticRepository } from 'src/repositories/restic.repository'; export type RepositoryInterface = Pick; @@ -8,6 +9,7 @@ export const newResticRepositoryMock = (): jest.Mocked => ({ + createDatabaseBackup: jest.fn().mockResolvedValue('dump.sql.gz'), + cleanupDatabaseBackups: jest.fn(), + getImmichDatabaseDumpConfig: jest.fn().mockResolvedValue({ enabled: true, keepLastAmount: 14 }), + configureImmichDatabaseDump: jest.fn(), + enterMaintenanceRollback: jest.fn().mockResolvedValue({ jwt: 'jwt' }), +}); diff --git a/packages/yucca-sdk/orchestration-api/test/schedule.integration-spec.ts b/packages/yucca-sdk/orchestration-api/test/schedule.integration-spec.ts index d19ed6ed..92f6009b 100644 --- a/packages/yucca-sdk/orchestration-api/test/schedule.integration-spec.ts +++ b/packages/yucca-sdk/orchestration-api/test/schedule.integration-spec.ts @@ -32,6 +32,7 @@ describe('Schedule', () => { const { schedule } = await scheduleService.createSchedule({ name: 'Locked Schedule', + paused: false, cron: '0 0 1 1 *', repositories: [repository.id], }); @@ -49,6 +50,7 @@ describe('Schedule', () => { it('skips task creation when schedule has no repositories', async () => { const { schedule } = await ctx.module.get(ScheduleService).createSchedule({ name: 'Empty Schedule', + paused: false, cron: '0 0 1 1 *', repositories: [], }); @@ -85,6 +87,7 @@ describe('Schedule', () => { const { schedule } = await scheduleService.createSchedule({ name: 'Multi Schedule', + paused: false, cron: '0 0 1 1 *', repositories: [repo1.id, repo2.id], }); @@ -121,17 +124,11 @@ describe('Schedule', () => { ); ctx.resticMock.backup.mockReset(); - let callCount = 0; - ctx.resticMock.backup.mockImplementation(() => { - callCount++; - if (callCount === 1) { - return Promise.reject(new Error('Simulated backup failure')); - } - return Promise.resolve(); - }); + ctx.resticMock.backup.mockRejectedValueOnce(new Error('Simulated backup failure')); const { schedule } = await scheduleService.createSchedule({ name: 'Resilient Schedule', + paused: false, cron: '0 0 1 1 *', repositories: [failRepo.id, successRepo.id], }); @@ -140,7 +137,6 @@ describe('Schedule', () => { await new Promise((resolve) => setTimeout(resolve, 300)); - expect(callCount).toBe(2); expect(ctx.resticMock.backup).toHaveBeenCalledTimes(2); ctx.resticMock.backup.mockReset(); @@ -171,6 +167,7 @@ describe('Schedule', () => { const { schedule } = await scheduleService.createSchedule({ name: 'Warn Schedule', + paused: false, cron: '0 0 1 1 *', repositories: [warnRepo.id], }); @@ -200,6 +197,7 @@ describe('Schedule', () => { const { schedule } = await scheduleService.createSchedule({ name: 'Ordering Schedule', + paused: false, cron: '0 0 1 1 *', repositories: [existing.id], }); @@ -223,6 +221,7 @@ describe('Schedule', () => { const { schedule } = await scheduleService.createSchedule({ name: 'Immich Schedule', + paused: false, cron: '0 2 * * *', repositories: [repository.id], }); diff --git a/packages/yucca-sdk/orchestration-api/test/testUtils.ts b/packages/yucca-sdk/orchestration-api/test/testUtils.ts index 48ff19ed..01fab8ec 100644 --- a/packages/yucca-sdk/orchestration-api/test/testUtils.ts +++ b/packages/yucca-sdk/orchestration-api/test/testUtils.ts @@ -16,7 +16,7 @@ import { ModuleConfigProvider } from 'src/moduleConfig'; import { controllers, repositories, services } from 'src/orchestrationApi.module'; import { BackendRepository } from 'src/repositories/backend.repository'; import { ResticRepository } from 'src/repositories/restic.repository'; -import { newResticRepositoryMock } from './mocks'; +import { newResticRepositoryMock, RepositoryInterface } from './mocks'; type GatewayListener = (event: GatewayEvent) => void; @@ -49,7 +49,7 @@ export interface TestContext { gateway: EventsGateway; events: TestEventBus; database: InstanceType; - resticMock: jest.Mocked; + resticMock: jest.Mocked>; backendId: string; statePath: string; backendPath: string; diff --git a/packages/yucca-sdk/orchestration-api/tsconfig.build.json b/packages/yucca-sdk/orchestration-api/tsconfig.build.json index 64f86c6b..f56a05c2 100644 --- a/packages/yucca-sdk/orchestration-api/tsconfig.build.json +++ b/packages/yucca-sdk/orchestration-api/tsconfig.build.json @@ -1,4 +1,7 @@ { "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "src" + }, "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] } diff --git a/packages/yucca-sdk/orchestration-api/tsconfig.json b/packages/yucca-sdk/orchestration-api/tsconfig.json index 7a4090c4..2f456112 100644 --- a/packages/yucca-sdk/orchestration-api/tsconfig.json +++ b/packages/yucca-sdk/orchestration-api/tsconfig.json @@ -22,7 +22,8 @@ "noImplicitAny": true, "strictBindCallApply": false, "noFallthroughCasesInSwitch": false, - "rootDir": "src", + "baseUrl": ".", + "paths": { "src/*": ["src/*"] }, "outDir": "dist", "types": ["@types/node", "@types/jest"] },