mirror of
https://github.com/immich-app/yucca.git
synced 2026-09-30 13:33:00 +08:00
fix(yucca sdk): tsconfig for api tests (#706)
fix(yucca sdk): tsconfig for api test: update lint issues in tests
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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}`;
|
||||
|
||||
|
||||
@@ -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: [],
|
||||
});
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { ImmichIntegration } from 'src/moduleConfig';
|
||||
import type { ResticRepository } from 'src/repositories/restic.repository';
|
||||
|
||||
export type RepositoryInterface<T extends object> = Pick<T, keyof T>;
|
||||
@@ -8,6 +9,7 @@ export const newResticRepositoryMock = (): jest.Mocked<RepositoryInterface<Resti
|
||||
backup: jest.fn(),
|
||||
restore: jest.fn(),
|
||||
snapshots: jest.fn().mockResolvedValue([]),
|
||||
snapshot: jest.fn(),
|
||||
stats: jest.fn().mockResolvedValue({ total_size: 0, snapshots_count: 0 }),
|
||||
forget: jest.fn(),
|
||||
forgetByPolicy: jest.fn().mockResolvedValue([]),
|
||||
@@ -17,3 +19,11 @@ export const newResticRepositoryMock = (): jest.Mocked<RepositoryInterface<Resti
|
||||
unlockAll: jest.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
export const newImmichHooksMock = (): jest.Mocked<ImmichIntegration['hooks']> => ({
|
||||
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' }),
|
||||
});
|
||||
|
||||
@@ -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],
|
||||
});
|
||||
|
||||
@@ -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<typeof Database>;
|
||||
resticMock: jest.Mocked<ResticRepository>;
|
||||
resticMock: jest.Mocked<RepositoryInterface<ResticRepository>>;
|
||||
backendId: string;
|
||||
statePath: string;
|
||||
backendPath: string;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src"
|
||||
},
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"noFallthroughCasesInSwitch": false,
|
||||
"rootDir": "src",
|
||||
"baseUrl": ".",
|
||||
"paths": { "src/*": ["src/*"] },
|
||||
"outDir": "dist",
|
||||
"types": ["@types/node", "@types/jest"]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user