@webiny/app-file-manager 6.5.0-beta.3 → 6.5.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +24 -24
- package/presentation/FileDetails/FileDetailsPresenter.test.js.map +1 -1
- package/presentation/FileDetails/components/FileDetailsDrawer.d.ts +2 -2
- package/presentation/FileList/FileListPresenter.test.js.map +1 -1
- package/presentation/FileList/components/BulkActions/BulkActionBar.d.ts +2 -2
- package/presentation/FileList/components/BulkActions/BulkActionDelete.d.ts +2 -2
- package/presentation/FileList/components/BulkActions/BulkActionMove.d.ts +2 -2
- package/presentation/FileList/components/Filters/SubFoldersToggle.d.ts +2 -2
- package/presentation/FileList/components/Filters/TagsFilter.d.ts +2 -2
- package/presentation/FileList/components/Filters/TypeFilter.d.ts +2 -2
- package/presentation/FileList/components/Grid/FileGrid.d.ts +2 -2
- package/presentation/FileList/components/Header/FileManagerHeader.d.ts +2 -2
- package/presentation/FileList/components/Search/SearchBar.d.ts +2 -2
- package/presentation/FileList/components/Table/FileTable.d.ts +2 -2
- package/presentation/FileList/components/Upload/UploadProgress.d.ts +2 -2
- package/presentation/Settings/components/SettingsView.d.ts +2 -2
- package/presentation/config/getThumbnailRenderer.js +1 -1
- package/presentation/config/getThumbnailRenderer.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-file-manager",
|
|
3
|
-
"version": "6.5.0-beta.
|
|
3
|
+
"version": "6.5.0-beta.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -14,39 +14,39 @@
|
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@types/react": "18.3.31",
|
|
17
|
-
"@webiny/admin-ui": "6.5.0-beta.
|
|
18
|
-
"@webiny/app": "6.5.0-beta.
|
|
19
|
-
"@webiny/app-aco": "6.5.0-beta.
|
|
20
|
-
"@webiny/app-admin": "6.5.0-beta.
|
|
21
|
-
"@webiny/app-headless-cms": "6.5.0-beta.
|
|
22
|
-
"@webiny/app-headless-cms-common": "6.5.0-beta.
|
|
23
|
-
"@webiny/app-websockets": "6.5.0-beta.
|
|
24
|
-
"@webiny/di": "1.0
|
|
25
|
-
"@webiny/feature": "6.5.0-beta.
|
|
26
|
-
"@webiny/form": "6.5.0-beta.
|
|
27
|
-
"@webiny/icons": "6.5.0-beta.
|
|
28
|
-
"@webiny/plugins": "6.5.0-beta.
|
|
29
|
-
"@webiny/react-composition": "6.5.0-beta.
|
|
30
|
-
"@webiny/react-properties": "6.5.0-beta.
|
|
31
|
-
"@webiny/sdk": "6.5.0-beta.
|
|
32
|
-
"@webiny/validation": "6.5.0-beta.
|
|
17
|
+
"@webiny/admin-ui": "6.5.0-beta.5",
|
|
18
|
+
"@webiny/app": "6.5.0-beta.5",
|
|
19
|
+
"@webiny/app-aco": "6.5.0-beta.5",
|
|
20
|
+
"@webiny/app-admin": "6.5.0-beta.5",
|
|
21
|
+
"@webiny/app-headless-cms": "6.5.0-beta.5",
|
|
22
|
+
"@webiny/app-headless-cms-common": "6.5.0-beta.5",
|
|
23
|
+
"@webiny/app-websockets": "6.5.0-beta.5",
|
|
24
|
+
"@webiny/di": "1.1.0",
|
|
25
|
+
"@webiny/feature": "6.5.0-beta.5",
|
|
26
|
+
"@webiny/form": "6.5.0-beta.5",
|
|
27
|
+
"@webiny/icons": "6.5.0-beta.5",
|
|
28
|
+
"@webiny/plugins": "6.5.0-beta.5",
|
|
29
|
+
"@webiny/react-composition": "6.5.0-beta.5",
|
|
30
|
+
"@webiny/react-properties": "6.5.0-beta.5",
|
|
31
|
+
"@webiny/sdk": "6.5.0-beta.5",
|
|
32
|
+
"@webiny/validation": "6.5.0-beta.5",
|
|
33
33
|
"bytes": "3.1.2",
|
|
34
|
-
"dayjs": "1.11.
|
|
34
|
+
"dayjs": "1.11.23",
|
|
35
35
|
"lodash": "4.18.1",
|
|
36
36
|
"mime": "4.1.0",
|
|
37
|
-
"minimatch": "10.2.
|
|
38
|
-
"mobx": "
|
|
39
|
-
"mobx-react-lite": "
|
|
37
|
+
"minimatch": "10.2.6",
|
|
38
|
+
"mobx": "7.0.5",
|
|
39
|
+
"mobx-react-lite": "5.1.0",
|
|
40
40
|
"react": "18.3.1",
|
|
41
41
|
"react-dom": "18.3.1",
|
|
42
42
|
"react-lazy-load": "4.0.1",
|
|
43
|
-
"zod": "4.
|
|
43
|
+
"zod": "4.6.5"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@webiny/build-tools": "6.5.0-beta.
|
|
46
|
+
"@webiny/build-tools": "6.5.0-beta.5",
|
|
47
47
|
"rimraf": "6.1.3",
|
|
48
48
|
"typescript": "7.0.2",
|
|
49
|
-
"vitest": "
|
|
49
|
+
"vitest": "5.0.2"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/FileDetails/FileDetailsPresenter.test.js","sources":["../../../src/presentation/FileDetails/FileDetailsPresenter.test.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { GetFileUseCase } from \"../../features/getFile/abstractions.js\";\nimport { UpdateFileUseCase } from \"../../features/updateFile/abstractions.js\";\nimport { DeleteFileUseCase } from \"../../features/deleteFile/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormVM } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { FileManagerPermissions } from \"../../features/permissions/abstractions.js\";\nimport { GetSettingsRepository } from \"../../features/settings/abstractions.js\";\nimport { FileDetailsPresenter as Abstraction, type IFileDetailsPresenter } from \"./abstractions.js\";\nimport { FileDetailsPresenter } from \"./FileDetailsPresenter.js\";\nimport { WcpService } from \"@webiny/app-admin/features/wcp/abstractions.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createMockFormModel(overrides?: Partial<IFormVM>): IFormModel {\n const vm: IFormVM = {\n layout: [],\n errors: [],\n hasErrors: false,\n isDirty: false,\n isValid: true,\n submitCount: 0,\n focusField: vi.fn(),\n getData: vi.fn(() => ({})),\n setData: vi.fn(),\n ...overrides\n };\n\n const data: Record<string, unknown> = {};\n\n return {\n field: vi.fn().mockReturnValue({ setDisabled: vi.fn() }) as any,\n fields: vi.fn() as any,\n layout: vi.fn() as any,\n getData: vi.fn(() => ({ ...data })),\n setData: vi.fn((incoming: Record<string, unknown>) => {\n Object.assign(data, incoming);\n }),\n reset: vi.fn(),\n validate: vi.fn().mockResolvedValue(true),\n submit: vi.fn().mockResolvedValue({ ...data }),\n get isDirty() {\n return vm.isDirty;\n },\n get isValid() {\n return vm.isValid;\n },\n get errors() {\n return vm.errors;\n },\n get vm() {\n return vm;\n }\n } as unknown as IFormModel;\n}\n\nfunction createMockFormModelFactory(): FormModelFactory.Interface {\n const mockForm = createMockFormModel();\n return {\n create: vi.fn().mockReturnValue(mockForm)\n };\n}\n\nfunction createMockGetFileUseCase(): GetFileUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({ success: true, file: createTestFile() })\n };\n}\n\nfunction createMockUpdateFileUseCase(): UpdateFileUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({ success: true, file: createTestFile() })\n };\n}\n\nfunction createMockDeleteFileUseCase(): DeleteFileUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({ success: true })\n };\n}\n\nfunction createMockPermissions(): FileManagerPermissions.Interface {\n return {\n canAccess: vi.fn().mockReturnValue(true),\n canRead: vi.fn().mockReturnValue(true),\n canCreate: vi.fn().mockReturnValue(true),\n canEdit: vi.fn().mockReturnValue(true),\n canDelete: vi.fn().mockReturnValue(false),\n canAction: vi.fn().mockReturnValue(true)\n } as unknown as FileManagerPermissions.Interface;\n}\n\nfunction createMockSettingsRepository(): GetSettingsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }),\n save: vi.fn().mockImplementation(async (data: Record<string, unknown>) => data),\n settings: {\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }\n };\n}\n\nfunction createMockWcpService(canUsePrivateFiles = true): WcpService.Interface {\n return {\n getProject: vi.fn().mockReturnValue({\n canUsePrivateFiles: vi.fn().mockReturnValue(canUsePrivateFiles)\n }),\n isLoaded: vi.fn().mockReturnValue(true),\n canUseFeature: vi.fn().mockReturnValue(false),\n loadProject: vi.fn().mockResolvedValue(undefined)\n } as unknown as WcpService.Interface;\n}\n\nfunction createTestFile(overrides?: Partial<FmFile>): FmFile {\n return {\n id: \"file-1\",\n name: \"photo.jpg\",\n key: \"files/photo.jpg\",\n src: \"https://cdn.example.com/files/photo.jpg\",\n type: \"image/jpeg\",\n size: 12345,\n metadata: {},\n tags: [\"nature\", \"landscape\"],\n createdOn: \"2025-01-01T00:00:00Z\",\n savedOn: \"2025-01-01T00:00:00Z\",\n createdBy: { id: \"user-1\", displayName: \"Test User\", type: \"admin\" },\n savedBy: { id: \"user-1\", displayName: \"Test User\", type: \"admin\" },\n location: { folderId: \"root\" },\n accessControl: { type: \"public\" },\n ...overrides\n };\n}\n\n// ---------------------------------------------------------------------------\n// Container setup\n// ---------------------------------------------------------------------------\n\ninterface Mocks {\n getFileUseCase: GetFileUseCase.Interface;\n updateFileUseCase: UpdateFileUseCase.Interface;\n deleteFileUseCase: DeleteFileUseCase.Interface;\n formModelFactory: FormModelFactory.Interface;\n permissions: FileManagerPermissions.Interface;\n settingsRepository: GetSettingsRepository.Interface;\n wcpService: WcpService.Interface;\n}\n\nfunction createMocks(canUsePrivateFiles = true): Mocks {\n return {\n getFileUseCase: createMockGetFileUseCase(),\n updateFileUseCase: createMockUpdateFileUseCase(),\n deleteFileUseCase: createMockDeleteFileUseCase(),\n formModelFactory: createMockFormModelFactory(),\n permissions: createMockPermissions(),\n settingsRepository: createMockSettingsRepository(),\n wcpService: createMockWcpService(canUsePrivateFiles)\n };\n}\n\nfunction createContainer(mocks: Mocks) {\n const container = new Container();\n\n container.registerInstance(GetFileUseCase, mocks.getFileUseCase);\n container.registerInstance(UpdateFileUseCase, mocks.updateFileUseCase);\n container.registerInstance(DeleteFileUseCase, mocks.deleteFileUseCase);\n container.registerInstance(FormModelFactory, mocks.formModelFactory);\n container.registerInstance(FileManagerPermissions, mocks.permissions);\n container.registerInstance(GetSettingsRepository, mocks.settingsRepository);\n container.registerInstance(WcpService, mocks.wcpService);\n\n // Register the real FileDetailsPresenter implementation.\n container.register(FileDetailsPresenter).inSingletonScope();\n\n return container;\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"FileDetailsPresenter\", () => {\n let mocks: Mocks;\n let presenter: IFileDetailsPresenter;\n\n beforeEach(() => {\n mocks = createMocks();\n const container = createContainer(mocks);\n presenter = container.resolve(Abstraction);\n });\n\n // -----------------------------------------------------------------------\n // Initial state.\n // -----------------------------------------------------------------------\n\n it(\"should have null file and loading=null before loadFile is called\", () => {\n expect(presenter.vm.file).toBeNull();\n expect(presenter.vm.loading).toBeNull();\n });\n\n it(\"should have a form vm with layout and isDirty=false initially\", () => {\n expect(presenter.vm.form).toBeDefined();\n expect(presenter.vm.form.layout).toBeDefined();\n expect(presenter.vm.form.isDirty).toBe(false);\n });\n\n it(\"should have null previewUrl when no file is loaded\", () => {\n expect(presenter.vm.previewUrl).toBeNull();\n });\n\n // -----------------------------------------------------------------------\n // loadFile populates vm with file data and FormModel.\n // -----------------------------------------------------------------------\n\n it(\"should populate vm.file after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.file).not.toBeNull();\n expect(presenter.vm.file!.id).toBe(\"file-1\");\n expect(presenter.vm.file!.name).toBe(\"photo.jpg\");\n });\n\n it(\"should set loading=null after loadFile completes\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.loading).toBeNull();\n });\n\n it(\"should call GetFileUseCase.execute with the file id\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(mocks.getFileUseCase.execute).toHaveBeenCalledWith({ id: \"file-1\" });\n });\n\n it(\"should rebuild the form and call setData after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n // FormModelFactory.create should be called twice: once in constructor, once in loadFile.\n expect(mocks.formModelFactory.create).toHaveBeenCalledTimes(2);\n });\n\n it(\"should have form.isDirty=false after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.form.isDirty).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // Form submission triggers UpdateFileUseCase.\n // -----------------------------------------------------------------------\n\n it(\"should call UpdateFileUseCase.execute when saveFile is called\", async () => {\n await presenter.loadFile(\"file-1\");\n\n // Mock the form submit to return data.\n const mockForm = (mocks.formModelFactory.create as ReturnType<typeof vi.fn>).mock.results[1]\n .value as IFormModel;\n (mockForm.submit as ReturnType<typeof vi.fn>).mockResolvedValue({\n name: \"updated.jpg\",\n tags: [\"updated\"],\n accessControl: \"private-authenticated\"\n });\n\n await presenter.saveFile();\n\n expect(mocks.updateFileUseCase.execute).toHaveBeenCalledWith({\n id: \"file-1\",\n data: {\n name: \"updated.jpg\",\n tags: [\"updated\"],\n accessControl: { type: \"private-authenticated\" }\n }\n });\n });\n\n it(\"should not call UpdateFileUseCase when no file is loaded\", async () => {\n await presenter.saveFile();\n\n expect(mocks.updateFileUseCase.execute).not.toHaveBeenCalled();\n });\n\n it(\"should not call UpdateFileUseCase when form submit returns false\", async () => {\n await presenter.loadFile(\"file-1\");\n\n // Mock the form submit to return false (validation failure).\n const mockForm = (mocks.formModelFactory.create as ReturnType<typeof vi.fn>).mock.results[1]\n .value as IFormModel;\n (mockForm.submit as ReturnType<typeof vi.fn>).mockResolvedValue(false);\n\n await presenter.saveFile();\n\n expect(mocks.updateFileUseCase.execute).not.toHaveBeenCalled();\n });\n\n // -----------------------------------------------------------------------\n // Permission flags control action visibility.\n // -----------------------------------------------------------------------\n\n it(\"should expose permission flags in vm.permissions\", () => {\n expect(presenter.vm.permissions.canEdit).toBe(true);\n expect(presenter.vm.permissions.canDelete).toBe(false);\n });\n\n it(\"should reflect updated permission mock values\", () => {\n // Override permissions to both false.\n (mocks.permissions.canEdit as ReturnType<typeof vi.fn>).mockReturnValue(false);\n (mocks.permissions.canDelete as ReturnType<typeof vi.fn>).mockReturnValue(true);\n\n expect(presenter.vm.permissions.canEdit).toBe(false);\n expect(presenter.vm.permissions.canDelete).toBe(true);\n });\n\n // -----------------------------------------------------------------------\n // previewUrl construction from srcPrefix + key.\n // -----------------------------------------------------------------------\n\n it(\"should construct previewUrl from srcPrefix + file.key after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.previewUrl).toBe(\"https://cdn.example.com/files/photo.jpg\");\n });\n\n it(\"should return null previewUrl when file has no key\", async () => {\n (mocks.getFileUseCase.execute as ReturnType<typeof vi.fn>).mockResolvedValue({\n success: true,\n file: createTestFile({ key: undefined })\n });\n\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.previewUrl).toBeNull();\n });\n\n // -----------------------------------------------------------------------\n // Loading state transitions.\n // -----------------------------------------------------------------------\n\n it(\"should set loading=true during loadFile and false after\", async () => {\n // Capture loading state during execution.\n let loadingDuringExecution: string | null = null;\n\n (mocks.getFileUseCase.execute as ReturnType<typeof vi.fn>).mockImplementation(async () => {\n loadingDuringExecution = presenter.vm.loading;\n return { success: true, file: createTestFile() };\n });\n\n await presenter.loadFile(\"file-1\");\n\n expect(loadingDuringExecution).toBe(\"Loading file...\");\n expect(presenter.vm.loading).toBeNull();\n });\n\n // -------------------------------------------------------------------\n // When Private Files is NOT licensed.\n // -------------------------------------------------------------------\n\n describe(\"when Private Files is NOT licensed\", () => {\n let unlicensedMocks: Mocks;\n let unlicensedPresenter: IFileDetailsPresenter;\n\n beforeEach(() => {\n unlicensedMocks = createMocks(false);\n const container = createContainer(unlicensedMocks);\n unlicensedPresenter = container.resolve(Abstraction);\n });\n\n it(\"should NOT include accessControl in the save payload\", async () => {\n await unlicensedPresenter.loadFile(\"file-1\");\n\n const mockForm = (unlicensedMocks.formModelFactory.create as ReturnType<typeof vi.fn>)\n .mock.results[1].value as IFormModel;\n (mockForm.submit as ReturnType<typeof vi.fn>).mockResolvedValue({\n name: \"updated.jpg\",\n description: \"\",\n tags: [\"updated\"]\n });\n\n await unlicensedPresenter.saveFile();\n\n const callArgs = (unlicensedMocks.updateFileUseCase.execute as ReturnType<typeof vi.fn>)\n .mock.calls[0][0];\n expect(callArgs.data).not.toHaveProperty(\"accessControl\");\n });\n\n it(\"should NOT set accessControl in form data during loadFile\", async () => {\n await unlicensedPresenter.loadFile(\"file-1\");\n\n const mockForm = (unlicensedMocks.formModelFactory.create as ReturnType<typeof vi.fn>)\n .mock.results[1].value as IFormModel;\n const setDataCall = (mockForm.setData as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(setDataCall).not.toHaveProperty(\"accessControl\");\n });\n\n it(\"should NOT disable accessControl field when user lacks edit permission\", async () => {\n (unlicensedMocks.permissions.canEdit as ReturnType<typeof vi.fn>).mockReturnValue(\n false\n );\n\n await unlicensedPresenter.loadFile(\"file-1\");\n\n const mockForm = (unlicensedMocks.formModelFactory.create as ReturnType<typeof vi.fn>)\n .mock.results[1].value as IFormModel;\n expect(mockForm.field).toHaveBeenCalledTimes(3);\n expect(mockForm.field).not.toHaveBeenCalledWith(\"accessControl\");\n });\n });\n});\n"],"names":["createMockFormModel","overrides","vm","vi","data","incoming","Object","createMockFormModelFactory","mockForm","createMockGetFileUseCase","createTestFile","createMockUpdateFileUseCase","createMockDeleteFileUseCase","createMockPermissions","createMockSettingsRepository","createMockWcpService","canUsePrivateFiles","undefined","createMocks","createContainer","mocks","container","Container","GetFileUseCase","UpdateFileUseCase","DeleteFileUseCase","FormModelFactory","FileManagerPermissions","GetSettingsRepository","WcpService","FileDetailsPresenter","describe","presenter","beforeEach","Abstraction","it","expect","loadingDuringExecution","unlicensedMocks","unlicensedPresenter","callArgs","setDataCall"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"presentation/FileDetails/FileDetailsPresenter.test.js","sources":["../../../src/presentation/FileDetails/FileDetailsPresenter.test.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { GetFileUseCase } from \"../../features/getFile/abstractions.js\";\nimport { UpdateFileUseCase } from \"../../features/updateFile/abstractions.js\";\nimport { DeleteFileUseCase } from \"../../features/deleteFile/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormVM } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { FileManagerPermissions } from \"../../features/permissions/abstractions.js\";\nimport { GetSettingsRepository } from \"../../features/settings/abstractions.js\";\nimport { FileDetailsPresenter as Abstraction, type IFileDetailsPresenter } from \"./abstractions.js\";\nimport { FileDetailsPresenter } from \"./FileDetailsPresenter.js\";\nimport { WcpService } from \"@webiny/app-admin/features/wcp/abstractions.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createMockFormModel(overrides?: Partial<IFormVM>): IFormModel {\n const vm: IFormVM = {\n layout: [],\n errors: [],\n hasErrors: false,\n isDirty: false,\n isValid: true,\n submitCount: 0,\n focusField: vi.fn(),\n getData: vi.fn(() => ({})),\n setData: vi.fn(),\n ...overrides\n };\n\n const data: Record<string, unknown> = {};\n\n return {\n field: vi.fn().mockReturnValue({ setDisabled: vi.fn() }) as any,\n fields: vi.fn() as any,\n layout: vi.fn() as any,\n getData: vi.fn(() => ({ ...data })),\n setData: vi.fn((incoming: Record<string, unknown>) => {\n Object.assign(data, incoming);\n }),\n reset: vi.fn(),\n validate: vi.fn().mockResolvedValue(true),\n submit: vi.fn().mockResolvedValue({ ...data }),\n get isDirty() {\n return vm.isDirty;\n },\n get isValid() {\n return vm.isValid;\n },\n get errors() {\n return vm.errors;\n },\n get vm() {\n return vm;\n }\n } as unknown as IFormModel;\n}\n\nfunction createMockFormModelFactory(): FormModelFactory.Interface {\n const mockForm = createMockFormModel();\n return {\n create: vi.fn().mockReturnValue(mockForm)\n };\n}\n\nfunction createMockGetFileUseCase(): GetFileUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({ success: true, file: createTestFile() })\n };\n}\n\nfunction createMockUpdateFileUseCase(): UpdateFileUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({ success: true, file: createTestFile() })\n };\n}\n\nfunction createMockDeleteFileUseCase(): DeleteFileUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({ success: true })\n };\n}\n\nfunction createMockPermissions(): FileManagerPermissions.Interface {\n return {\n canAccess: vi.fn().mockReturnValue(true),\n canRead: vi.fn().mockReturnValue(true),\n canCreate: vi.fn().mockReturnValue(true),\n canEdit: vi.fn().mockReturnValue(true),\n canDelete: vi.fn().mockReturnValue(false),\n canAction: vi.fn().mockReturnValue(true)\n } as unknown as FileManagerPermissions.Interface;\n}\n\nfunction createMockSettingsRepository(): GetSettingsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }),\n save: vi.fn().mockImplementation(async (data: Record<string, unknown>) => data),\n settings: {\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }\n };\n}\n\nfunction createMockWcpService(canUsePrivateFiles = true): WcpService.Interface {\n return {\n getProject: vi.fn().mockReturnValue({\n canUsePrivateFiles: vi.fn().mockReturnValue(canUsePrivateFiles)\n }),\n isLoaded: vi.fn().mockReturnValue(true),\n canUseFeature: vi.fn().mockReturnValue(false),\n loadProject: vi.fn().mockResolvedValue(undefined)\n } as unknown as WcpService.Interface;\n}\n\nfunction createTestFile(overrides?: Partial<FmFile>): FmFile {\n return {\n id: \"file-1\",\n name: \"photo.jpg\",\n key: \"files/photo.jpg\",\n src: \"https://cdn.example.com/files/photo.jpg\",\n type: \"image/jpeg\",\n size: 12345,\n metadata: {},\n tags: [\"nature\", \"landscape\"],\n createdOn: \"2025-01-01T00:00:00Z\",\n savedOn: \"2025-01-01T00:00:00Z\",\n createdBy: { id: \"user-1\", displayName: \"Test User\", type: \"admin\" },\n savedBy: { id: \"user-1\", displayName: \"Test User\", type: \"admin\" },\n location: { folderId: \"root\" },\n accessControl: { type: \"public\" },\n ...overrides\n };\n}\n\n// ---------------------------------------------------------------------------\n// Container setup\n// ---------------------------------------------------------------------------\n\ninterface Mocks {\n getFileUseCase: GetFileUseCase.Interface;\n updateFileUseCase: UpdateFileUseCase.Interface;\n deleteFileUseCase: DeleteFileUseCase.Interface;\n formModelFactory: FormModelFactory.Interface;\n permissions: FileManagerPermissions.Interface;\n settingsRepository: GetSettingsRepository.Interface;\n wcpService: WcpService.Interface;\n}\n\nfunction createMocks(canUsePrivateFiles = true): Mocks {\n return {\n getFileUseCase: createMockGetFileUseCase(),\n updateFileUseCase: createMockUpdateFileUseCase(),\n deleteFileUseCase: createMockDeleteFileUseCase(),\n formModelFactory: createMockFormModelFactory(),\n permissions: createMockPermissions(),\n settingsRepository: createMockSettingsRepository(),\n wcpService: createMockWcpService(canUsePrivateFiles)\n };\n}\n\nfunction createContainer(mocks: Mocks) {\n const container = new Container();\n\n container.registerInstance(GetFileUseCase, mocks.getFileUseCase);\n container.registerInstance(UpdateFileUseCase, mocks.updateFileUseCase);\n container.registerInstance(DeleteFileUseCase, mocks.deleteFileUseCase);\n container.registerInstance(FormModelFactory, mocks.formModelFactory);\n container.registerInstance(FileManagerPermissions, mocks.permissions);\n container.registerInstance(GetSettingsRepository, mocks.settingsRepository);\n container.registerInstance(WcpService, mocks.wcpService);\n\n // Register the real FileDetailsPresenter implementation.\n container.register(FileDetailsPresenter).inSingletonScope();\n\n return container;\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"FileDetailsPresenter\", () => {\n let mocks: Mocks;\n let presenter: IFileDetailsPresenter;\n\n beforeEach(() => {\n mocks = createMocks();\n const container = createContainer(mocks);\n presenter = container.resolve(Abstraction);\n });\n\n // -----------------------------------------------------------------------\n // Initial state.\n // -----------------------------------------------------------------------\n\n it(\"should have null file and loading=null before loadFile is called\", () => {\n expect(presenter.vm.file).toBeNull();\n expect(presenter.vm.loading).toBeNull();\n });\n\n it(\"should have a form vm with layout and isDirty=false initially\", () => {\n expect(presenter.vm.form).toBeDefined();\n expect(presenter.vm.form.layout).toBeDefined();\n expect(presenter.vm.form.isDirty).toBe(false);\n });\n\n it(\"should have null previewUrl when no file is loaded\", () => {\n expect(presenter.vm.previewUrl).toBeNull();\n });\n\n // -----------------------------------------------------------------------\n // loadFile populates vm with file data and FormModel.\n // -----------------------------------------------------------------------\n\n it(\"should populate vm.file after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.file).not.toBeNull();\n expect(presenter.vm.file!.id).toBe(\"file-1\");\n expect(presenter.vm.file!.name).toBe(\"photo.jpg\");\n });\n\n it(\"should set loading=null after loadFile completes\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.loading).toBeNull();\n });\n\n it(\"should call GetFileUseCase.execute with the file id\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(mocks.getFileUseCase.execute).toHaveBeenCalledWith({ id: \"file-1\" });\n });\n\n it(\"should rebuild the form and call setData after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n // FormModelFactory.create should be called twice: once in constructor, once in loadFile.\n expect(mocks.formModelFactory.create).toHaveBeenCalledTimes(2);\n });\n\n it(\"should have form.isDirty=false after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.form.isDirty).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // Form submission triggers UpdateFileUseCase.\n // -----------------------------------------------------------------------\n\n it(\"should call UpdateFileUseCase.execute when saveFile is called\", async () => {\n await presenter.loadFile(\"file-1\");\n\n // Mock the form submit to return data.\n const mockForm = (mocks.formModelFactory.create as ReturnType<typeof vi.fn>).mock.results[1]\n .value as IFormModel;\n (mockForm.submit as ReturnType<typeof vi.fn>).mockResolvedValue({\n name: \"updated.jpg\",\n tags: [\"updated\"],\n accessControl: \"private-authenticated\"\n });\n\n await presenter.saveFile();\n\n expect(mocks.updateFileUseCase.execute).toHaveBeenCalledWith({\n id: \"file-1\",\n data: {\n name: \"updated.jpg\",\n tags: [\"updated\"],\n accessControl: { type: \"private-authenticated\" }\n }\n });\n });\n\n it(\"should not call UpdateFileUseCase when no file is loaded\", async () => {\n await presenter.saveFile();\n\n expect(mocks.updateFileUseCase.execute).not.toHaveBeenCalled();\n });\n\n it(\"should not call UpdateFileUseCase when form submit returns false\", async () => {\n await presenter.loadFile(\"file-1\");\n\n // Mock the form submit to return false (validation failure).\n const mockForm = (mocks.formModelFactory.create as ReturnType<typeof vi.fn>).mock.results[1]\n .value as IFormModel;\n (mockForm.submit as ReturnType<typeof vi.fn>).mockResolvedValue(false);\n\n await presenter.saveFile();\n\n expect(mocks.updateFileUseCase.execute).not.toHaveBeenCalled();\n });\n\n // -----------------------------------------------------------------------\n // Permission flags control action visibility.\n // -----------------------------------------------------------------------\n\n it(\"should expose permission flags in vm.permissions\", () => {\n expect(presenter.vm.permissions.canEdit).toBe(true);\n expect(presenter.vm.permissions.canDelete).toBe(false);\n });\n\n it(\"should reflect updated permission mock values\", () => {\n // Override permissions to both false.\n (mocks.permissions.canEdit as ReturnType<typeof vi.fn>).mockReturnValue(false);\n (mocks.permissions.canDelete as ReturnType<typeof vi.fn>).mockReturnValue(true);\n\n expect(presenter.vm.permissions.canEdit).toBe(false);\n expect(presenter.vm.permissions.canDelete).toBe(true);\n });\n\n // -----------------------------------------------------------------------\n // previewUrl construction from srcPrefix + key.\n // -----------------------------------------------------------------------\n\n it(\"should construct previewUrl from srcPrefix + file.key after loadFile\", async () => {\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.previewUrl).toBe(\"https://cdn.example.com/files/photo.jpg\");\n });\n\n it(\"should return null previewUrl when file has no key\", async () => {\n (mocks.getFileUseCase.execute as ReturnType<typeof vi.fn>).mockResolvedValue({\n success: true,\n file: createTestFile({ key: undefined })\n });\n\n await presenter.loadFile(\"file-1\");\n\n expect(presenter.vm.previewUrl).toBeNull();\n });\n\n // -----------------------------------------------------------------------\n // Loading state transitions.\n // -----------------------------------------------------------------------\n\n it(\"should set loading=true during loadFile and false after\", async () => {\n // Capture loading state during execution.\n let loadingDuringExecution: string | null = null;\n\n (mocks.getFileUseCase.execute as ReturnType<typeof vi.fn>).mockImplementation(async () => {\n loadingDuringExecution = presenter.vm.loading;\n return { success: true, file: createTestFile() };\n });\n\n await presenter.loadFile(\"file-1\");\n\n expect(loadingDuringExecution).toBe(\"Loading file...\");\n expect(presenter.vm.loading).toBeNull();\n });\n\n // -------------------------------------------------------------------\n // When Private Files is NOT licensed.\n // -------------------------------------------------------------------\n\n describe(\"when Private Files is NOT licensed\", () => {\n let unlicensedMocks: Mocks;\n let unlicensedPresenter: IFileDetailsPresenter;\n\n beforeEach(() => {\n unlicensedMocks = createMocks(false);\n const container = createContainer(unlicensedMocks);\n unlicensedPresenter = container.resolve(Abstraction);\n });\n\n it(\"should NOT include accessControl in the save payload\", async () => {\n await unlicensedPresenter.loadFile(\"file-1\");\n\n const mockForm = (unlicensedMocks.formModelFactory.create as ReturnType<typeof vi.fn>)\n .mock.results[1].value as IFormModel;\n (mockForm.submit as ReturnType<typeof vi.fn>).mockResolvedValue({\n name: \"updated.jpg\",\n description: \"\",\n tags: [\"updated\"]\n });\n\n await unlicensedPresenter.saveFile();\n\n const callArgs = (unlicensedMocks.updateFileUseCase.execute as ReturnType<typeof vi.fn>)\n .mock.calls[0][0];\n expect(callArgs.data).not.toHaveProperty(\"accessControl\");\n });\n\n it(\"should NOT set accessControl in form data during loadFile\", async () => {\n await unlicensedPresenter.loadFile(\"file-1\");\n\n const mockForm = (unlicensedMocks.formModelFactory.create as ReturnType<typeof vi.fn>)\n .mock.results[1].value as IFormModel;\n const setDataCall = (mockForm.setData as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(setDataCall).not.toHaveProperty(\"accessControl\");\n });\n\n it(\"should NOT disable accessControl field when user lacks edit permission\", async () => {\n (unlicensedMocks.permissions.canEdit as ReturnType<typeof vi.fn>).mockReturnValue(\n false\n );\n\n await unlicensedPresenter.loadFile(\"file-1\");\n\n const mockForm = (unlicensedMocks.formModelFactory.create as ReturnType<typeof vi.fn>)\n .mock.results[1].value as IFormModel;\n expect(mockForm.field).toHaveBeenCalledTimes(3);\n expect(mockForm.field).not.toHaveBeenCalledWith(\"accessControl\");\n });\n });\n});\n"],"names":["createMockFormModel","overrides","vm","vi","data","incoming","Object","createMockFormModelFactory","mockForm","createMockGetFileUseCase","createTestFile","createMockUpdateFileUseCase","createMockDeleteFileUseCase","createMockPermissions","createMockSettingsRepository","createMockWcpService","canUsePrivateFiles","undefined","createMocks","createContainer","mocks","container","Container","GetFileUseCase","UpdateFileUseCase","DeleteFileUseCase","FormModelFactory","FileManagerPermissions","GetSettingsRepository","WcpService","FileDetailsPresenter","describe","presenter","beforeEach","Abstraction","it","expect","loadingDuringExecution","unlicensedMocks","unlicensedPresenter","callArgs","setDataCall"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const FileDetailsDrawer: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const FileDetailsDrawer: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/FileList/FileListPresenter.test.js","sources":["../../../src/presentation/FileList/FileListPresenter.test.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { observable, runInAction } from \"mobx\";\nimport { Container } from \"@webiny/di\";\nimport { ListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { FileManagerPermissions } from \"../../features/permissions/abstractions.js\";\nimport { GetSettingsRepository } from \"../../features/settings/abstractions.js\";\nimport { ListTagsRepository } from \"../../features/tags/abstractions.js\";\nimport { FileUploader } from \"../../features/fileUploader/abstractions.js\";\nimport { LocalStorage } from \"@webiny/app/features/localStorage\";\nimport { ListFilesUseCase } from \"../../features/listFiles/abstractions.js\";\nimport { FilesListCache } from \"../../features/shared/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { FileModelProvider } from \"../../features/fileModel/abstractions.js\";\nimport { FileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport { FileManagerPresenter as Abstraction, type IFileManagerPresenter } from \"./abstractions.js\";\nimport { FileManagerPresenter } from \"./FileManagerPresenter.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createMockListPresenter(): ListPresenter.Interface<FmFile> {\n const vmState = observable({\n rows: [] as FmFile[],\n sort: null as { field: string; direction: \"ASC\" | \"DESC\" } | null,\n filters: {} as Record<string, unknown>,\n search: \"\",\n appliedQuery: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IDataSourceQuery\n | null,\n pagination: {\n hasMore: false,\n loading: false,\n loadingMore: false,\n totalCount: 0,\n currentCount: 0\n },\n selection: {\n selectedIds: new Set<string>(),\n selectedCount: 0,\n allSelected: false,\n label: \"\"\n },\n showingFilters: false,\n empty: true,\n emptyWithFilters: false,\n error: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IListError\n | null\n });\n\n return {\n get vm() {\n return vmState;\n },\n actions: {\n search: { set: vi.fn(), clear: vi.fn() },\n sort: { set: vi.fn(), toggle: vi.fn() },\n filter: {\n set: vi.fn(),\n clear: vi.fn(),\n clearAll: vi.fn(),\n show: vi.fn(),\n hide: vi.fn()\n },\n selection: {\n toggle: vi.fn(),\n selectRangeTo: vi.fn(),\n selectAll: vi.fn(),\n deselectAll: vi.fn(),\n selectRows: vi.fn(),\n isSelected: vi.fn().mockReturnValue(false)\n },\n loadMore: vi.fn().mockResolvedValue(undefined),\n refresh: vi.fn().mockResolvedValue(undefined)\n },\n init: vi.fn()\n };\n}\n\nfunction createMockFolderTreePresenter(): FolderTreePresenter.Interface {\n const state = observable({\n folders: [],\n tree: [],\n currentFolderId: null as string | null,\n currentFolder: null,\n loading: false,\n operation: { active: false, mode: null },\n isRootFolder: true,\n currentFolderTitle: \"All Files\",\n childFolders: [],\n loadingNodeIds: []\n });\n\n return {\n get vm() {\n return state;\n },\n selectFolder: vi.fn(),\n createFolder: vi.fn(),\n editFolder: vi.fn(),\n deleteFolder: vi.fn().mockResolvedValue(undefined),\n moveFolder: vi.fn().mockResolvedValue(undefined),\n loadChildFolders: vi.fn().mockResolvedValue(undefined),\n canManageStructure: vi.fn().mockReturnValue(true),\n getAncestorIds: vi.fn().mockReturnValue([]),\n submitOperation: vi.fn().mockResolvedValue(true),\n cancelOperation: vi.fn(),\n onFolderChange: vi.fn().mockReturnValue(() => {})\n };\n}\n\nfunction createMockPermissions(): FileManagerPermissions.Interface {\n return {\n canAccess: vi.fn().mockReturnValue(true),\n canRead: vi.fn().mockReturnValue(true),\n canCreate: vi.fn().mockReturnValue(true),\n canEdit: vi.fn().mockReturnValue(false),\n canDelete: vi.fn().mockReturnValue(false),\n canAction: vi.fn().mockReturnValue(true)\n } as unknown as FileManagerPermissions.Interface;\n}\n\nfunction createMockSettingsRepository(): GetSettingsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }),\n save: vi.fn().mockImplementation(async (data: Record<string, unknown>) => data),\n settings: null\n };\n}\n\nfunction createMockTagsRepository(): ListTagsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue([]),\n tags: [{ tag: \"photo\", count: 5 }]\n };\n}\n\nfunction createMockFileUploader(): FileUploader.Interface {\n return {\n vm: {\n jobs: [],\n overallProgress: { sent: 0, total: 0, percentage: 0 },\n isUploading: false,\n completedCount: 0,\n failedCount: 0\n },\n upload: vi.fn().mockResolvedValue(undefined),\n uploadMany: vi.fn().mockResolvedValue(undefined),\n abort: vi.fn(),\n clear: vi.fn()\n };\n}\n\nfunction createMockLocalStorage(): LocalStorage.Interface {\n const store = new Map<string, unknown>();\n return {\n get: vi.fn((key: string) => store.get(key)) as LocalStorage.Interface[\"get\"],\n set: vi.fn(<T>(key: string, value: T): void => {\n store.set(key, value);\n }),\n remove: vi.fn((key: string) => {\n store.delete(key);\n }),\n clear: vi.fn(() => store.clear()),\n keys: vi.fn(() => Array.from(store.keys()))\n };\n}\n\nfunction createMockListFilesUseCase(): ListFilesUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n })\n };\n}\n\nfunction createMockGetDescendantFoldersUseCase(): GetDescendantFoldersUseCase.Interface {\n return {\n execute: vi.fn().mockReturnValue([])\n };\n}\n\nfunction createMockFileDetailsPresenter(): IFileDetailsPresenter {\n return {\n vm: {\n file: null,\n loading: null,\n form: {\n layout: [],\n errors: [],\n hasErrors: false,\n isDirty: false,\n isValid: null,\n submitCount: 0,\n focusField: vi.fn(),\n getData: vi.fn(() => ({})),\n setData: vi.fn()\n },\n previewUrl: null,\n permissions: { canEdit: true, canDelete: true }\n },\n loadFile: vi.fn().mockResolvedValue(undefined),\n saveFile: vi.fn().mockResolvedValue(undefined),\n setFile: vi.fn()\n };\n}\n\n// ---------------------------------------------------------------------------\n// Container setup\n// ---------------------------------------------------------------------------\n\ninterface Mocks {\n listPresenter: ListPresenter.Interface<FmFile>;\n folderTreePresenter: FolderTreePresenter.Interface;\n fileDetailsPresenter: IFileDetailsPresenter;\n permissions: FileManagerPermissions.Interface;\n settingsRepository: GetSettingsRepository.Interface;\n tagsRepository: ListTagsRepository.Interface;\n fileUploader: FileUploader.Interface;\n localStorage: LocalStorage.Interface;\n listFilesUseCase: ListFilesUseCase.Interface;\n cache: ListCache<FmFile>;\n getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface;\n fileModelProvider: FileModelProvider.Interface;\n}\n\nfunction createMocks(): Mocks {\n return {\n listPresenter: createMockListPresenter(),\n folderTreePresenter: createMockFolderTreePresenter(),\n fileDetailsPresenter: createMockFileDetailsPresenter(),\n permissions: createMockPermissions(),\n settingsRepository: createMockSettingsRepository(),\n tagsRepository: createMockTagsRepository(),\n fileUploader: createMockFileUploader(),\n localStorage: createMockLocalStorage(),\n listFilesUseCase: createMockListFilesUseCase(),\n cache: new ListCache<FmFile>(),\n getDescendantFoldersUseCase: createMockGetDescendantFoldersUseCase(),\n fileModelProvider: {\n getModel: vi.fn().mockResolvedValue({ fields: [] })\n }\n };\n}\n\nfunction createContainer(mocks: Mocks) {\n const container = new Container();\n\n container.registerInstance(ListPresenter, mocks.listPresenter);\n container.registerInstance(FolderTreePresenter, mocks.folderTreePresenter);\n container.registerInstance(FileDetailsPresenter, mocks.fileDetailsPresenter);\n container.registerInstance(FileManagerPermissions, mocks.permissions);\n container.registerInstance(GetSettingsRepository, mocks.settingsRepository);\n container.registerInstance(ListTagsRepository, mocks.tagsRepository);\n container.registerInstance(FileUploader, mocks.fileUploader);\n container.registerInstance(LocalStorage, mocks.localStorage);\n container.registerInstance(ListFilesUseCase, mocks.listFilesUseCase);\n container.registerInstance(FilesListCache, mocks.cache);\n container.registerInstance(GetDescendantFoldersUseCase, mocks.getDescendantFoldersUseCase);\n container.registerInstance(FileModelProvider, mocks.fileModelProvider);\n\n // Register the real FileListPresenter implementation.\n container.register(FileManagerPresenter).inSingletonScope();\n\n return container;\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"FileListPresenter\", () => {\n let mocks: Mocks;\n let presenter: IFileManagerPresenter;\n\n beforeEach(() => {\n mocks = createMocks();\n const container = createContainer(mocks);\n presenter = container.resolve(Abstraction);\n });\n\n // -----------------------------------------------------------------------\n // Composition: ListPresenter and FolderTreePresenter initialized.\n // -----------------------------------------------------------------------\n\n it(\"should call listPresenter.init with a DataSource and initialSort on init()\", () => {\n presenter.init();\n\n expect(mocks.listPresenter.init).toHaveBeenCalledTimes(1);\n const config = (mocks.listPresenter.init as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(config.dataSource).toBeDefined();\n expect(config.initialSort).toEqual({ field: \"createdOn\", direction: \"DESC\" });\n });\n\n it(\"should forward ListPresenter.vm data as vm.list\", () => {\n presenter.init();\n expect(presenter.vm.list.rows).toEqual(mocks.listPresenter.vm.rows);\n expect(presenter.vm.list.sort).toEqual(mocks.listPresenter.vm.sort);\n expect(presenter.vm.list.search).toBe(mocks.listPresenter.vm.search);\n expect(presenter.vm.list.empty).toBe(mocks.listPresenter.vm.empty);\n });\n\n it(\"should forward FolderTreePresenter.vm as vm.folders\", () => {\n presenter.init();\n expect(presenter.vm.folders).toBe(mocks.folderTreePresenter.vm);\n });\n\n // -----------------------------------------------------------------------\n // Folder change wiring.\n // -----------------------------------------------------------------------\n\n it(\"should set folderId filter when folder changes\", async () => {\n presenter.init();\n\n // Simulate folder selection via MobX observable change.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-abc\";\n });\n\n // MobX reaction fires synchronously in the same tick after runInAction.\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\n \"folderId\",\n \"folder-abc\"\n );\n });\n\n it(\"should set folderId to root when folder is set to null\", () => {\n presenter.init();\n\n // First set a folder.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-1\";\n });\n\n // Then clear it.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = null;\n });\n\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\"folderId\", \"root\");\n });\n\n // -----------------------------------------------------------------------\n // Permission flags forwarded to vm.\n // -----------------------------------------------------------------------\n\n it(\"should expose permission flags in vm.permissions\", () => {\n presenter.init();\n\n expect(presenter.vm.permissions.canRead).toBe(true);\n expect(presenter.vm.permissions.canCreate).toBe(true);\n expect(presenter.vm.permissions.canEdit).toBe(false);\n expect(presenter.vm.permissions.canDelete).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // View mode persistence via LocalStorage.\n // -----------------------------------------------------------------------\n\n it(\"should default viewMode to 'grid'\", () => {\n expect(presenter.vm.viewMode).toBe(\"grid\");\n });\n\n it(\"should update viewMode and persist to localStorage\", () => {\n presenter.actions.setViewMode(\"grid\");\n\n expect(presenter.vm.viewMode).toBe(\"grid\");\n expect(mocks.localStorage.set).toHaveBeenCalledWith(\"fm:viewMode\", \"grid\");\n });\n\n it(\"should restore viewMode from localStorage on construction\", () => {\n // Pre-seed localStorage with \"grid\" before creating the presenter.\n const seededMocks = createMocks();\n (seededMocks.localStorage.get as ReturnType<typeof vi.fn>).mockReturnValue(\"grid\");\n\n const container = createContainer(seededMocks);\n const seededPresenter: IFileManagerPresenter = container.resolve(Abstraction);\n\n expect(seededPresenter.vm.viewMode).toBe(\"grid\");\n });\n\n // -----------------------------------------------------------------------\n // Upload action.\n // -----------------------------------------------------------------------\n\n it(\"should call fileUploader.uploadMany when actions.upload is called\", async () => {\n presenter.init();\n\n const file1 = {\n id: \"f1\",\n name: \"test.txt\",\n type: \"text/plain\",\n size: 7,\n src: { file: new File([\"content\"], \"test.txt\", { type: \"text/plain\" }), base64: null }\n };\n const file2 = {\n id: \"f2\",\n name: \"photo.png\",\n type: \"image/png\",\n size: 3,\n src: { file: new File([\"img\"], \"photo.png\", { type: \"image/png\" }), base64: null }\n };\n\n await presenter.actions.upload([file1, file2]);\n\n expect(mocks.fileUploader.uploadMany).toHaveBeenCalledTimes(1);\n const args = (mocks.fileUploader.uploadMany as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(args).toHaveLength(2);\n expect(args[0].data.name).toBe(\"test.txt\");\n expect(args[0].data.type).toBe(\"text/plain\");\n expect(args[1].data.name).toBe(\"photo.png\");\n expect(args[1].data.type).toBe(\"image/png\");\n });\n\n // -----------------------------------------------------------------------\n // loading: true only during initial load (no rows yet).\n // -----------------------------------------------------------------------\n\n it(\"should be loading when pagination is loading and no rows exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(true);\n });\n\n it(\"should not be loading when rows already exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n it(\"should not be loading when pagination is not loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // empty: accounts for both files and child folders.\n // -----------------------------------------------------------------------\n\n it(\"should be empty when no files and no child folders\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n it(\"should not be empty when there are files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty when there are child folders but no files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty while loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should be empty when child folders exist but folders are hidden (search active)\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n // -----------------------------------------------------------------------\n // showFolders computed from appliedQuery.\n // -----------------------------------------------------------------------\n\n it(\"should show folders when appliedQuery is null\", () => {\n presenter.init();\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should show folders when appliedQuery has no search and only folderId filter\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should hide folders when appliedQuery has a search\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should hide folders when appliedQuery has non-folderId filters\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", tags: [\"photo\"] }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should show folders again when appliedQuery filters are cleared\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", type: \"image\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n});\n"],"names":["createMockListPresenter","vmState","observable","Set","vi","undefined","createMockFolderTreePresenter","state","createMockPermissions","createMockSettingsRepository","data","createMockTagsRepository","createMockFileUploader","createMockLocalStorage","store","Map","key","value","Array","createMockListFilesUseCase","createMockGetDescendantFoldersUseCase","createMockFileDetailsPresenter","createMocks","ListCache","createContainer","mocks","container","Container","ListPresenter","FolderTreePresenter","FileDetailsPresenter","FileManagerPermissions","GetSettingsRepository","ListTagsRepository","FileUploader","LocalStorage","ListFilesUseCase","FilesListCache","GetDescendantFoldersUseCase","FileModelProvider","FileManagerPresenter","describe","presenter","beforeEach","Abstraction","it","expect","config","runInAction","seededMocks","seededPresenter","file1","File","file2","args"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"presentation/FileList/FileListPresenter.test.js","sources":["../../../src/presentation/FileList/FileListPresenter.test.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { observable, runInAction } from \"mobx\";\nimport { Container } from \"@webiny/di\";\nimport { ListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { FileManagerPermissions } from \"../../features/permissions/abstractions.js\";\nimport { GetSettingsRepository } from \"../../features/settings/abstractions.js\";\nimport { ListTagsRepository } from \"../../features/tags/abstractions.js\";\nimport { FileUploader } from \"../../features/fileUploader/abstractions.js\";\nimport { LocalStorage } from \"@webiny/app/features/localStorage\";\nimport { ListFilesUseCase } from \"../../features/listFiles/abstractions.js\";\nimport { FilesListCache } from \"../../features/shared/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { FileModelProvider } from \"../../features/fileModel/abstractions.js\";\nimport { FileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport { FileManagerPresenter as Abstraction, type IFileManagerPresenter } from \"./abstractions.js\";\nimport { FileManagerPresenter } from \"./FileManagerPresenter.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createMockListPresenter(): ListPresenter.Interface<FmFile> {\n const vmState = observable({\n rows: [] as FmFile[],\n sort: null as { field: string; direction: \"ASC\" | \"DESC\" } | null,\n filters: {} as Record<string, unknown>,\n search: \"\",\n appliedQuery: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IDataSourceQuery\n | null,\n pagination: {\n hasMore: false,\n loading: false,\n loadingMore: false,\n totalCount: 0,\n currentCount: 0\n },\n selection: {\n selectedIds: new Set<string>(),\n selectedCount: 0,\n allSelected: false,\n label: \"\"\n },\n showingFilters: false,\n empty: true,\n emptyWithFilters: false,\n error: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IListError\n | null\n });\n\n return {\n get vm() {\n return vmState;\n },\n actions: {\n search: { set: vi.fn(), clear: vi.fn() },\n sort: { set: vi.fn(), toggle: vi.fn() },\n filter: {\n set: vi.fn(),\n clear: vi.fn(),\n clearAll: vi.fn(),\n show: vi.fn(),\n hide: vi.fn()\n },\n selection: {\n toggle: vi.fn(),\n selectRangeTo: vi.fn(),\n selectAll: vi.fn(),\n deselectAll: vi.fn(),\n selectRows: vi.fn(),\n isSelected: vi.fn().mockReturnValue(false)\n },\n loadMore: vi.fn().mockResolvedValue(undefined),\n refresh: vi.fn().mockResolvedValue(undefined)\n },\n init: vi.fn()\n };\n}\n\nfunction createMockFolderTreePresenter(): FolderTreePresenter.Interface {\n const state = observable({\n folders: [],\n tree: [],\n currentFolderId: null as string | null,\n currentFolder: null,\n loading: false,\n operation: { active: false, mode: null },\n isRootFolder: true,\n currentFolderTitle: \"All Files\",\n childFolders: [],\n loadingNodeIds: []\n });\n\n return {\n get vm() {\n return state;\n },\n selectFolder: vi.fn(),\n createFolder: vi.fn(),\n editFolder: vi.fn(),\n deleteFolder: vi.fn().mockResolvedValue(undefined),\n moveFolder: vi.fn().mockResolvedValue(undefined),\n loadChildFolders: vi.fn().mockResolvedValue(undefined),\n canManageStructure: vi.fn().mockReturnValue(true),\n getAncestorIds: vi.fn().mockReturnValue([]),\n submitOperation: vi.fn().mockResolvedValue(true),\n cancelOperation: vi.fn(),\n onFolderChange: vi.fn().mockReturnValue(() => {})\n };\n}\n\nfunction createMockPermissions(): FileManagerPermissions.Interface {\n return {\n canAccess: vi.fn().mockReturnValue(true),\n canRead: vi.fn().mockReturnValue(true),\n canCreate: vi.fn().mockReturnValue(true),\n canEdit: vi.fn().mockReturnValue(false),\n canDelete: vi.fn().mockReturnValue(false),\n canAction: vi.fn().mockReturnValue(true)\n } as unknown as FileManagerPermissions.Interface;\n}\n\nfunction createMockSettingsRepository(): GetSettingsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }),\n save: vi.fn().mockImplementation(async (data: Record<string, unknown>) => data),\n settings: null\n };\n}\n\nfunction createMockTagsRepository(): ListTagsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue([]),\n tags: [{ tag: \"photo\", count: 5 }]\n };\n}\n\nfunction createMockFileUploader(): FileUploader.Interface {\n return {\n vm: {\n jobs: [],\n overallProgress: { sent: 0, total: 0, percentage: 0 },\n isUploading: false,\n completedCount: 0,\n failedCount: 0\n },\n upload: vi.fn().mockResolvedValue(undefined),\n uploadMany: vi.fn().mockResolvedValue(undefined),\n abort: vi.fn(),\n clear: vi.fn()\n };\n}\n\nfunction createMockLocalStorage(): LocalStorage.Interface {\n const store = new Map<string, unknown>();\n return {\n get: vi.fn((key: string) => store.get(key)) as LocalStorage.Interface[\"get\"],\n set: vi.fn(<T>(key: string, value: T): void => {\n store.set(key, value);\n }),\n remove: vi.fn((key: string) => {\n store.delete(key);\n }),\n clear: vi.fn(() => store.clear()),\n keys: vi.fn(() => Array.from(store.keys()))\n };\n}\n\nfunction createMockListFilesUseCase(): ListFilesUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n })\n };\n}\n\nfunction createMockGetDescendantFoldersUseCase(): GetDescendantFoldersUseCase.Interface {\n return {\n execute: vi.fn().mockReturnValue([])\n };\n}\n\nfunction createMockFileDetailsPresenter(): IFileDetailsPresenter {\n return {\n vm: {\n file: null,\n loading: null,\n form: {\n layout: [],\n errors: [],\n hasErrors: false,\n isDirty: false,\n isValid: null,\n submitCount: 0,\n focusField: vi.fn(),\n getData: vi.fn(() => ({})),\n setData: vi.fn()\n },\n previewUrl: null,\n permissions: { canEdit: true, canDelete: true }\n },\n loadFile: vi.fn().mockResolvedValue(undefined),\n saveFile: vi.fn().mockResolvedValue(undefined),\n setFile: vi.fn()\n };\n}\n\n// ---------------------------------------------------------------------------\n// Container setup\n// ---------------------------------------------------------------------------\n\ninterface Mocks {\n listPresenter: ListPresenter.Interface<FmFile>;\n folderTreePresenter: FolderTreePresenter.Interface;\n fileDetailsPresenter: IFileDetailsPresenter;\n permissions: FileManagerPermissions.Interface;\n settingsRepository: GetSettingsRepository.Interface;\n tagsRepository: ListTagsRepository.Interface;\n fileUploader: FileUploader.Interface;\n localStorage: LocalStorage.Interface;\n listFilesUseCase: ListFilesUseCase.Interface;\n cache: ListCache<FmFile>;\n getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface;\n fileModelProvider: FileModelProvider.Interface;\n}\n\nfunction createMocks(): Mocks {\n return {\n listPresenter: createMockListPresenter(),\n folderTreePresenter: createMockFolderTreePresenter(),\n fileDetailsPresenter: createMockFileDetailsPresenter(),\n permissions: createMockPermissions(),\n settingsRepository: createMockSettingsRepository(),\n tagsRepository: createMockTagsRepository(),\n fileUploader: createMockFileUploader(),\n localStorage: createMockLocalStorage(),\n listFilesUseCase: createMockListFilesUseCase(),\n cache: new ListCache<FmFile>(),\n getDescendantFoldersUseCase: createMockGetDescendantFoldersUseCase(),\n fileModelProvider: {\n getModel: vi.fn().mockResolvedValue({ fields: [] })\n }\n };\n}\n\nfunction createContainer(mocks: Mocks) {\n const container = new Container();\n\n container.registerInstance(ListPresenter, mocks.listPresenter);\n container.registerInstance(FolderTreePresenter, mocks.folderTreePresenter);\n container.registerInstance(FileDetailsPresenter, mocks.fileDetailsPresenter);\n container.registerInstance(FileManagerPermissions, mocks.permissions);\n container.registerInstance(GetSettingsRepository, mocks.settingsRepository);\n container.registerInstance(ListTagsRepository, mocks.tagsRepository);\n container.registerInstance(FileUploader, mocks.fileUploader);\n container.registerInstance(LocalStorage, mocks.localStorage);\n container.registerInstance(ListFilesUseCase, mocks.listFilesUseCase);\n container.registerInstance(FilesListCache, mocks.cache);\n container.registerInstance(GetDescendantFoldersUseCase, mocks.getDescendantFoldersUseCase);\n container.registerInstance(FileModelProvider, mocks.fileModelProvider);\n\n // Register the real FileListPresenter implementation.\n container.register(FileManagerPresenter).inSingletonScope();\n\n return container;\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"FileListPresenter\", () => {\n let mocks: Mocks;\n let presenter: IFileManagerPresenter;\n\n beforeEach(() => {\n mocks = createMocks();\n const container = createContainer(mocks);\n presenter = container.resolve(Abstraction);\n });\n\n // -----------------------------------------------------------------------\n // Composition: ListPresenter and FolderTreePresenter initialized.\n // -----------------------------------------------------------------------\n\n it(\"should call listPresenter.init with a DataSource and initialSort on init()\", () => {\n presenter.init();\n\n expect(mocks.listPresenter.init).toHaveBeenCalledTimes(1);\n const config = (mocks.listPresenter.init as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(config.dataSource).toBeDefined();\n expect(config.initialSort).toEqual({ field: \"createdOn\", direction: \"DESC\" });\n });\n\n it(\"should forward ListPresenter.vm data as vm.list\", () => {\n presenter.init();\n expect(presenter.vm.list.rows).toEqual(mocks.listPresenter.vm.rows);\n expect(presenter.vm.list.sort).toEqual(mocks.listPresenter.vm.sort);\n expect(presenter.vm.list.search).toBe(mocks.listPresenter.vm.search);\n expect(presenter.vm.list.empty).toBe(mocks.listPresenter.vm.empty);\n });\n\n it(\"should forward FolderTreePresenter.vm as vm.folders\", () => {\n presenter.init();\n expect(presenter.vm.folders).toBe(mocks.folderTreePresenter.vm);\n });\n\n // -----------------------------------------------------------------------\n // Folder change wiring.\n // -----------------------------------------------------------------------\n\n it(\"should set folderId filter when folder changes\", async () => {\n presenter.init();\n\n // Simulate folder selection via MobX observable change.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-abc\";\n });\n\n // MobX reaction fires synchronously in the same tick after runInAction.\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\n \"folderId\",\n \"folder-abc\"\n );\n });\n\n it(\"should set folderId to root when folder is set to null\", () => {\n presenter.init();\n\n // First set a folder.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-1\";\n });\n\n // Then clear it.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = null;\n });\n\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\"folderId\", \"root\");\n });\n\n // -----------------------------------------------------------------------\n // Permission flags forwarded to vm.\n // -----------------------------------------------------------------------\n\n it(\"should expose permission flags in vm.permissions\", () => {\n presenter.init();\n\n expect(presenter.vm.permissions.canRead).toBe(true);\n expect(presenter.vm.permissions.canCreate).toBe(true);\n expect(presenter.vm.permissions.canEdit).toBe(false);\n expect(presenter.vm.permissions.canDelete).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // View mode persistence via LocalStorage.\n // -----------------------------------------------------------------------\n\n it(\"should default viewMode to 'grid'\", () => {\n expect(presenter.vm.viewMode).toBe(\"grid\");\n });\n\n it(\"should update viewMode and persist to localStorage\", () => {\n presenter.actions.setViewMode(\"grid\");\n\n expect(presenter.vm.viewMode).toBe(\"grid\");\n expect(mocks.localStorage.set).toHaveBeenCalledWith(\"fm:viewMode\", \"grid\");\n });\n\n it(\"should restore viewMode from localStorage on construction\", () => {\n // Pre-seed localStorage with \"grid\" before creating the presenter.\n const seededMocks = createMocks();\n (seededMocks.localStorage.get as ReturnType<typeof vi.fn>).mockReturnValue(\"grid\");\n\n const container = createContainer(seededMocks);\n const seededPresenter: IFileManagerPresenter = container.resolve(Abstraction);\n\n expect(seededPresenter.vm.viewMode).toBe(\"grid\");\n });\n\n // -----------------------------------------------------------------------\n // Upload action.\n // -----------------------------------------------------------------------\n\n it(\"should call fileUploader.uploadMany when actions.upload is called\", async () => {\n presenter.init();\n\n const file1 = {\n id: \"f1\",\n name: \"test.txt\",\n type: \"text/plain\",\n size: 7,\n src: { file: new File([\"content\"], \"test.txt\", { type: \"text/plain\" }), base64: null }\n };\n const file2 = {\n id: \"f2\",\n name: \"photo.png\",\n type: \"image/png\",\n size: 3,\n src: { file: new File([\"img\"], \"photo.png\", { type: \"image/png\" }), base64: null }\n };\n\n await presenter.actions.upload([file1, file2]);\n\n expect(mocks.fileUploader.uploadMany).toHaveBeenCalledTimes(1);\n const args = (mocks.fileUploader.uploadMany as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(args).toHaveLength(2);\n expect(args[0].data.name).toBe(\"test.txt\");\n expect(args[0].data.type).toBe(\"text/plain\");\n expect(args[1].data.name).toBe(\"photo.png\");\n expect(args[1].data.type).toBe(\"image/png\");\n });\n\n // -----------------------------------------------------------------------\n // loading: true only during initial load (no rows yet).\n // -----------------------------------------------------------------------\n\n it(\"should be loading when pagination is loading and no rows exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(true);\n });\n\n it(\"should not be loading when rows already exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n it(\"should not be loading when pagination is not loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // empty: accounts for both files and child folders.\n // -----------------------------------------------------------------------\n\n it(\"should be empty when no files and no child folders\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n it(\"should not be empty when there are files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty when there are child folders but no files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty while loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should be empty when child folders exist but folders are hidden (search active)\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n // -----------------------------------------------------------------------\n // showFolders computed from appliedQuery.\n // -----------------------------------------------------------------------\n\n it(\"should show folders when appliedQuery is null\", () => {\n presenter.init();\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should show folders when appliedQuery has no search and only folderId filter\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should hide folders when appliedQuery has a search\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should hide folders when appliedQuery has non-folderId filters\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", tags: [\"photo\"] }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should show folders again when appliedQuery filters are cleared\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", type: \"image\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n});\n"],"names":["createMockListPresenter","vmState","observable","Set","vi","undefined","createMockFolderTreePresenter","state","createMockPermissions","createMockSettingsRepository","data","createMockTagsRepository","createMockFileUploader","createMockLocalStorage","store","Map","key","value","Array","createMockListFilesUseCase","createMockGetDescendantFoldersUseCase","createMockFileDetailsPresenter","createMocks","ListCache","createContainer","mocks","container","Container","ListPresenter","FolderTreePresenter","FileDetailsPresenter","FileManagerPermissions","GetSettingsRepository","ListTagsRepository","FileUploader","LocalStorage","ListFilesUseCase","FilesListCache","GetDescendantFoldersUseCase","FileModelProvider","FileManagerPresenter","describe","presenter","beforeEach","Abstraction","it","expect","config","runInAction","seededMocks","seededPresenter","file1","File","file2","args"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
export declare const getFilesLabel: (count?: number) => string;
|
|
3
|
-
export declare const BulkActionBar: (() => React.JSX.Element | null) & {
|
|
4
|
-
|
|
3
|
+
export declare const BulkActionBar: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
4
|
+
readonly type: () => React.JSX.Element | null;
|
|
5
5
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const BulkActionDelete: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const BulkActionDelete: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const BulkActionMove: (() => React.JSX.Element) & {
|
|
3
|
-
|
|
2
|
+
export declare const BulkActionMove: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element;
|
|
4
4
|
};
|
|
@@ -4,6 +4,6 @@ import React from "react";
|
|
|
4
4
|
* Sets the "includeSubFolders" filter which the FileListDataSource uses
|
|
5
5
|
* to expand the folder scope via GetDescendantFoldersUseCase.
|
|
6
6
|
*/
|
|
7
|
-
export declare const SubFoldersToggle: (() => React.JSX.Element) & {
|
|
8
|
-
|
|
7
|
+
export declare const SubFoldersToggle: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
8
|
+
readonly type: () => React.JSX.Element;
|
|
9
9
|
};
|
|
@@ -4,6 +4,6 @@ import React from "react";
|
|
|
4
4
|
* Reads available tags from vm.tags, supports AND/OR filter modes,
|
|
5
5
|
* and dispatches changes via presenter.actions.filter.set("tags", ...).
|
|
6
6
|
*/
|
|
7
|
-
export declare const TagsFilter: (() => React.JSX.Element) & {
|
|
8
|
-
|
|
7
|
+
export declare const TagsFilter: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
8
|
+
readonly type: () => React.JSX.Element;
|
|
9
9
|
};
|
|
@@ -3,6 +3,6 @@ import React from "react";
|
|
|
3
3
|
* File type filter component wired to the FileListPresenter.
|
|
4
4
|
* Sets the "type" filter via presenter.actions.filter.set/clear.
|
|
5
5
|
*/
|
|
6
|
-
export declare const TypeFilter: (() => React.JSX.Element) & {
|
|
7
|
-
|
|
6
|
+
export declare const TypeFilter: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
7
|
+
readonly type: () => React.JSX.Element;
|
|
8
8
|
};
|
|
@@ -4,6 +4,6 @@ import React from "react";
|
|
|
4
4
|
* Renders file thumbnail cards and folder cards in a responsive grid layout.
|
|
5
5
|
* Wires click-to-select through presenter.actions.selection.
|
|
6
6
|
*/
|
|
7
|
-
export declare const FileGrid: (() => React.JSX.Element) & {
|
|
8
|
-
|
|
7
|
+
export declare const FileGrid: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
8
|
+
readonly type: () => React.JSX.Element;
|
|
9
9
|
};
|
|
@@ -2,6 +2,6 @@ import React from "react";
|
|
|
2
2
|
export interface FileManagerHeaderProps {
|
|
3
3
|
browseFiles?: () => void;
|
|
4
4
|
}
|
|
5
|
-
export declare const FileManagerHeader: (({ browseFiles }: FileManagerHeaderProps) => React.JSX.Element) & {
|
|
6
|
-
|
|
5
|
+
export declare const FileManagerHeader: (({ browseFiles }: FileManagerHeaderProps) => React.JSX.Element) & React.NamedExoticComponent<FileManagerHeaderProps> & {
|
|
6
|
+
readonly type: ({ browseFiles }: FileManagerHeaderProps) => React.JSX.Element;
|
|
7
7
|
};
|
|
@@ -4,6 +4,6 @@ import React from "react";
|
|
|
4
4
|
* Uses DelayedOnChange for debounced input, reads current search from vm.list.search,
|
|
5
5
|
* and dispatches changes via presenter.actions.search.set().
|
|
6
6
|
*/
|
|
7
|
-
export declare const SearchBar: (() => React.JSX.Element) & {
|
|
8
|
-
|
|
7
|
+
export declare const SearchBar: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
8
|
+
readonly type: () => React.JSX.Element;
|
|
9
9
|
};
|
|
@@ -7,6 +7,6 @@ export type FileTableItem = FolderTableRow | RecordTableRow<FmFile>;
|
|
|
7
7
|
* Bridges the presenter's state to the ACO Table component,
|
|
8
8
|
* wiring sort and selection actions back to the presenter.
|
|
9
9
|
*/
|
|
10
|
-
export declare const FileTable: (() => React.JSX.Element) & {
|
|
11
|
-
|
|
10
|
+
export declare const FileTable: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
11
|
+
readonly type: () => React.JSX.Element;
|
|
12
12
|
};
|
|
@@ -4,6 +4,6 @@ import React from "react";
|
|
|
4
4
|
* Reuses the original UploadStatus markup — a bottom-center bar with progress
|
|
5
5
|
* and a close button.
|
|
6
6
|
*/
|
|
7
|
-
export declare const UploadProgress: (() => React.JSX.Element | null) & {
|
|
8
|
-
|
|
7
|
+
export declare const UploadProgress: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
8
|
+
readonly type: () => React.JSX.Element | null;
|
|
9
9
|
};
|
|
@@ -5,7 +5,7 @@ const getThumbnailRenderer = (renderers, file)=>{
|
|
|
5
5
|
const countA = (a.type.match(regExMatch) || []).length;
|
|
6
6
|
const countB = (b.type.match(regExMatch) || []).length;
|
|
7
7
|
if (countB > countA) return -1;
|
|
8
|
-
if (countB < countA) return 1;
|
|
8
|
+
else if (countB < countA) return 1;
|
|
9
9
|
return 0;
|
|
10
10
|
});
|
|
11
11
|
const renderer = types.find((type)=>minimatch(file.type, type.type));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/config/getThumbnailRenderer.js","sources":["../../../src/presentation/config/getThumbnailRenderer.ts"],"sourcesContent":["import { minimatch } from \"minimatch\";\nimport type { FileItem } from \"~/domain/types.js\";\n\nexport const getThumbnailRenderer = <T extends { type: string }>(\n renderers: T[],\n file: FileItem\n): T => {\n // Sort by type and by priority. More occurrences of `*` means lower priority.\n const regExMatch = /\\*/g;\n\n const types = renderers.sort((a, b) => {\n const countA = (a.type.match(regExMatch) || []).length;\n const countB = (b.type.match(regExMatch) || []).length;\n if (countB > countA) {\n return -1;\n } else if (countB < countA) {\n return 1;\n }\n return 0;\n });\n\n // Find first matching type\n const renderer = types.find(type => minimatch(file.type, type.type));\n\n return renderer!;\n};\n"],"names":["getThumbnailRenderer","renderers","file","regExMatch","types","a","b","countA","countB","renderer","type","minimatch"],"mappings":";AAGO,MAAMA,uBAAuB,CAChCC,WACAC;IAGA,MAAMC,aAAa;IAEnB,MAAMC,QAAQH,UAAU,IAAI,CAAC,CAACI,GAAGC;QAC7B,MAAMC,SAAUF,AAAAA,CAAAA,EAAE,IAAI,CAAC,KAAK,CAACF,eAAe,EAAC,EAAG,MAAM;QACtD,MAAMK,SAAUF,AAAAA,CAAAA,EAAE,IAAI,CAAC,KAAK,CAACH,eAAe,EAAC,EAAG,MAAM;QACtD,IAAIK,SAASD,QACT,OAAO;
|
|
1
|
+
{"version":3,"file":"presentation/config/getThumbnailRenderer.js","sources":["../../../src/presentation/config/getThumbnailRenderer.ts"],"sourcesContent":["import { minimatch } from \"minimatch\";\nimport type { FileItem } from \"~/domain/types.js\";\n\nexport const getThumbnailRenderer = <T extends { type: string }>(\n renderers: T[],\n file: FileItem\n): T => {\n // Sort by type and by priority. More occurrences of `*` means lower priority.\n const regExMatch = /\\*/g;\n\n const types = renderers.sort((a, b) => {\n const countA = (a.type.match(regExMatch) || []).length;\n const countB = (b.type.match(regExMatch) || []).length;\n if (countB > countA) {\n return -1;\n } else if (countB < countA) {\n return 1;\n }\n return 0;\n });\n\n // Find first matching type\n const renderer = types.find(type => minimatch(file.type, type.type));\n\n return renderer!;\n};\n"],"names":["getThumbnailRenderer","renderers","file","regExMatch","types","a","b","countA","countB","renderer","type","minimatch"],"mappings":";AAGO,MAAMA,uBAAuB,CAChCC,WACAC;IAGA,MAAMC,aAAa;IAEnB,MAAMC,QAAQH,UAAU,IAAI,CAAC,CAACI,GAAGC;QAC7B,MAAMC,SAAUF,AAAAA,CAAAA,EAAE,IAAI,CAAC,KAAK,CAACF,eAAe,EAAC,EAAG,MAAM;QACtD,MAAMK,SAAUF,AAAAA,CAAAA,EAAE,IAAI,CAAC,KAAK,CAACH,eAAe,EAAC,EAAG,MAAM;QACtD,IAAIK,SAASD,QACT,OAAO;aACJ,IAAIC,SAASD,QAChB,OAAO;QAEX,OAAO;IACX;IAGA,MAAME,WAAWL,MAAM,IAAI,CAACM,CAAAA,OAAQC,UAAUT,KAAK,IAAI,EAAEQ,KAAK,IAAI;IAElE,OAAOD;AACX"}
|