@flusys/nestjs-storage 6.0.2 → 6.1.1
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/cjs/controllers/file-manager.controller.spec.js +135 -0
- package/cjs/controllers/folder.controller.spec.js +86 -0
- package/cjs/controllers/storage-config.controller.spec.js +85 -0
- package/cjs/controllers/upload.controller.spec.js +132 -0
- package/cjs/docs/storage-swagger.config.spec.js +72 -0
- package/cjs/entities/index.spec.js +18 -0
- package/cjs/middlewares/file-serve.middleware.spec.js +211 -0
- package/cjs/modules/storage.module.spec.js +184 -0
- package/cjs/providers/azure-provider.optional.spec.js +228 -0
- package/cjs/providers/local-provider.spec.js +239 -0
- package/cjs/providers/s3-provider.optional.spec.js +243 -0
- package/cjs/providers/sftp-provider.optional.spec.js +217 -0
- package/cjs/providers/storage-factory.service.spec.js +253 -0
- package/cjs/providers/storage-provider.registry.spec.js +67 -0
- package/cjs/services/file-manager.service.spec.js +549 -0
- package/cjs/services/folder.service.spec.js +163 -0
- package/cjs/services/storage-config.service.spec.js +257 -0
- package/cjs/services/storage-datasource.provider.spec.js +217 -0
- package/cjs/services/storage-provider-config.service.spec.js +243 -0
- package/cjs/services/upload.service.spec.js +372 -0
- package/cjs/utils/file-validator.util.spec.js +259 -0
- package/cjs/utils/image-compressor.util.spec.js +166 -0
- package/fesm/controllers/file-manager.controller.spec.js +131 -0
- package/fesm/controllers/folder.controller.spec.js +82 -0
- package/fesm/controllers/storage-config.controller.spec.js +81 -0
- package/fesm/controllers/upload.controller.spec.js +128 -0
- package/fesm/docs/storage-swagger.config.spec.js +68 -0
- package/fesm/entities/index.spec.js +14 -0
- package/fesm/middlewares/file-serve.middleware.spec.js +207 -0
- package/fesm/modules/storage.module.spec.js +180 -0
- package/fesm/providers/azure-provider.optional.spec.js +224 -0
- package/fesm/providers/local-provider.spec.js +194 -0
- package/fesm/providers/s3-provider.optional.spec.js +239 -0
- package/fesm/providers/sftp-provider.optional.spec.js +213 -0
- package/fesm/providers/storage-factory.service.spec.js +249 -0
- package/fesm/providers/storage-provider.registry.spec.js +63 -0
- package/fesm/services/file-manager.service.spec.js +545 -0
- package/fesm/services/folder.service.spec.js +159 -0
- package/fesm/services/storage-config.service.spec.js +253 -0
- package/fesm/services/storage-datasource.provider.spec.js +172 -0
- package/fesm/services/storage-provider-config.service.spec.js +239 -0
- package/fesm/services/upload.service.spec.js +368 -0
- package/fesm/utils/file-validator.util.spec.js +255 -0
- package/fesm/utils/image-compressor.util.spec.js +162 -0
- package/package.json +3 -3
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _common = require("@nestjs/common");
|
|
6
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
7
|
+
const _filemanagercontroller = require("./file-manager.controller");
|
|
8
|
+
function buildFile(overrides = {}) {
|
|
9
|
+
return {
|
|
10
|
+
id: 'file-1',
|
|
11
|
+
name: 'report.pdf',
|
|
12
|
+
key: 'files/report.pdf',
|
|
13
|
+
size: 1024,
|
|
14
|
+
contentType: 'application/pdf',
|
|
15
|
+
isActive: true,
|
|
16
|
+
readOnly: false,
|
|
17
|
+
createdAt: new Date(),
|
|
18
|
+
updatedAt: new Date(),
|
|
19
|
+
...overrides
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
describe('FileManagerController', ()=>{
|
|
23
|
+
let controller;
|
|
24
|
+
let mockFileService;
|
|
25
|
+
beforeEach(()=>{
|
|
26
|
+
mockFileService = {
|
|
27
|
+
insert: jest.fn(),
|
|
28
|
+
findById: jest.fn(),
|
|
29
|
+
getAll: jest.fn(),
|
|
30
|
+
update: jest.fn(),
|
|
31
|
+
delete: jest.fn(),
|
|
32
|
+
getFiles: jest.fn()
|
|
33
|
+
};
|
|
34
|
+
controller = new _filemanagercontroller.FileManagerController(mockFileService);
|
|
35
|
+
});
|
|
36
|
+
describe('insert', ()=>{
|
|
37
|
+
it('creates a file record and returns the mapped response', async ()=>{
|
|
38
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
39
|
+
mockFileService.insert.mockResolvedValue(buildFile());
|
|
40
|
+
const result = await controller.insert({
|
|
41
|
+
name: 'report.pdf'
|
|
42
|
+
}, user);
|
|
43
|
+
expect(mockFileService.insert).toHaveBeenCalledWith({
|
|
44
|
+
name: 'report.pdf'
|
|
45
|
+
}, user);
|
|
46
|
+
expect(result.success).toBe(true);
|
|
47
|
+
expect(result.data).toEqual(expect.objectContaining({
|
|
48
|
+
id: 'file-1'
|
|
49
|
+
}));
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('getAll', ()=>{
|
|
53
|
+
it('paginates files and maps the response list', async ()=>{
|
|
54
|
+
mockFileService.getAll.mockResolvedValue({
|
|
55
|
+
data: [
|
|
56
|
+
buildFile()
|
|
57
|
+
],
|
|
58
|
+
total: 1
|
|
59
|
+
});
|
|
60
|
+
const result = await controller.getAll({}, (0, _loggedusermock.buildMockUser)(), '');
|
|
61
|
+
expect(mockFileService.getAll).toHaveBeenCalledWith('', {}, (0, _loggedusermock.buildMockUser)());
|
|
62
|
+
expect(result.data).toHaveLength(1);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('getFiles', ()=>{
|
|
66
|
+
it('resolves signed/public URLs for the requested files using the request protocol and host', async ()=>{
|
|
67
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
68
|
+
const req = {
|
|
69
|
+
protocol: 'https',
|
|
70
|
+
hostname: 'app.example.com',
|
|
71
|
+
get: jest.fn().mockReturnValue('app.example.com')
|
|
72
|
+
};
|
|
73
|
+
mockFileService.getFiles.mockResolvedValue([
|
|
74
|
+
{
|
|
75
|
+
id: 'file-1',
|
|
76
|
+
url: 'https://app.example.com/storage/upload/file/report.pdf'
|
|
77
|
+
}
|
|
78
|
+
]);
|
|
79
|
+
const result = await controller.getFiles([
|
|
80
|
+
{
|
|
81
|
+
id: 'file-1'
|
|
82
|
+
}
|
|
83
|
+
], req, user);
|
|
84
|
+
expect(mockFileService.getFiles).toHaveBeenCalledWith([
|
|
85
|
+
{
|
|
86
|
+
id: 'file-1'
|
|
87
|
+
}
|
|
88
|
+
], 'https', 'app.example.com', user);
|
|
89
|
+
expect(result.success).toBe(true);
|
|
90
|
+
expect(result.data).toEqual([
|
|
91
|
+
{
|
|
92
|
+
id: 'file-1',
|
|
93
|
+
url: 'https://app.example.com/storage/upload/file/report.pdf'
|
|
94
|
+
}
|
|
95
|
+
]);
|
|
96
|
+
});
|
|
97
|
+
it('falls back to req.hostname when the host header is absent', async ()=>{
|
|
98
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
99
|
+
const req = {
|
|
100
|
+
protocol: 'http',
|
|
101
|
+
hostname: 'localhost',
|
|
102
|
+
get: jest.fn().mockReturnValue(undefined)
|
|
103
|
+
};
|
|
104
|
+
mockFileService.getFiles.mockResolvedValue([]);
|
|
105
|
+
await controller.getFiles([
|
|
106
|
+
{
|
|
107
|
+
id: 'file-1'
|
|
108
|
+
}
|
|
109
|
+
], req, user);
|
|
110
|
+
expect(mockFileService.getFiles).toHaveBeenCalledWith([
|
|
111
|
+
{
|
|
112
|
+
id: 'file-1'
|
|
113
|
+
}
|
|
114
|
+
], 'http', 'localhost', user);
|
|
115
|
+
});
|
|
116
|
+
it('rejects an empty file id list without calling the service', async ()=>{
|
|
117
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
118
|
+
const req = {
|
|
119
|
+
protocol: 'https',
|
|
120
|
+
get: jest.fn()
|
|
121
|
+
};
|
|
122
|
+
await expect(controller.getFiles([], req, user)).rejects.toThrow(_common.BadRequestException);
|
|
123
|
+
expect(mockFileService.getFiles).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
it('rejects a null/undefined dto without calling the service', async ()=>{
|
|
126
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
127
|
+
const req = {
|
|
128
|
+
protocol: 'https',
|
|
129
|
+
get: jest.fn()
|
|
130
|
+
};
|
|
131
|
+
await expect(controller.getFiles(undefined, req, user)).rejects.toThrow(_common.BadRequestException);
|
|
132
|
+
expect(mockFileService.getFiles).not.toHaveBeenCalled();
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
6
|
+
const _foldercontroller = require("./folder.controller");
|
|
7
|
+
function buildFolder(overrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
id: 'folder-1',
|
|
10
|
+
name: 'Documents',
|
|
11
|
+
parentId: null,
|
|
12
|
+
isActive: true,
|
|
13
|
+
readOnly: false,
|
|
14
|
+
createdAt: new Date(),
|
|
15
|
+
updatedAt: new Date(),
|
|
16
|
+
...overrides
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
describe('FolderController', ()=>{
|
|
20
|
+
let controller;
|
|
21
|
+
let mockFolderService;
|
|
22
|
+
beforeEach(()=>{
|
|
23
|
+
mockFolderService = {
|
|
24
|
+
insert: jest.fn(),
|
|
25
|
+
findById: jest.fn(),
|
|
26
|
+
getAll: jest.fn(),
|
|
27
|
+
update: jest.fn(),
|
|
28
|
+
delete: jest.fn()
|
|
29
|
+
};
|
|
30
|
+
controller = new _foldercontroller.FolderController(mockFolderService);
|
|
31
|
+
});
|
|
32
|
+
it('wires the injected service onto the generated controller base', ()=>{
|
|
33
|
+
expect(controller.folderService).toBe(mockFolderService);
|
|
34
|
+
expect(controller.service).toBe(mockFolderService);
|
|
35
|
+
});
|
|
36
|
+
describe('insert', ()=>{
|
|
37
|
+
it('creates a folder and returns the mapped response', async ()=>{
|
|
38
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
39
|
+
mockFolderService.insert.mockResolvedValue(buildFolder());
|
|
40
|
+
const result = await controller.insert({
|
|
41
|
+
name: 'Documents'
|
|
42
|
+
}, user);
|
|
43
|
+
expect(mockFolderService.insert).toHaveBeenCalledWith({
|
|
44
|
+
name: 'Documents'
|
|
45
|
+
}, user);
|
|
46
|
+
expect(result.success).toBe(true);
|
|
47
|
+
expect(result.data).toEqual(expect.objectContaining({
|
|
48
|
+
id: 'folder-1',
|
|
49
|
+
name: 'Documents'
|
|
50
|
+
}));
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('getAll', ()=>{
|
|
54
|
+
it('paginates folders and maps the response list', async ()=>{
|
|
55
|
+
mockFolderService.getAll.mockResolvedValue({
|
|
56
|
+
data: [
|
|
57
|
+
buildFolder()
|
|
58
|
+
],
|
|
59
|
+
total: 1
|
|
60
|
+
});
|
|
61
|
+
const result = await controller.getAll({}, (0, _loggedusermock.buildMockUser)(), '');
|
|
62
|
+
expect(mockFolderService.getAll).toHaveBeenCalledWith('', {}, (0, _loggedusermock.buildMockUser)());
|
|
63
|
+
expect(result.data).toHaveLength(1);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('delete', ()=>{
|
|
67
|
+
it('delegates soft-delete to the service', async ()=>{
|
|
68
|
+
mockFolderService.delete.mockResolvedValue({
|
|
69
|
+
count: 1
|
|
70
|
+
});
|
|
71
|
+
const result = await controller.delete({
|
|
72
|
+
id: [
|
|
73
|
+
'folder-1'
|
|
74
|
+
],
|
|
75
|
+
type: 'delete'
|
|
76
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
77
|
+
expect(mockFolderService.delete).toHaveBeenCalledWith({
|
|
78
|
+
id: [
|
|
79
|
+
'folder-1'
|
|
80
|
+
],
|
|
81
|
+
type: 'delete'
|
|
82
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
83
|
+
expect(result.success).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
6
|
+
const _storageconfigcontroller = require("./storage-config.controller");
|
|
7
|
+
function buildStorageConfig(overrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
id: 'storage-config-1',
|
|
10
|
+
provider: 'local',
|
|
11
|
+
isActive: true,
|
|
12
|
+
isDefault: true,
|
|
13
|
+
readOnly: false,
|
|
14
|
+
createdAt: new Date(),
|
|
15
|
+
updatedAt: new Date(),
|
|
16
|
+
...overrides
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
describe('StorageConfigController', ()=>{
|
|
20
|
+
let controller;
|
|
21
|
+
let mockStorageConfigService;
|
|
22
|
+
beforeEach(()=>{
|
|
23
|
+
mockStorageConfigService = {
|
|
24
|
+
insert: jest.fn(),
|
|
25
|
+
findById: jest.fn(),
|
|
26
|
+
getAll: jest.fn(),
|
|
27
|
+
update: jest.fn(),
|
|
28
|
+
delete: jest.fn()
|
|
29
|
+
};
|
|
30
|
+
controller = new _storageconfigcontroller.StorageConfigController(mockStorageConfigService);
|
|
31
|
+
});
|
|
32
|
+
it('wires the injected service onto the generated controller base', ()=>{
|
|
33
|
+
expect(controller.storageConfigService).toBe(mockStorageConfigService);
|
|
34
|
+
expect(controller.service).toBe(mockStorageConfigService);
|
|
35
|
+
});
|
|
36
|
+
describe('insert', ()=>{
|
|
37
|
+
it('creates a storage config and returns the mapped response', async ()=>{
|
|
38
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
39
|
+
mockStorageConfigService.insert.mockResolvedValue(buildStorageConfig());
|
|
40
|
+
const result = await controller.insert({
|
|
41
|
+
provider: 'local'
|
|
42
|
+
}, user);
|
|
43
|
+
expect(mockStorageConfigService.insert).toHaveBeenCalledWith({
|
|
44
|
+
provider: 'local'
|
|
45
|
+
}, user);
|
|
46
|
+
expect(result.success).toBe(true);
|
|
47
|
+
expect(result.data).toEqual(expect.objectContaining({
|
|
48
|
+
id: 'storage-config-1'
|
|
49
|
+
}));
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('getAll', ()=>{
|
|
53
|
+
it('paginates storage configs and maps the response list', async ()=>{
|
|
54
|
+
mockStorageConfigService.getAll.mockResolvedValue({
|
|
55
|
+
data: [
|
|
56
|
+
buildStorageConfig()
|
|
57
|
+
],
|
|
58
|
+
total: 1
|
|
59
|
+
});
|
|
60
|
+
const result = await controller.getAll({}, (0, _loggedusermock.buildMockUser)(), '');
|
|
61
|
+
expect(mockStorageConfigService.getAll).toHaveBeenCalledWith('', {}, (0, _loggedusermock.buildMockUser)());
|
|
62
|
+
expect(result.data).toHaveLength(1);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('delete', ()=>{
|
|
66
|
+
it('delegates soft-delete to the service', async ()=>{
|
|
67
|
+
mockStorageConfigService.delete.mockResolvedValue({
|
|
68
|
+
count: 1
|
|
69
|
+
});
|
|
70
|
+
const result = await controller.delete({
|
|
71
|
+
id: [
|
|
72
|
+
'storage-config-1'
|
|
73
|
+
],
|
|
74
|
+
type: 'delete'
|
|
75
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
76
|
+
expect(mockStorageConfigService.delete).toHaveBeenCalledWith({
|
|
77
|
+
id: [
|
|
78
|
+
'storage-config-1'
|
|
79
|
+
],
|
|
80
|
+
type: 'delete'
|
|
81
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
82
|
+
expect(result.success).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
6
|
+
const _uploadcontroller = require("./upload.controller");
|
|
7
|
+
describe('UploadController', ()=>{
|
|
8
|
+
let controller;
|
|
9
|
+
let mockUploadService;
|
|
10
|
+
beforeEach(()=>{
|
|
11
|
+
mockUploadService = {
|
|
12
|
+
bytesToKb: jest.fn((bytes)=>bytes / 1024),
|
|
13
|
+
uploadSingleFile: jest.fn(),
|
|
14
|
+
uploadMultipleFiles: jest.fn(),
|
|
15
|
+
deleteSingleFile: jest.fn(),
|
|
16
|
+
deleteMultipleFile: jest.fn()
|
|
17
|
+
};
|
|
18
|
+
controller = new _uploadcontroller.UploadController(mockUploadService);
|
|
19
|
+
});
|
|
20
|
+
describe('uploadSingleFile', ()=>{
|
|
21
|
+
it('uploads a file and maps the response payload', async ()=>{
|
|
22
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
23
|
+
const file = {
|
|
24
|
+
originalname: 'photo.png'
|
|
25
|
+
};
|
|
26
|
+
mockUploadService.uploadSingleFile.mockResolvedValue({
|
|
27
|
+
size: 2048,
|
|
28
|
+
name: 'photo.png',
|
|
29
|
+
key: 'files/photo.png',
|
|
30
|
+
contentType: 'image/png',
|
|
31
|
+
location: 's3',
|
|
32
|
+
storageConfigId: 'storage-1'
|
|
33
|
+
});
|
|
34
|
+
const result = await controller.uploadSingleFile(file, {
|
|
35
|
+
folderPath: 'photos'
|
|
36
|
+
}, user);
|
|
37
|
+
expect(mockUploadService.uploadSingleFile).toHaveBeenCalledWith(file, {
|
|
38
|
+
folderPath: 'photos'
|
|
39
|
+
}, user);
|
|
40
|
+
expect(mockUploadService.bytesToKb).toHaveBeenCalledWith(2048);
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
success: true,
|
|
43
|
+
message: 'File uploaded successfully',
|
|
44
|
+
messageKey: expect.any(String),
|
|
45
|
+
data: {
|
|
46
|
+
size: 2,
|
|
47
|
+
name: 'photo.png',
|
|
48
|
+
key: 'files/photo.png',
|
|
49
|
+
contentType: 'image/png',
|
|
50
|
+
location: 's3',
|
|
51
|
+
storageConfigId: 'storage-1'
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
it('defaults location to "local" and storageConfigId to an empty string when absent', async ()=>{
|
|
56
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
57
|
+
mockUploadService.uploadSingleFile.mockResolvedValue({
|
|
58
|
+
size: 100,
|
|
59
|
+
name: 'file.txt',
|
|
60
|
+
key: 'files/file.txt',
|
|
61
|
+
contentType: 'text/plain'
|
|
62
|
+
});
|
|
63
|
+
const result = await controller.uploadSingleFile({}, {}, user);
|
|
64
|
+
expect(result.data.location).toBe('local');
|
|
65
|
+
expect(result.data.storageConfigId).toBe('');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('uploadMultipleFiles', ()=>{
|
|
69
|
+
it('uploads multiple files and maps each response payload', async ()=>{
|
|
70
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
71
|
+
const files = [
|
|
72
|
+
{
|
|
73
|
+
originalname: 'a.png'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
originalname: 'b.png'
|
|
77
|
+
}
|
|
78
|
+
];
|
|
79
|
+
mockUploadService.uploadMultipleFiles.mockResolvedValue([
|
|
80
|
+
{
|
|
81
|
+
size: 100,
|
|
82
|
+
name: 'a.png',
|
|
83
|
+
key: 'files/a.png',
|
|
84
|
+
contentType: 'image/png'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
size: 200,
|
|
88
|
+
name: 'b.png',
|
|
89
|
+
key: 'files/b.png',
|
|
90
|
+
contentType: 'image/png'
|
|
91
|
+
}
|
|
92
|
+
]);
|
|
93
|
+
const result = await controller.uploadMultipleFiles(files, {}, user);
|
|
94
|
+
expect(mockUploadService.uploadMultipleFiles).toHaveBeenCalledWith(files, {}, user);
|
|
95
|
+
expect(result.data).toHaveLength(2);
|
|
96
|
+
expect(result.data[0]).toEqual(expect.objectContaining({
|
|
97
|
+
name: 'a.png',
|
|
98
|
+
key: 'files/a.png'
|
|
99
|
+
}));
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('deleteSingleFile', ()=>{
|
|
103
|
+
it('deletes a file by key and storage config', async ()=>{
|
|
104
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
105
|
+
mockUploadService.deleteSingleFile.mockResolvedValue(true);
|
|
106
|
+
const result = await controller.deleteSingleFile({
|
|
107
|
+
key: 'files/a.png',
|
|
108
|
+
storageConfigId: 'storage-1'
|
|
109
|
+
}, user);
|
|
110
|
+
expect(mockUploadService.deleteSingleFile).toHaveBeenCalledWith('files/a.png', 'storage-1', user);
|
|
111
|
+
expect(result.data).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('deleteMultipleFile', ()=>{
|
|
115
|
+
it('deletes multiple files by keys and storage config', async ()=>{
|
|
116
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
117
|
+
mockUploadService.deleteMultipleFile.mockResolvedValue(true);
|
|
118
|
+
const result = await controller.deleteMultipleFile({
|
|
119
|
+
keys: [
|
|
120
|
+
'files/a.png',
|
|
121
|
+
'files/b.png'
|
|
122
|
+
],
|
|
123
|
+
storageConfigId: 'storage-1'
|
|
124
|
+
}, user);
|
|
125
|
+
expect(mockUploadService.deleteMultipleFile).toHaveBeenCalledWith([
|
|
126
|
+
'files/a.png',
|
|
127
|
+
'files/b.png'
|
|
128
|
+
], 'storage-1', user);
|
|
129
|
+
expect(result.data).toBe(true);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _storageswaggerconfig = require("./storage-swagger.config");
|
|
6
|
+
describe('storageSwaggerConfig', ()=>{
|
|
7
|
+
it('should default to company feature enabled and single-database mode when no config is given', ()=>{
|
|
8
|
+
const config = (0, _storageswaggerconfig.storageSwaggerConfig)();
|
|
9
|
+
expect(config.title).toBe('Storage API');
|
|
10
|
+
expect(config.path).toBe('api/docs/storage');
|
|
11
|
+
expect(config.bearerAuth).toBe(true);
|
|
12
|
+
expect(config.excludeTags).toEqual([]);
|
|
13
|
+
expect(config.excludeSchemaProperties).toBeUndefined();
|
|
14
|
+
expect(config.description).not.toContain('Multi-Tenant Mode');
|
|
15
|
+
expect(config.description).toContain('with multi-tenant support');
|
|
16
|
+
});
|
|
17
|
+
it('should exclude companyId schema properties when the company feature is disabled', ()=>{
|
|
18
|
+
const config = (0, _storageswaggerconfig.storageSwaggerConfig)({
|
|
19
|
+
enableCompanyFeature: false
|
|
20
|
+
});
|
|
21
|
+
expect(config.excludeSchemaProperties).toEqual([
|
|
22
|
+
{
|
|
23
|
+
schemaName: 'FileManagerResponseDto',
|
|
24
|
+
properties: [
|
|
25
|
+
'companyId'
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
schemaName: 'FolderResponseDto',
|
|
30
|
+
properties: [
|
|
31
|
+
'companyId'
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
schemaName: 'StorageConfigResponseDto',
|
|
36
|
+
properties: [
|
|
37
|
+
'companyId'
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
it('should not exclude any schema properties when the company feature is enabled', ()=>{
|
|
43
|
+
const config = (0, _storageswaggerconfig.storageSwaggerConfig)({
|
|
44
|
+
enableCompanyFeature: true
|
|
45
|
+
});
|
|
46
|
+
expect(config.excludeSchemaProperties).toBeUndefined();
|
|
47
|
+
});
|
|
48
|
+
it('should describe company isolation and multi-tenant sections only when the company feature is enabled', ()=>{
|
|
49
|
+
const withCompany = (0, _storageswaggerconfig.storageSwaggerConfig)({
|
|
50
|
+
enableCompanyFeature: true
|
|
51
|
+
});
|
|
52
|
+
const withoutCompany = (0, _storageswaggerconfig.storageSwaggerConfig)({
|
|
53
|
+
enableCompanyFeature: false
|
|
54
|
+
});
|
|
55
|
+
expect(withCompany.description).toContain('Company isolation');
|
|
56
|
+
expect(withCompany.description).toContain('## Multi-Tenant Support');
|
|
57
|
+
expect(withCompany.description).toContain('## Examples');
|
|
58
|
+
expect(withoutCompany.description).not.toContain('Company isolation');
|
|
59
|
+
expect(withoutCompany.description).not.toContain('## Multi-Tenant Support');
|
|
60
|
+
expect(withoutCompany.description).not.toContain('## Examples');
|
|
61
|
+
});
|
|
62
|
+
it('should mention multi-tenant mode in the description only for multi-tenant database mode', ()=>{
|
|
63
|
+
const multiTenant = (0, _storageswaggerconfig.storageSwaggerConfig)({
|
|
64
|
+
databaseMode: 'multi-tenant'
|
|
65
|
+
});
|
|
66
|
+
const single = (0, _storageswaggerconfig.storageSwaggerConfig)({
|
|
67
|
+
databaseMode: 'single'
|
|
68
|
+
});
|
|
69
|
+
expect(multiTenant.description).toContain('Multi-Tenant Mode');
|
|
70
|
+
expect(single.description).not.toContain('Multi-Tenant Mode');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _index = require("./index");
|
|
6
|
+
describe('getStorageEntitiesByConfig', ()=>{
|
|
7
|
+
it('returns the core entities when the company feature is disabled', ()=>{
|
|
8
|
+
expect((0, _index.getStorageEntitiesByConfig)(false)).toBe(_index.StorageCoreEntities);
|
|
9
|
+
});
|
|
10
|
+
it('returns the company-scoped entities when the company feature is enabled', ()=>{
|
|
11
|
+
expect((0, _index.getStorageEntitiesByConfig)(true)).toBe(_index.StorageCompanyEntities);
|
|
12
|
+
});
|
|
13
|
+
it('core and company entity sets are disjoint (never mixed)', ()=>{
|
|
14
|
+
const core = (0, _index.getStorageEntitiesByConfig)(false);
|
|
15
|
+
const company = (0, _index.getStorageEntitiesByConfig)(true);
|
|
16
|
+
expect(core.some((e)=>company.includes(e))).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
});
|