Source Code added

This commit is contained in:
Fr4nz D13trich 2026-02-02 15:06:40 +01:00
parent 800376eafd
commit 9efa9bc6dd
3912 changed files with 754770 additions and 2 deletions

152
server/test/fixtures/album.stub.ts vendored Normal file
View file

@ -0,0 +1,152 @@
import { AlbumUserRole, AssetOrder } from 'src/enum';
import { assetStub } from 'test/fixtures/asset.stub';
import { authStub } from 'test/fixtures/auth.stub';
import { userStub } from 'test/fixtures/user.stub';
export const albumStub = {
empty: Object.freeze({
id: 'album-1',
albumName: 'Empty album',
description: '',
ownerId: authStub.admin.user.id,
owner: userStub.admin,
assets: [],
albumThumbnailAsset: null,
albumThumbnailAssetId: null,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
sharedLinks: [],
albumUsers: [],
isActivityEnabled: true,
order: AssetOrder.Desc,
updateId: '42',
}),
sharedWithUser: Object.freeze({
id: 'album-2',
albumName: 'Empty album shared with user',
description: '',
ownerId: authStub.admin.user.id,
owner: userStub.admin,
assets: [],
albumThumbnailAsset: null,
albumThumbnailAssetId: null,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
sharedLinks: [],
albumUsers: [
{
user: userStub.user1,
role: AlbumUserRole.Editor,
},
],
isActivityEnabled: true,
order: AssetOrder.Desc,
updateId: '42',
}),
sharedWithMultiple: Object.freeze({
id: 'album-3',
albumName: 'Empty album shared with users',
description: '',
ownerId: authStub.admin.user.id,
owner: userStub.admin,
assets: [],
albumThumbnailAsset: null,
albumThumbnailAssetId: null,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
sharedLinks: [],
albumUsers: [
{
user: userStub.user1,
role: AlbumUserRole.Editor,
},
{
user: userStub.user2,
role: AlbumUserRole.Editor,
},
],
isActivityEnabled: true,
order: AssetOrder.Desc,
updateId: '42',
}),
sharedWithAdmin: Object.freeze({
id: 'album-3',
albumName: 'Empty album shared with admin',
description: '',
ownerId: authStub.user1.user.id,
owner: userStub.user1,
assets: [],
albumThumbnailAsset: null,
albumThumbnailAssetId: null,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
sharedLinks: [],
albumUsers: [
{
user: userStub.admin,
role: AlbumUserRole.Editor,
},
],
isActivityEnabled: true,
order: AssetOrder.Desc,
updateId: '42',
}),
oneAsset: Object.freeze({
id: 'album-4',
albumName: 'Album with one asset',
description: '',
ownerId: authStub.admin.user.id,
owner: userStub.admin,
assets: [assetStub.image],
albumThumbnailAsset: null,
albumThumbnailAssetId: null,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
sharedLinks: [],
albumUsers: [],
isActivityEnabled: true,
order: AssetOrder.Desc,
updateId: '42',
}),
twoAssets: Object.freeze({
id: 'album-4a',
albumName: 'Album with two assets',
description: '',
ownerId: authStub.admin.user.id,
owner: userStub.admin,
assets: [assetStub.image, assetStub.withLocation],
albumThumbnailAsset: assetStub.image,
albumThumbnailAssetId: assetStub.image.id,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
sharedLinks: [],
albumUsers: [],
isActivityEnabled: true,
order: AssetOrder.Desc,
updateId: '42',
}),
emptyWithValidThumbnail: Object.freeze({
id: 'album-5',
albumName: 'Empty album with valid thumbnail',
description: '',
ownerId: authStub.admin.user.id,
owner: userStub.admin,
assets: [],
albumThumbnailAsset: assetStub.image,
albumThumbnailAssetId: assetStub.image.id,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
sharedLinks: [],
albumUsers: [],
isActivityEnabled: true,
order: AssetOrder.Desc,
updateId: '42',
}),
};

1133
server/test/fixtures/asset.stub.ts vendored Normal file

File diff suppressed because it is too large Load diff

56
server/test/fixtures/auth.stub.ts vendored Normal file
View file

