mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-22 06:56:35 +00:00
724c88c201
A mechanical prettier --write over server/src, server/tests, server/scripts and shared/src with the workspaces' .prettierrc; nothing but layout and import order changes, and every file keeps the same set of imports. shared is formatted throughout and its format baseline is empty. The server baseline keeps the 35 files that Prettier would grow past their lint:size limit (they need a split first, which is not a formatting change), and the generated entity files stay as their generator writes them.
211 lines
9.5 KiB
TypeScript
211 lines
9.5 KiB
TypeScript
import type { ImmichService } from '../../../src/nest/memories/immich.service';
|
|
import type { MemoriesAccessService } from '../../../src/nest/memories/memories-access.service';
|
|
import { MemoriesService } from '../../../src/nest/memories/memories.service';
|
|
import type { SynologyService } from '../../../src/nest/memories/synology.service';
|
|
import type { UnifiedMemoriesService } from '../../../src/nest/memories/unified-memories.service';
|
|
import { FakeRealtimeService } from '../../helpers/fake-realtime';
|
|
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
// The MemoriesService is a thin pass-through over the legacy services/memories/*
|
|
// helpers. Mock each legacy module so we can assert the wrapper forwards every
|
|
// argument unchanged (and exercise the optional-param call sites).
|
|
|
|
const unified = vi.hoisted(() => ({
|
|
listTripPhotos: vi.fn(() => ({ data: [] })),
|
|
listTripAlbumLinks: vi.fn(() => ({ data: [] })),
|
|
createTripAlbumLink: vi.fn(() => ({ data: {} })),
|
|
removeAlbumLink: vi.fn(() => ({ data: {} })),
|
|
addTripPhotos: vi.fn(async () => ({ data: { added: 0 } })),
|
|
syncImmichAlbum: vi.fn(async () => ({ success: true, added: 0, total: 0 })),
|
|
syncSynologyAlbum: vi.fn(async () => ({ success: true, data: { added: 0, total: 0 } })),
|
|
removeTripPhoto: vi.fn(() => ({ data: {} })),
|
|
setTripPhotoSharing: vi.fn(async () => ({ data: {} })),
|
|
}));
|
|
|
|
const immich = vi.hoisted(() => ({
|
|
getConnectionSettings: vi.fn(() => ({})),
|
|
saveImmichSettings: vi.fn(async () => ({ success: true })),
|
|
setImmichAutoUpload: vi.fn(),
|
|
testConnection: vi.fn(async () => ({ connected: true })),
|
|
getConnectionStatus: vi.fn(async () => ({ connected: true })),
|
|
browseTimeline: vi.fn(async () => ({ buckets: [] })),
|
|
searchPhotos: vi.fn(async () => ({ assets: [] })),
|
|
streamImmichAsset: vi.fn(async () => undefined),
|
|
listAlbums: vi.fn(async () => ({ albums: [] })),
|
|
getAlbumPhotos: vi.fn(async () => ({ assets: [] })),
|
|
collectAlbumSelection: vi.fn(async () => ({ selection: { provider: 'immich', asset_ids: [] }, total: 0 })),
|
|
getAssetInfo: vi.fn(async () => ({ data: {} })),
|
|
isValidAssetId: vi.fn(() => true),
|
|
}));
|
|
|
|
const synology = vi.hoisted(() => ({
|
|
getSynologySettings: vi.fn(async () => ({ success: true, data: {} })),
|
|
updateSynologySettings: vi.fn(async () => ({ success: true, data: {} })),
|
|
getSynologyStatus: vi.fn(async () => ({ success: true, data: {} })),
|
|
testSynologyConnection: vi.fn(async () => ({ success: true, data: {} })),
|
|
listSynologyAlbums: vi.fn(async () => ({ success: true, data: {} })),
|
|
getSynologyAlbumPhotos: vi.fn(async () => ({ success: true, data: {} })),
|
|
collectSynologyAlbumSelection: vi.fn(async () => ({
|
|
success: true,
|
|
data: { selection: { provider: 'synologyphotos', asset_ids: [] }, total: 0 },
|
|
})),
|
|
searchSynologyPhotos: vi.fn(async () => ({ success: true, data: {} })),
|
|
getSynologyAssetInfo: vi.fn(async () => ({ success: true, data: {} })),
|
|
streamSynologyAsset: vi.fn(async () => undefined),
|
|
}));
|
|
|
|
const helpers = vi.hoisted(() => ({ canAccessUserPhoto: vi.fn(() => true) }));
|
|
|
|
const res = {} as import('express').Response;
|
|
const realtime = new FakeRealtimeService();
|
|
|
|
describe('MemoriesService (delegation wrapper over services/memories/*)', () => {
|
|
let svc: MemoriesService;
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
svc = new MemoriesService(
|
|
realtime,
|
|
unified as unknown as UnifiedMemoriesService,
|
|
immich as unknown as ImmichService,
|
|
synology as unknown as SynologyService,
|
|
helpers as unknown as MemoriesAccessService,
|
|
);
|
|
});
|
|
|
|
it('access check + broadcast forward verbatim', async () => {
|
|
helpers.canAccessUserPhoto.mockReturnValue(false);
|
|
expect(await svc.canAccessUserPhoto(1, 2, '5', 'a', 'immich')).toBe(false);
|
|
expect(helpers.canAccessUserPhoto).toHaveBeenCalledWith(1, 2, '5', 'a', 'immich');
|
|
|
|
svc.broadcast('5', 'memories:updated', { userId: 1 }, 'sock');
|
|
expect(realtime.broadcastMock).toHaveBeenCalledWith('5', 'memories:updated', { userId: 1 }, 'sock');
|
|
});
|
|
|
|
it('broadcast forwards an absent socket id as undefined', () => {
|
|
svc.broadcast('5', 'memories:updated', { userId: 1 });
|
|
expect(realtime.broadcastMock).toHaveBeenCalledWith('5', 'memories:updated', { userId: 1 }, undefined);
|
|
});
|
|
|
|
it('unified methods delegate', async () => {
|
|
await svc.listTripPhotos('5', 7);
|
|
expect(unified.listTripPhotos).toHaveBeenCalledWith('5', 7);
|
|
|
|
const selections = [{ provider: 'immich', asset_ids: ['a'] }];
|
|
await svc.addTripPhotos('5', 7, true, selections, 'sock');
|
|
expect(unified.addTripPhotos).toHaveBeenCalledWith('5', 7, true, selections, 'sock');
|
|
|
|
await svc.setTripPhotoSharing('5', 7, 9, false);
|
|
expect(unified.setTripPhotoSharing).toHaveBeenCalledWith('5', 7, 9, false);
|
|
|
|
await svc.removeTripPhoto('5', 7, 9);
|
|
expect(unified.removeTripPhoto).toHaveBeenCalledWith('5', 7, 9);
|
|
|
|
await svc.listTripAlbumLinks('5', 7);
|
|
expect(unified.listTripAlbumLinks).toHaveBeenCalledWith('5', 7);
|
|
|
|
await svc.removeAlbumLink('5', 'l1', 7);
|
|
expect(unified.removeAlbumLink).toHaveBeenCalledWith('5', 'l1', 7);
|
|
});
|
|
|
|
it('createTripAlbumLink forwards a passphrase when present and omits it when absent', async () => {
|
|
await svc.createTripAlbumLink('5', 7, 'immich', 'a1', 'Trip', 'secret');
|
|
expect(unified.createTripAlbumLink).toHaveBeenCalledWith('5', 7, 'immich', 'a1', 'Trip', 'secret');
|
|
|
|
await svc.createTripAlbumLink('5', 7, 'immich', 'a1', 'Trip');
|
|
expect(unified.createTripAlbumLink).toHaveBeenLastCalledWith('5', 7, 'immich', 'a1', 'Trip', undefined);
|
|
});
|
|
|
|
it('immich methods delegate', async () => {
|
|
await svc.immichGetConnectionSettings(7);
|
|
expect(immich.getConnectionSettings).toHaveBeenCalledWith(7);
|
|
|
|
await svc.immichSaveSettings(7, 'u', 'k', '1.2.3.4', true);
|
|
expect(immich.saveImmichSettings).toHaveBeenCalledWith(7, 'u', 'k', '1.2.3.4', true, undefined);
|
|
|
|
await svc.immichSaveSettings(7, 'u', 'k', '1.2.3.4', undefined, false);
|
|
expect(immich.saveImmichSettings).toHaveBeenLastCalledWith(7, 'u', 'k', '1.2.3.4', undefined, false);
|
|
|
|
await svc.immichGetConnectionStatus(7);
|
|
expect(immich.getConnectionStatus).toHaveBeenCalledWith(7);
|
|
|
|
await svc.immichTestConnection('u', 'k', true);
|
|
expect(immich.testConnection).toHaveBeenCalledWith('u', 'k', true);
|
|
|
|
await svc.immichBrowseTimeline(7);
|
|
expect(immich.browseTimeline).toHaveBeenCalledWith(7);
|
|
|
|
await svc.immichSearchPhotos(7, 'f', 't', 2, 50);
|
|
expect(immich.searchPhotos).toHaveBeenCalledWith(7, 'f', 't', 2, 50);
|
|
|
|
expect(svc.immichIsValidAssetId('abc')).toBe(true);
|
|
expect(immich.isValidAssetId).toHaveBeenCalledWith('abc');
|
|
|
|
await svc.immichGetAssetInfo(7, 'a', 2);
|
|
expect(immich.getAssetInfo).toHaveBeenCalledWith(7, 'a', 2);
|
|
|
|
await svc.immichStreamAsset(res, 7, 'a', 'thumbnail', 2);
|
|
expect(immich.streamImmichAsset).toHaveBeenCalledWith(res, 7, 'a', 'thumbnail', 2);
|
|
|
|
await svc.immichListAlbums(7);
|
|
expect(immich.listAlbums).toHaveBeenCalledWith(7);
|
|
|
|
await svc.immichGetAlbumPhotos(7, 'al1');
|
|
expect(immich.getAlbumPhotos).toHaveBeenCalledWith(7, 'al1');
|
|
|
|
await svc.immichSyncAlbumAssets('5', 'l1', 7, 'sock');
|
|
expect(unified.syncImmichAlbum).toHaveBeenCalledWith('5', 'l1', 7, 'sock');
|
|
});
|
|
|
|
it('synology methods delegate', async () => {
|
|
await svc.synologyGetSettings(7);
|
|
expect(synology.getSynologySettings).toHaveBeenCalledWith(7);
|
|
|
|
await svc.synologyUpdateSettings(7, 'u', 'a', 'p', true);
|
|
expect(synology.updateSynologySettings).toHaveBeenCalledWith(7, 'u', 'a', 'p', true);
|
|
|
|
await svc.synologyGetStatus(7);
|
|
expect(synology.getSynologyStatus).toHaveBeenCalledWith(7);
|
|
|
|
await svc.synologyTestConnection(7, 'u', 'a', 'p', '123', false);
|
|
expect(synology.testSynologyConnection).toHaveBeenCalledWith(7, 'u', 'a', 'p', '123', false);
|
|
|
|
await svc.synologyListAlbums(7);
|
|
expect(synology.listSynologyAlbums).toHaveBeenCalledWith(7);
|
|
|
|
await svc.synologySyncAlbumLink(7, '5', 'l1', 'sock');
|
|
expect(unified.syncSynologyAlbum).toHaveBeenCalledWith(7, '5', 'l1', 'sock');
|
|
|
|
await svc.synologySearchPhotos(7, 'f', 't', 0, 100);
|
|
expect(synology.searchSynologyPhotos).toHaveBeenCalledWith(7, 'f', 't', 0, 100, 0);
|
|
|
|
// The zone the days are meant in has to reach the provider, and it is a
|
|
// different thing from the pagination offset sitting next to it (#2336).
|
|
await svc.synologySearchPhotos(7, 'f', 't', 0, 100, 600);
|
|
expect(synology.searchSynologyPhotos).toHaveBeenLastCalledWith(7, 'f', 't', 0, 100, 600);
|
|
});
|
|
|
|
it('synology album-photos forwards a passphrase when present and omits it when absent', async () => {
|
|
await svc.synologyGetAlbumPhotos(7, 'al1', 'secret');
|
|
expect(synology.getSynologyAlbumPhotos).toHaveBeenCalledWith(7, 'al1', 'secret');
|
|
|
|
await svc.synologyGetAlbumPhotos(7, 'al1');
|
|
expect(synology.getSynologyAlbumPhotos).toHaveBeenLastCalledWith(7, 'al1', undefined);
|
|
});
|
|
|
|
it('synology asset-info + stream forward a passphrase when present and omit it when absent', async () => {
|
|
await svc.synologyGetAssetInfo(7, 'p1', 2, 'secret');
|
|
expect(synology.getSynologyAssetInfo).toHaveBeenCalledWith(7, 'p1', 2, 'secret');
|
|
|
|
await svc.synologyGetAssetInfo(7, 'p1', 2);
|
|
expect(synology.getSynologyAssetInfo).toHaveBeenLastCalledWith(7, 'p1', 2, undefined);
|
|
|
|
await svc.synologyStreamAsset(res, 7, 2, 'p1', 'thumbnail', 'sm', 'secret');
|
|
expect(synology.streamSynologyAsset).toHaveBeenCalledWith(res, 7, 2, 'p1', 'thumbnail', 'sm', 'secret');
|
|
|
|
await svc.synologyStreamAsset(res, 7, 2, 'p1', 'original', 'xl');
|
|
expect(synology.streamSynologyAsset).toHaveBeenLastCalledWith(res, 7, 2, 'p1', 'original', 'xl', undefined);
|
|
});
|
|
});
|