diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index d8804445d2..fb02aff2ff 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -4,6 +4,7 @@ name: immich-e2e x-server-build: &server-common image: immich-server:latest + container_name: immich-e2e-server build: context: ../ dockerfile: server/Dockerfile diff --git a/e2e/src/api/specs/audit.e2e-spec.ts b/e2e/src/api/specs/audit.e2e-spec.ts new file mode 100644 index 0000000000..073106e728 --- /dev/null +++ b/e2e/src/api/specs/audit.e2e-spec.ts @@ -0,0 +1,51 @@ +import { + deleteAssets, + getAuditFiles, + updateAsset, + type LoginResponseDto, +} from '@immich/sdk'; +import { apiUtils, asBearerAuth, dbUtils, fileUtils } from 'src/utils'; +import { beforeAll, describe, expect, it } from 'vitest'; + +describe('/audit', () => { + let admin: LoginResponseDto; + + beforeAll(async () => { + apiUtils.setup(); + await dbUtils.reset(); + await fileUtils.reset(); + + admin = await apiUtils.adminSetup(); + }); + + describe('GET :/file-report', () => { + it('excludes assets without issues from report', async () => { + const [trashedAsset, archivedAsset, _] = await Promise.all([ + apiUtils.createAsset(admin.accessToken), + apiUtils.createAsset(admin.accessToken), + apiUtils.createAsset(admin.accessToken), + ]); + + await Promise.all([ + deleteAssets( + { assetBulkDeleteDto: { ids: [trashedAsset.id] } }, + { headers: asBearerAuth(admin.accessToken) } + ), + updateAsset( + { + id: archivedAsset.id, + updateAssetDto: { isArchived: true }, + }, + { headers: asBearerAuth(admin.accessToken) } + ), + ]); + + const body = await getAuditFiles({ + headers: asBearerAuth(admin.accessToken), + }); + + expect(body.orphans).toHaveLength(0); + expect(body.extras).toHaveLength(0); + }); + }); +}); diff --git a/e2e/src/utils.ts b/e2e/src/utils.ts index a6374aff52..fbc0b43b31 100644 --- a/e2e/src/utils.ts +++ b/e2e/src/utils.ts @@ -17,14 +17,17 @@ import { updatePerson, } from '@immich/sdk'; import { BrowserContext } from '@playwright/test'; -import { spawn } from 'child_process'; +import { exec, spawn } from 'child_process'; import { randomBytes } from 'node:crypto'; import { access } from 'node:fs/promises'; import path from 'node:path'; +import { promisify } from 'node:util'; import pg from 'pg'; import { loginDto, signupDto } from 'src/fixtures'; import request from 'supertest'; +const execPromise = promisify(exec); + export const app = 'http://127.0.0.1:2283/api'; const directoryExists = (directory: string) => @@ -35,6 +38,9 @@ const directoryExists = (directory: string) => // TODO move test assets into e2e/assets export const testAssetDir = path.resolve(`./../server/test/assets/`); +const serverContainerName = 'immich-e2e-server'; +const uploadMediaDir = '/usr/src/app/upload/upload'; + if (!(await directoryExists(`${testAssetDir}/albums`))) { throw new Error( `Test assets not found. Please checkout https://github.com/immich-app/test-assets into ${testAssetDir} before testing` @@ -50,6 +56,14 @@ export const asKeyAuth = (key: string) => ({ 'x-api-key': key }); let client: pg.Client | null = null; +export const fileUtils = { + reset: async () => { + await execPromise( + `docker exec -i "${serverContainerName}" rm -R "${uploadMediaDir}"` + ); + }, +}; + export const dbUtils = { createFace: async ({ assetId, diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index 887b72e2cd..a7c003fad6 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -167,7 +167,7 @@ export class AuditService { `Found ${libraryFiles.size} original files, ${thumbFiles.size} thumbnails, ${videoFiles.size} encoded videos, ${profileFiles.size} profile files`, ); const pagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (options) => - this.assetRepository.getAll(options, { withDeleted: true }), + this.assetRepository.getAll(options, { withDeleted: true, withArchived: true }), ); let assetCount = 0;