@ -0,0 +1,56 @@
import { AuthSession } from 'src/database';
import { AuthDto } from 'src/dtos/auth.dto';
const authUser = {
admin: {
id: 'admin_id',
name: 'admin',
email: 'admin@test.com',
isAdmin: true,
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
user1: {
id: 'user-id',
name: 'User 1',
email: 'immich@test.com',
isAdmin: false,
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
};
export const authStub = {
admin: Object.freeze<AuthDto>({ user: authUser.admin }),
user1: Object.freeze<AuthDto>({
user: authUser.user1,
session: {
id: 'token-id',
} as AuthSession,
}),
user2: Object.freeze<AuthDto>({
user: {
id: 'user-2',
name: 'User 2',
email: 'user2@immich.cloud',
isAdmin: false,
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
session: {
id: 'token-id',
} as AuthSession,
}),
adminSharedLink: Object.freeze({
user: authUser.admin,
sharedLink: {
id: '123',
showExif: true,
allowDownload: true,
allowUpload: true,
expiresAt: null,
password: null,
userId: '42',
},
}),
};

160
server/test/fixtures/face.stub.ts vendored Normal file
View file

@ -0,0 +1,160 @@
import { SourceType } from 'src/enum';
import { assetStub } from 'test/fixtures/asset.stub';
import { personStub } from 'test/fixtures/person.stub';
export const faceStub = {
face1: Object.freeze({
id: 'assetFaceId1',
assetId: assetStub.image.id,
asset: {
...assetStub.image,
libraryId: null,
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
stackId: null,
},
personId: personStub.withName.id,
person: personStub.withName,
boundingBoxX1: 0,
boundingBoxY1: 0,
boundingBoxX2: 1,
boundingBoxY2: 1,
imageHeight: 1024,
imageWidth: 1024,
sourceType: SourceType.MachineLearning,
faceSearch: { faceId: 'assetFaceId1', embedding: '[1, 2, 3, 4]' },
deletedAt: new Date(),
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
primaryFace1: Object.freeze({
id: 'assetFaceId2',
assetId: assetStub.image.id,
asset: assetStub.image,
personId: personStub.primaryPerson.id,
person: personStub.primaryPerson,
boundingBoxX1: 0,
boundingBoxY1: 0,
boundingBoxX2: 1,
boundingBoxY2: 1,
imageHeight: 1024,
imageWidth: 1024,
sourceType: SourceType.MachineLearning,
faceSearch: { faceId: 'assetFaceId2', embedding: '[1, 2, 3, 4]' },
deletedAt: null,
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
mergeFace1: Object.freeze({
id: 'assetFaceId3',
assetId: assetStub.image.id,
asset: assetStub.image,
personId: personStub.mergePerson.id,
person: personStub.mergePerson,
boundingBoxX1: 0,
boundingBoxY1: 0,
boundingBoxX2: 1,
boundingBoxY2: 1,
imageHeight: 1024,
imageWidth: 1024,
sourceType: SourceType.MachineLearning,
faceSearch: { faceId: 'assetFaceId3', embedding: '[1, 2, 3, 4]' },
deletedAt: null,
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
noPerson1: Object.freeze({
id: 'assetFaceId8',
assetId: assetStub.image.id,
asset: assetStub.image,
personId: null,
person: null,
boundingBoxX1: 0,
boundingBoxY1: 0,
boundingBoxX2: 1,
boundingBoxY2: 1,
imageHeight: 1024,
imageWidth: 1024,
sourceType: SourceType.MachineLearning,
faceSearch: { faceId: 'assetFaceId8', embedding: '[1, 2, 3, 4]' },
deletedAt: null,
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
noPerson2: Object.freeze({
id: 'assetFaceId9',
assetId: assetStub.image.id,
asset: assetStub.image,
personId: null,
person: null,
boundingBoxX1: 0,
boundingBoxY1: 0,
boundingBoxX2: 1,
boundingBoxY2: 1,
imageHeight: 1024,
imageWidth: 1024,
sourceType: SourceType.MachineLearning,
faceSearch: { faceId: 'assetFaceId9', embedding: '[1, 2, 3, 4]' },
deletedAt: null,
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
fromExif1: Object.freeze({
id: 'assetFaceId9',
assetId: assetStub.image.id,
asset: assetStub.image,
personId: personStub.randomPerson.id,
person: personStub.randomPerson,
boundingBoxX1: 100,
boundingBoxY1: 100,
boundingBoxX2: 200,
boundingBoxY2: 200,
imageHeight: 500,
imageWidth: 400,
sourceType: SourceType.Exif,
deletedAt: null,
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
fromExif2: Object.freeze({
id: 'assetFaceId9',
assetId: assetStub.image.id,
asset: assetStub.image,
personId: personStub.randomPerson.id,
person: personStub.randomPerson,
boundingBoxX1: 0,
boundingBoxY1: 0,
boundingBoxX2: 1,
boundingBoxY2: 1,
imageHeight: 1024,
imageWidth: 1024,
sourceType: SourceType.Exif,
deletedAt: null,
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
withBirthDate: Object.freeze({
id: 'assetFaceId10',
assetId: assetStub.image.id,
asset: assetStub.image,
personId: personStub.withBirthDate.id,
person: personStub.withBirthDate,
boundingBoxX1: 0,
boundingBoxY1: 0,
boundingBoxX2: 1,
boundingBoxY2: 1,
imageHeight: 1024,
imageWidth: 1024,
sourceType: SourceType.MachineLearning,
deletedAt: null,
updatedAt: new Date('2023-01-01T00:00:00Z'),
updateId: '0d1173e3-4d80-4d76-b41e-57d56de21125',
isVisible: true,
}),
};

31
server/test/fixtures/file.stub.ts vendored Normal file
View file

@ -0,0 +1,31 @@
export const fileStub = {
livePhotoStill: Object.freeze({
uuid: 'random-uuid',
originalPath: 'fake_path/asset_1.jpeg',
checksum: Buffer.from('file hash', 'utf8'),
originalName: 'asset_1.jpeg',
size: 42,
}),
livePhotoMotion: Object.freeze({
uuid: 'live-photo-motion-asset',
originalPath: 'fake_path/asset_1.mp4',
checksum: Buffer.from('live photo file hash', 'utf8'),
originalName: 'asset_1.mp4',
size: 69,
}),
photo: Object.freeze({
uuid: 'photo',
originalPath: 'fake_path/photo1.jpeg',
mimeType: 'image/jpeg',
checksum: Buffer.from('photo file hash', 'utf8'),
originalName: 'photo1.jpeg',
size: 24,
}),
photoSidecar: Object.freeze({
uuid: 'photo-sidecar',
originalPath: 'fake_path/photo1.jpeg.xmp',
originalName: 'photo1.jpeg.xmp',
checksum: Buffer.from('photo-sidecar file hash', 'utf8'),
size: 96,
}),
};

275
server/test/fixtures/media.stub.ts vendored Normal file
View file

@ -0,0 +1,275 @@
import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from 'src/types';
const probeStubDefaultFormat: VideoFormat = {
formatName: 'mov,mp4,m4a,3gp,3g2,mj2',
formatLongName: 'QuickTime / MOV',
duration: 0,
bitrate: 0,
};
const probeStubDefaultVideoStream: VideoStreamInfo[] = [
{
index: 0,
height: 1080,
width: 1920,
codecName: 'hevc',
frameCount: 100,
rotation: 0,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p',
},
];
const probeStubDefaultAudioStream: AudioStreamInfo[] = [{ index: 3, codecName: 'mp3', bitrate: 100 }];
const probeStubDefault: VideoInfo = {
format: probeStubDefaultFormat,
videoStreams: probeStubDefaultVideoStream,
audioStreams: probeStubDefaultAudioStream,
};
export const probeStub = {
noVideoStreams: Object.freeze<VideoInfo>({ ...probeStubDefault, videoStreams: [] }),
noAudioStreams: Object.freeze<VideoInfo>({ ...probeStubDefault, audioStreams: [] }),
multipleVideoStreams: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 1080,
width: 400,
codecName: 'hevc',
frameCount: 1,
rotation: 0,
isHDR: false,
bitrate: 100,
pixelFormat: 'yuv420p',
},
{
index: 1,
height: 1080,
width: 400,
codecName: 'hevc',
frameCount: 2,
rotation: 0,
isHDR: false,
bitrate: 101,
pixelFormat: 'yuv420p',
},
{
index: 2,
height: 1080,
width: 400,
codecName: 'h7000',
frameCount: 3,
rotation: 0,
isHDR: false,
bitrate: 99,
pixelFormat: 'yuv420p',
},
],
}),
multipleAudioStreams: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [
{ index: 0, codecName: 'mp3', bitrate: 100 },
{ index: 1, codecName: 'mp3', bitrate: 101 },
{ index: 2, codecName: 'mp3', bitrate: 102 },
],
}),
noHeight: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 0,
width: 400,
codecName: 'hevc',
frameCount: 100,
rotation: 0,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p',
},
],
}),
videoStream2160p: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'h264',
frameCount: 100,
rotation: 0,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p',
},
],
}),
videoStream40Mbps: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], bitrate: 40_000_000 }],
}),
videoStreamMTS: Object.freeze<VideoInfo>({
...probeStubDefault,
format: {
...probeStubDefaultFormat,
formatName: 'mpegts',
},
}),
videoStreamHDR: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 480,
width: 480,
codecName: 'h264',
frameCount: 100,
rotation: 0,
isHDR: true,
bitrate: 0,
pixelFormat: 'yuv420p10le',
},
],
}),
videoStream10Bit: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 480,
width: 480,
codecName: 'h264',
frameCount: 100,
rotation: 0,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p10le',
},
],
}),
videoStream4K10Bit: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'h264',
frameCount: 100,
rotation: 0,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p10le',
},
],
}),
videoStreamVertical2160p: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 2160,
width: 3840,
codecName: 'h264',
frameCount: 100,
rotation: 90,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p',
},
],
}),
videoStreamOddHeight: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 355,
width: 1586,
codecName: 'h264',
frameCount: 100,
rotation: 0,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p',
},
],
}),
videoStreamOddWidth: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
index: 0,
height: 1586,
width: 355,
codecName: 'h264',
frameCount: 100,
rotation: 0,
isHDR: false,
bitrate: 0,
pixelFormat: 'yuv420p',
},
],
}),
audioStreamAac: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [{ index: 1, codecName: 'aac', bitrate: 100 }],
}),
audioStreamUnknown: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [
{ index: 0, codecName: 'aac', bitrate: 100 },
{ index: 1, codecName: 'unknown', bitrate: 200 },
],
}),
matroskaContainer: Object.freeze<VideoInfo>({
...probeStubDefault,
format: {
formatName: 'matroska,webm',
formatLongName: 'Matroska / WebM',
duration: 0,
bitrate: 0,
},
}),
videoStreamVp9: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], codecName: 'vp9' }],
format: {
formatName: 'matroska,webm',
formatLongName: 'Matroska / WebM',
duration: 0,
bitrate: 0,
},
}),
videoStreamH264: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], codecName: 'h264' }],
}),
videoStreamAvi: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [{ ...probeStubDefaultVideoStream[0], codecName: 'h264' }],
format: {
formatName: 'avi',
formatLongName: 'AVI (Audio Video Interleaved)',
duration: 0,
bitrate: 0,
},
}),
videoStreamReserved: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
...probeStubDefaultVideoStream[0],
colorPrimaries: 'reserved',
colorSpace: 'reserved',
colorTransfer: 'reserved',
},
],
}),
};

