mirror of
https://github.com/immich-app/immich.git
synced 2026-02-04 08:49:01 +03:00
fix(web): Handle upload failures from public users (#24826)
This commit is contained in:
73
web/src/lib/utils/file-uploader.spec.ts
Normal file
73
web/src/lib/utils/file-uploader.spec.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { uploadManager } from '$lib/managers/upload-manager.svelte';
|
||||||
|
import { uploadAssetsStore } from '$lib/stores/upload';
|
||||||
|
import { resetSavedUser, user } from '$lib/stores/user.store';
|
||||||
|
import { UploadState } from '$lib/types';
|
||||||
|
import * as utils from '$lib/utils';
|
||||||
|
import { AssetMediaStatus, type AssetMediaResponseDto, type UserAdminResponseDto } from '@immich/sdk';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
import { fileUploadHandler } from './file-uploader';
|
||||||
|
|
||||||
|
describe('fileUploader error handling', () => {
|
||||||
|
const mockFile = new File(['content'], 'test.jpg', { type: 'image/jpeg' });
|
||||||
|
const mockUserObject = { id: 'user-123', email: 'test@example.com' } as UserAdminResponseDto;
|
||||||
|
const mockError = new Error('Upload failed');
|
||||||
|
const mockUploadResponse = { id: 'mock-id', status: AssetMediaStatus.Created } as AssetMediaResponseDto;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
vi.spyOn(uploadManager, 'getExtensions').mockReturnValue(['.jpg']);
|
||||||
|
uploadAssetsStore.reset();
|
||||||
|
resetSavedUser();
|
||||||
|
|
||||||
|
// Stub out crypto to avoid that branch
|
||||||
|
vi.stubGlobal('crypto', undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const [name, mockUser] of [
|
||||||
|
['logged-in users', true],
|
||||||
|
['anonymous users', false],
|
||||||
|
] as const) {
|
||||||
|
describe(`for ${name}`, () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
if (mockUser) {
|
||||||
|
user.set(mockUserObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should transition successful uploads to done`, async () => {
|
||||||
|
vi.spyOn(utils, 'uploadRequest').mockResolvedValue({ status: 200, data: mockUploadResponse });
|
||||||
|
|
||||||
|
await fileUploadHandler({ files: [mockFile] });
|
||||||
|
|
||||||
|
const items = get(uploadAssetsStore);
|
||||||
|
expect(items.length).toBe(1);
|
||||||
|
expect(items[0].state).toBe(UploadState.DONE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should capture errors', async () => {
|
||||||
|
vi.spyOn(utils, 'uploadRequest').mockRejectedValue(mockError);
|
||||||
|
|
||||||
|
await fileUploadHandler({ files: [mockFile] });
|
||||||
|
|
||||||
|
const items = get(uploadAssetsStore);
|
||||||
|
expect(items.length).toBe(1);
|
||||||
|
expect(items[0].state).toBe(UploadState.ERROR);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should suppress errors on logout', async () => {
|
||||||
|
user.set(mockUserObject);
|
||||||
|
vi.spyOn(utils, 'uploadRequest').mockImplementationOnce(() => {
|
||||||
|
resetSavedUser();
|
||||||
|
return Promise.reject(mockError);
|
||||||
|
});
|
||||||
|
|
||||||
|
await fileUploadHandler({ files: [mockFile] });
|
||||||
|
|
||||||
|
const items = get(uploadAssetsStore);
|
||||||
|
expect(items.length).toBe(1);
|
||||||
|
expect(items[0].state).toBe(UploadState.STARTED);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -125,6 +125,7 @@ async function fileUploader({
|
|||||||
}: FileUploaderParams): Promise<string | undefined> {
|
}: FileUploaderParams): Promise<string | undefined> {
|
||||||
const fileCreatedAt = new Date(assetFile.lastModified).toISOString();
|
const fileCreatedAt = new Date(assetFile.lastModified).toISOString();
|
||||||
const $t = get(t);
|
const $t = get(t);
|
||||||
|
const wasInitiallyLoggedIn = !!get(user);
|
||||||
|
|
||||||
uploadAssetsStore.markStarted(deviceAssetId);
|
uploadAssetsStore.markStarted(deviceAssetId);
|
||||||
|
|
||||||
@@ -215,8 +216,9 @@ async function fileUploader({
|
|||||||
|
|
||||||
return responseData.id;
|
return responseData.id;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore errors if the user logs out during uploads
|
// If the user store no longer holds a user, it means they have logged out
|
||||||
if (!get(user)) {
|
// In this case don't bother reporting any errors.
|
||||||
|
if (wasInitiallyLoggedIn && !get(user)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user