mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 02:13:51 -04:00
fix(server): empty/restore trash (#7161)
* fix(server): empty/restore trash * add e2e tests * add e2e tests - part 2
This commit is contained in:
parent
69983ff83a
commit
0730b54ca9
@ -1,4 +1,4 @@
|
|||||||
import { AssetResponseDto } from '@app/domain';
|
import { AssetBulkDeleteDto, AssetResponseDto } from '@app/domain';
|
||||||
import { CreateAssetDto } from '@app/immich/api-v1/asset/dto/create-asset.dto';
|
import { CreateAssetDto } from '@app/immich/api-v1/asset/dto/create-asset.dto';
|
||||||
import { AssetFileUploadResponseDto } from '@app/immich/api-v1/asset/response-dto/asset-file-upload-response.dto';
|
import { AssetFileUploadResponseDto } from '@app/immich/api-v1/asset/response-dto/asset-file-upload-response.dto';
|
||||||
import { randomBytes } from 'node:crypto';
|
import { randomBytes } from 'node:crypto';
|
||||||
@ -74,4 +74,8 @@ export const assetApi = {
|
|||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
return body;
|
return body;
|
||||||
},
|
},
|
||||||
|
delete: async (server: any, accessToken: string, dto: AssetBulkDeleteDto) => {
|
||||||
|
const { status } = await request(server).delete('/asset').set('Authorization', `Bearer ${accessToken}`).send(dto);
|
||||||
|
expect(status).toBe(204);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@ import { libraryApi } from './library-api';
|
|||||||
import { partnerApi } from './partner-api';
|
import { partnerApi } from './partner-api';
|
||||||
import { serverInfoApi } from './server-info-api';
|
import { serverInfoApi } from './server-info-api';
|
||||||
import { sharedLinkApi } from './shared-link-api';
|
import { sharedLinkApi } from './shared-link-api';
|
||||||
|
import { trashApi } from './trash-api';
|
||||||
import { userApi } from './user-api';
|
import { userApi } from './user-api';
|
||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
@ -17,6 +18,7 @@ export const api = {
|
|||||||
libraryApi,
|
libraryApi,
|
||||||
serverInfoApi,
|
serverInfoApi,
|
||||||
sharedLinkApi,
|
sharedLinkApi,
|
||||||
|
trashApi,
|
||||||
albumApi,
|
albumApi,
|
||||||
userApi,
|
userApi,
|
||||||
partnerApi,
|
partnerApi,
|
||||||
|
13
server/e2e/client/trash-api.ts
Normal file
13
server/e2e/client/trash-api.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import request from 'supertest';
|
||||||
|
import type { App } from 'supertest/types';
|
||||||
|
|
||||||
|
export const trashApi = {
|
||||||
|
async empty(server: App, accessToken: string) {
|
||||||
|
const { status } = await request(server).post('/trash/empty').set('Authorization', `Bearer ${accessToken}`);
|
||||||
|
expect(status).toBe(204);
|
||||||
|
},
|
||||||
|
async restore(server: App, accessToken: string) {
|
||||||
|
const { status } = await request(server).post('/trash/restore').set('Authorization', `Bearer ${accessToken}`);
|
||||||
|
expect(status).toBe(204);
|
||||||
|
},
|
||||||
|
};
|
80
server/e2e/jobs/specs/trash.e2e-spec.ts
Normal file
80
server/e2e/jobs/specs/trash.e2e-spec.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { LoginResponseDto } from '@app/domain';
|
||||||
|
import { api } from 'e2e/client';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
import { basename, join } from 'node:path';
|
||||||
|
import type { App } from 'supertest/types';
|
||||||
|
import { IMMICH_TEST_ASSET_PATH, testApp } from '../../../src/test-utils/utils';
|
||||||
|
|
||||||
|
const assetFilePath = join(IMMICH_TEST_ASSET_PATH, 'formats/png/density_plot.png');
|
||||||
|
|
||||||
|
describe(`Trash (e2e)`, () => {
|
||||||
|
let server: App;
|
||||||
|
let admin: LoginResponseDto;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const app = await testApp.create();
|
||||||
|
server = app.getHttpServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await testApp.reset();
|
||||||
|
await api.authApi.adminSignUp(server);
|
||||||
|
admin = await api.authApi.adminLogin(server);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await testApp.teardown();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should move an asset to trash', async () => {
|
||||||
|
const content = await readFile(assetFilePath);
|
||||||
|
const { id: assetId } = await api.assetApi.upload(server, admin.accessToken, 'test-device-id', {
|
||||||
|
content,
|
||||||
|
filename: basename(assetFilePath),
|
||||||
|
});
|
||||||
|
|
||||||
|
const uploadedAsset = await api.assetApi.get(server, admin.accessToken, assetId);
|
||||||
|
expect(uploadedAsset.isTrashed).toBe(false);
|
||||||
|
|
||||||
|
await api.assetApi.delete(server, admin.accessToken, { ids: [assetId] });
|
||||||
|
|
||||||
|
const deletedAsset = await api.assetApi.get(server, admin.accessToken, assetId);
|
||||||
|
expect(deletedAsset.isTrashed).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete all trashed assets', async () => {
|
||||||
|
const content = await readFile(assetFilePath);
|
||||||
|
const { id: assetId } = await api.assetApi.upload(server, admin.accessToken, 'test-device-id', {
|
||||||
|
content,
|
||||||
|
filename: basename(assetFilePath),
|
||||||
|
});
|
||||||
|
|
||||||
|
await api.assetApi.delete(server, admin.accessToken, { ids: [assetId] });
|
||||||
|
|
||||||
|
const assetsBeforeEmpty = await api.assetApi.getAllAssets(server, admin.accessToken);
|
||||||
|
expect(assetsBeforeEmpty.length).toBe(1);
|
||||||
|
|
||||||
|
await api.trashApi.empty(server, admin.accessToken);
|
||||||
|
|
||||||
|
const assetsAfterEmpty = await api.assetApi.getAllAssets(server, admin.accessToken);
|
||||||
|
expect(assetsAfterEmpty.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should restore all trashed assets', async () => {
|
||||||
|
const content = await readFile(assetFilePath);
|
||||||
|
const { id: assetId } = await api.assetApi.upload(server, admin.accessToken, 'test-device-id', {
|
||||||
|
content,
|
||||||
|
filename: basename(assetFilePath),
|
||||||
|
});
|
||||||
|
|
||||||
|
await api.assetApi.delete(server, admin.accessToken, { ids: [assetId] });
|
||||||
|
|
||||||
|
const deletedAsset = await api.assetApi.get(server, admin.accessToken, assetId);
|
||||||
|
expect(deletedAsset.isTrashed).toBe(true);
|
||||||
|
|
||||||
|
await api.trashApi.restore(server, admin.accessToken);
|
||||||
|
|
||||||
|
const restoredAsset = await api.assetApi.get(server, admin.accessToken, assetId);
|
||||||
|
expect(restoredAsset.isTrashed).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
@ -176,7 +176,7 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getByUserId(pagination: PaginationOptions, userId: string, options: AssetSearchOptions = {}): Paginated<AssetEntity> {
|
getByUserId(pagination: PaginationOptions, userId: string, options: AssetSearchOptions = {}): Paginated<AssetEntity> {
|
||||||
return this.getAll(pagination, { ...options, id: userId });
|
return this.getAll(pagination, { ...options, ownerId: userId });
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [[DummyValue.UUID]] })
|
@GenerateSql({ params: [[DummyValue.UUID]] })
|
||||||
|
Loading…
x
Reference in New Issue
Block a user