View file

@ -0,0 +1,14 @@
import { NotificationLevel, NotificationType } from 'src/enum';
export const notificationStub = {
albumEvent: {
id: 'notification-album-event',
type: NotificationType.AlbumInvite,
description: 'You have been invited to a shared album',
title: 'Album Invitation',
createdAt: new Date('2024-01-01'),
data: { albumId: 'album-id' },
level: NotificationLevel.Success,
readAt: null,
},
};

262
server/test/fixtures/person.stub.ts vendored Normal file
View file

@ -0,0 +1,262 @@
import { AssetType } from 'src/enum';
import { previewFile } from 'test/fixtures/asset.stub';
import { userStub } from 'test/fixtures/user.stub';
const updateId = '0d1173e3-4d80-4d76-b41e-57d56de21125';
export const personStub = {
noName: Object.freeze({
id: 'person-1',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: '',
birthDate: null,
thumbnailPath: '/path/to/thumbnail.jpg',
faces: [],
faceAssetId: null,
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
hidden: Object.freeze({
id: 'person-1',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: '',
birthDate: null,
thumbnailPath: '/path/to/thumbnail.jpg',
faces: [],
faceAssetId: null,
faceAsset: null,
isHidden: true,
isFavorite: false,
color: 'red',
}),
withName: Object.freeze({
id: 'person-1',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: 'Person 1',
birthDate: null,
thumbnailPath: '/path/to/thumbnail.jpg',
faces: [],
faceAssetId: 'assetFaceId',
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
withBirthDate: Object.freeze({
id: 'person-1',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: 'Person 1',
birthDate: new Date('1976-06-30'),
thumbnailPath: '/path/to/thumbnail.jpg',
faces: [],
faceAssetId: null,
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
noThumbnail: Object.freeze({
id: 'person-1',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: '',
birthDate: null,
thumbnailPath: '',
faces: [],
faceAssetId: null,
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
newThumbnail: Object.freeze({
id: 'person-1',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: '',
birthDate: null,
thumbnailPath: '/new/path/to/thumbnail.jpg',
faces: [],
faceAssetId: 'asset-id',
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
primaryPerson: Object.freeze({
id: 'person-1',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: 'Person 1',
birthDate: null,
thumbnailPath: '/path/to/thumbnail',
faces: [],
faceAssetId: null,
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
mergePerson: Object.freeze({
id: 'person-2',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: 'Person 2',
birthDate: null,
thumbnailPath: '/path/to/thumbnail',
faces: [],
faceAssetId: null,
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
randomPerson: Object.freeze({
id: 'person-3',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: '',
birthDate: null,
thumbnailPath: '/path/to/thumbnail',
faces: [],
faceAssetId: null,
faceAsset: null,
isHidden: false,
isFavorite: false,
color: 'red',
}),
isFavorite: Object.freeze({
id: 'person-4',
createdAt: new Date('2021-01-01'),
updatedAt: new Date('2021-01-01'),
updateId,
ownerId: userStub.admin.id,
name: 'Person 1',
birthDate: null,
thumbnailPath: '/path/to/thumbnail.jpg',
faces: [],
faceAssetId: 'assetFaceId',
faceAsset: null,
isHidden: false,
isFavorite: true,
color: 'red',
}),
};
export const personThumbnailStub = {
newThumbnailStart: Object.freeze({
ownerId: userStub.admin.id,
x1: 5,
y1: 5,
x2: 505,
y2: 505,
oldHeight: 2880,
oldWidth: 2160,
type: AssetType.Image,
originalPath: '/original/path.jpg',
exifOrientation: '1',
previewPath: previewFile.path,
}),
newThumbnailMiddle: Object.freeze({
ownerId: userStub.admin.id,
x1: 100,
y1: 100,
x2: 200,
y2: 200,
oldHeight: 500,
oldWidth: 400,
type: AssetType.Image,
originalPath: '/original/path.jpg',
exifOrientation: '1',
previewPath: previewFile.path,
}),
newThumbnailEnd: Object.freeze({
ownerId: userStub.admin.id,
x1: 300,
y1: 300,
x2: 495,
y2: 495,
oldHeight: 500,
oldWidth: 500,
type: AssetType.Image,
originalPath: '/original/path.jpg',
exifOrientation: '1',
previewPath: previewFile.path,
}),
rawEmbeddedThumbnail: Object.freeze({
ownerId: userStub.admin.id,
x1: 100,
y1: 100,
x2: 200,
y2: 200,
oldHeight: 500,
oldWidth: 400,
type: AssetType.Image,
originalPath: '/original/path.dng',
exifOrientation: '1',
previewPath: previewFile.path,
}),
negativeCoordinate: Object.freeze({
ownerId: userStub.admin.id,
x1: -176,
y1: -230,
x2: 193,
y2: 251,
oldHeight: 1440,
oldWidth: 2162,
type: AssetType.Image,
originalPath: '/original/path.jpg',
exifOrientation: '1',
previewPath: previewFile.path,
}),
overflowingCoordinate: Object.freeze({
ownerId: userStub.admin.id,
x1: 2097,
y1: 0,
x2: 2171,
y2: 152,
oldHeight: 1440,
oldWidth: 2162,
type: AssetType.Image,
originalPath: '/original/path.jpg',
exifOrientation: '1',
previewPath: previewFile.path,
}),
videoThumbnail: Object.freeze({
ownerId: userStub.admin.id,
x1: 100,
y1: 100,
x2: 200,
y2: 200,
oldHeight: 500,
oldWidth: 400,
type: AssetType.Video,
originalPath: '/original/path.mp4',
exifOrientation: '1',
previewPath: previewFile.path,
}),
};

221
server/test/fixtures/shared-link.stub.ts vendored Normal file
View file

@ -0,0 +1,221 @@
import { UserAdmin } from 'src/database';
import { MapAsset } from 'src/dtos/asset-response.dto';
import { SharedLinkResponseDto } from 'src/dtos/shared-link.dto';
import { AssetStatus, AssetType, AssetVisibility, SharedLinkType } from 'src/enum';
import { assetStub } from 'test/fixtures/asset.stub';
import { authStub } from 'test/fixtures/auth.stub';
import { userStub } from 'test/fixtures/user.stub';
const today = new Date();
const tomorrow = new Date();
const yesterday = new Date();
tomorrow.setDate(today.getDate() + 1);
yesterday.setDate(yesterday.getDate() - 1);
const sharedLinkBytes = Buffer.from(
'2c2b646895f84753bff43fb696ad124f3b0faf2a0bd547406f26fa4a76b5c71990092baa536275654b2ab7a191fb21a6d6cd',
'hex',
);
export const sharedLinkStub = {
individual: Object.freeze({
id: '123',
userId: authStub.admin.user.id,
key: sharedLinkBytes,
type: SharedLinkType.Individual,
createdAt: today,
expiresAt: tomorrow,
allowUpload: true,
allowDownload: true,
showExif: true,
albumId: null,
album: null,
description: null,
assets: [assetStub.image],
password: 'password',
slug: null,
}),
valid: Object.freeze({
id: '123',
userId: authStub.admin.user.id,
user: userStub.admin,
key: sharedLinkBytes,
type: SharedLinkType.Album,
createdAt: today,
expiresAt: tomorrow,
allowUpload: true,
allowDownload: true,
showExif: true,
albumId: null,
description: null,
password: null,
assets: [] as MapAsset[],
album: null,
slug: null,
}),
expired: Object.freeze({
id: '123',
userId: authStub.admin.user.id,
user: userStub.admin,
key: sharedLinkBytes,
type: SharedLinkType.Album,
createdAt: today,
expiresAt: yesterday,
allowUpload: true,
allowDownload: true,
showExif: true,
description: null,
password: null,
albumId: null,
assets: [] as MapAsset[],
album: null,
slug: null,
}),
readonlyNoExif: Object.freeze({
id: '123',
userId: authStub.admin.user.id,
key: sharedLinkBytes,
type: SharedLinkType.Individual,
createdAt: today,
expiresAt: tomorrow,
allowUpload: false,
allowDownload: false,
showExif: false,
description: null,
password: null,
assets: [
{
id: 'id_1',
status: AssetStatus.Active,
owner: undefined as unknown as UserAdmin,
ownerId: 'user_id_1',
deviceAssetId: 'device_asset_id_1',
deviceId: 'device_id_1',
type: AssetType.Video,
originalPath: 'fake_path/jpeg',
checksum: Buffer.from('file hash', 'utf8'),
fileModifiedAt: today,
fileCreatedAt: today,
localDateTime: today,
createdAt: today,
updatedAt: today,
isFavorite: false,
isArchived: false,
isExternal: false,
isOffline: false,
files: [],
thumbhash: null,
encodedVideoPath: '',
duration: null,
livePhotoVideo: null,
livePhotoVideoId: null,
originalFileName: 'asset_1.jpeg',
exifInfo: {
projectionType: null,
livePhotoCID: null,
assetId: 'id_1',
description: 'description',
exifImageWidth: 500,
exifImageHeight: 500,
fileSizeInByte: 100,
orientation: 'orientation',
dateTimeOriginal: today,
modifyDate: today,
timeZone: 'America/Los_Angeles',
latitude: 100,
longitude: 100,
city: 'city',
state: 'state',
country: 'country',
make: 'camera-make',
model: 'camera-model',
lensModel: 'fancy',
fNumber: 100,
focalLength: 100,
iso: 100,
exposureTime: '1/16',
fps: 100,
profileDescription: 'sRGB',
bitsPerSample: 8,
colorspace: 'sRGB',
autoStackId: null,
rating: 3,
updatedAt: today,
updateId: '42',
libraryId: null,
stackId: null,
visibility: AssetVisibility.Timeline,
width: 500,
height: 500,
tags: [],
},
sharedLinks: [],
faces: [],
sidecarPath: null,
deletedAt: null,
duplicateId: null,
updateId: '42',
libraryId: null,
stackId: null,
visibility: AssetVisibility.Timeline,
width: 500,
height: 500,
isEdited: false,
},
],
albumId: null,
album: null,
slug: null,
}),
passwordRequired: Object.freeze({
id: '123',
userId: authStub.admin.user.id,
key: sharedLinkBytes,
type: SharedLinkType.Album,
createdAt: today,
expiresAt: tomorrow,
allowUpload: true,
allowDownload: true,
showExif: true,
slug: null,
description: null,
password: 'password',
assets: [],
albumId: null,
album: null,
}),
};
export const sharedLinkResponseStub = {
valid: Object.freeze<SharedLinkResponseDto>({
allowDownload: true,
allowUpload: true,
assets: [],
createdAt: today,
description: null,
password: null,
expiresAt: tomorrow,
id: '123',
key: sharedLinkBytes.toString('base64url'),
showMetadata: true,
type: SharedLinkType.Album,
userId: 'admin_id',
slug: null,
}),
expired: Object.freeze<SharedLinkResponseDto>({
album: undefined,
allowDownload: true,
allowUpload: true,
assets: [],
createdAt: today,
description: null,
password: null,
expiresAt: yesterday,
id: '123',
key: sharedLinkBytes.toString('base64url'),
showMetadata: true,
type: SharedLinkType.Album,
userId: 'admin_id',
slug: null,
}),
};

View file

@ -0,0 +1,120 @@
import { SystemConfig } from 'src/config';
import { DeepPartial } from 'src/types';
export const systemConfigStub = {
enabled: {
oauth: {
enabled: true,
autoRegister: true,
autoLaunch: false,
buttonText: 'OAuth',
},
},
disabled: {
passwordLogin: {
enabled: false,
},
},
oauthEnabled: {
oauth: {
enabled: true,
autoRegister: false,
autoLaunch: false,
buttonText: 'OAuth',
},
},
oauthWithAutoRegister: {
oauth: {
enabled: true,
autoRegister: true,
autoLaunch: false,
buttonText: 'OAuth',
},
},
oauthWithMobileOverride: {
oauth: {
enabled: true,
autoRegister: true,
mobileOverrideEnabled: true,
mobileRedirectUri: 'http://mobile-redirect',
buttonText: 'OAuth',
},
},
oauthWithStorageQuota: {
oauth: {
enabled: true,
autoRegister: true,
defaultStorageQuota: 1,
},
},
libraryWatchEnabled: {
library: {
scan: {
enabled: false,
},
watch: {
enabled: true,
},
},
},
libraryWatchDisabled: {
library: {
scan: {
enabled: false,
},
watch: {
enabled: false,
},
},
},
libraryScan: {
library: {
scan: {
enabled: true,
cronExpression: '0 0 * * *',
},
watch: {
enabled: false,
},
},
},
libraryScanAndWatch: {
library: {
scan: {
enabled: true,
cronExpression: '0 0 * * *',
},
watch: {
enabled: true,
},
},
},
backupEnabled: {
backup: {
database: {
enabled: true,
cronExpression: '0 0 * * *',
keepLastAmount: 1,
},
},
},
machineLearningDisabled: {
machineLearning: {
enabled: false,
},
},
machineLearningEnabled: {
machineLearning: {
enabled: true,
clip: {
modelName: 'ViT-B-16__openai',
enabled: true,
},
},
},
publicUsersDisabled: {
server: {
publicUsers: false,
},
},
} satisfies Record<string, DeepPartial<SystemConfig>>;

71
server/test/fixtures/tag.stub.ts vendored Normal file
View file

@ -0,0 +1,71 @@
import { Tag } from 'src/database';
import { TagResponseDto } from 'src/dtos/tag.dto';
import { newUuidV7 } from 'test/small.factory';
const parent = Object.freeze<Tag>({
id: 'tag-parent',
createdAt: new Date('2021-01-01T00:00:00Z'),
updatedAt: new Date('2021-01-01T00:00:00Z'),
value: 'Parent',
color: null,
parentId: null,
});
const child = Object.freeze<Tag>({
id: 'tag-child',
createdAt: new Date('2021-01-01T00:00:00Z'),
updatedAt: new Date('2021-01-01T00:00:00Z'),
value: 'Parent/Child',
color: null,
parentId: parent.id,
});
const tag = {
id: 'tag-1',
createdAt: new Date('2021-01-01T00:00:00Z'),
updatedAt: new Date('2021-01-01T00:00:00Z'),
value: 'Tag1',
color: null,
parentId: null,
};
const color = {
id: 'tag-1',
createdAt: new Date('2021-01-01T00:00:00Z'),
updatedAt: new Date('2021-01-01T00:00:00Z'),
value: 'Tag1',
color: '#000000',
parentId: null,
};
const upsert = {
userId: 'tag-user',
updateId: newUuidV7(),
};
export const tagStub = {
tag,
tagCreate: { ...tag, ...upsert },
color,
colorCreate: { ...color, ...upsert },
parentUpsert: { ...parent, ...upsert },
childUpsert: { ...child, ...upsert },
};
export const tagResponseStub = {
tag1: Object.freeze<TagResponseDto>({
id: 'tag-1',
createdAt: new Date('2021-01-01T00:00:00Z'),
updatedAt: new Date('2021-01-01T00:00:00Z'),
name: 'Tag1',
value: 'Tag1',
}),
color1: Object.freeze<TagResponseDto>({
id: 'tag-1',
createdAt: new Date('2021-01-01T00:00:00Z'),
updatedAt: new Date('2021-01-01T00:00:00Z'),
color: '#000000',
name: 'Tag1',
value: 'Tag1',
}),
};

58
server/test/fixtures/user.stub.ts vendored Normal file
View file

@ -0,0 +1,58 @@
import { UserAdmin } from 'src/database';
import { UserStatus } from 'src/enum';
import { authStub } from 'test/fixtures/auth.stub';
export const userStub = {
admin: <UserAdmin>{
...authStub.admin.user,
status: UserStatus.Active,
profileChangedAt: new Date('2021-01-01'),
name: 'admin_name',
id: 'admin_id',
storageLabel: 'admin',
oauthId: '',
shouldChangePassword: false,
avatarColor: null,
profileImagePath: '',
createdAt: new Date('2021-01-01'),
deletedAt: null,
updatedAt: new Date('2021-01-01'),
metadata: [],
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
user1: <UserAdmin>{
...authStub.user1.user,
status: UserStatus.Active,
profileChangedAt: new Date('2021-01-01'),
name: 'immich_name',
storageLabel: null,
oauthId: '',
shouldChangePassword: false,
avatarColor: null,
profileImagePath: '',
createdAt: new Date('2021-01-01'),
deletedAt: null,
updatedAt: new Date('2021-01-01'),
metadata: [],
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
user2: <UserAdmin>{
...authStub.user2.user,
status: UserStatus.Active,
profileChangedAt: new Date('2021-01-01'),
metadata: [],
name: 'immich_name',
storageLabel: null,
oauthId: '',
shouldChangePassword: false,
avatarColor: null,
profileImagePath: '',
createdAt: new Date('2021-01-01'),
deletedAt: null,
updatedAt: new Date('2021-01-01'),
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
};