mirror of
https://github.com/strapi/strapi.git
synced 2025-10-26 23:51:10 +00:00
remove path for files + add base for delete folders
This commit is contained in:
parent
9476065472
commit
ada5553977
@ -95,10 +95,5 @@ module.exports = {
|
|||||||
target: 'plugin::upload.folder',
|
target: 'plugin::upload.folder',
|
||||||
inversedBy: 'files',
|
inversedBy: 'files',
|
||||||
},
|
},
|
||||||
path: {
|
|
||||||
type: 'string',
|
|
||||||
min: 1,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { setCreatorFields, pipeAsync } = require('@strapi/utils');
|
const { setCreatorFields, pipeAsync } = require('@strapi/utils');
|
||||||
const { ApplicationError } = require('@strapi/utils').errors;
|
|
||||||
const { getService } = require('../utils');
|
const { getService } = require('../utils');
|
||||||
const { validateCreateFolder } = require('./validation/folder');
|
const { validateCreateFolder, validateDeleteManyFolders } = require('./validation/folder');
|
||||||
|
|
||||||
const folderModel = 'plugin::upload.folder';
|
const folderModel = 'plugin::upload.folder';
|
||||||
|
|
||||||
@ -40,16 +39,6 @@ module.exports = {
|
|||||||
|
|
||||||
await validateCreateFolder(body);
|
await validateCreateFolder(body);
|
||||||
|
|
||||||
const existingFolders = await strapi.entityService.findMany(folderModel, {
|
|
||||||
filters: {
|
|
||||||
parent: body.parent || null,
|
|
||||||
name: body.name,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (existingFolders.length > 0) {
|
|
||||||
throw new ApplicationError('name already taken');
|
|
||||||
}
|
|
||||||
|
|
||||||
const { setPathAndUID } = getService('folder');
|
const { setPathAndUID } = getService('folder');
|
||||||
|
|
||||||
// TODO: wrap with a transaction
|
// TODO: wrap with a transaction
|
||||||
@ -70,4 +59,18 @@ module.exports = {
|
|||||||
data: await permissionsManager.sanitizeOutput(folder),
|
data: await permissionsManager.sanitizeOutput(folder),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
// deleteMany WIP
|
||||||
|
async deleteMany(ctx) {
|
||||||
|
const { body } = ctx.request;
|
||||||
|
|
||||||
|
await validateDeleteManyFolders(body);
|
||||||
|
|
||||||
|
const { deleteByIds } = getService('folder');
|
||||||
|
|
||||||
|
const deletedFolders = await deleteByIds(body.ids);
|
||||||
|
|
||||||
|
ctx.body = {
|
||||||
|
data: deletedFolders,
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { yup, validateYupSchema } = require('@strapi/utils');
|
const { yup, validateYupSchema } = require('@strapi/utils');
|
||||||
|
const { getService } = require('../../utils');
|
||||||
|
|
||||||
const NO_SLASH_REGEX = /^[^/]+$/;
|
const NO_SLASH_REGEX = /^[^/]+$/;
|
||||||
const NO_SPACES_AROUND = /^(?! ).+(?<! )$/;
|
const NO_SPACES_AROUND = /^(?! ).+(?<! )$/;
|
||||||
@ -16,9 +17,27 @@ const validateCreateFolderSchema = yup
|
|||||||
.required(),
|
.required(),
|
||||||
parent: yup.strapiID().nullable(),
|
parent: yup.strapiID().nullable(),
|
||||||
})
|
})
|
||||||
|
.test('is-folder-unique', 'name already taken', async folder => {
|
||||||
|
const { exists } = getService('folder');
|
||||||
|
const doesExist = await exists({ parent: folder.parent || null, name: folder.name });
|
||||||
|
return !doesExist;
|
||||||
|
})
|
||||||
|
.noUnknown()
|
||||||
|
.required();
|
||||||
|
|
||||||
|
const validateDeleteManyFoldersSchema = yup
|
||||||
|
.object()
|
||||||
|
.shape({
|
||||||
|
ids: yup
|
||||||
|
.array()
|
||||||
|
.min(1)
|
||||||
|
.of(yup.strapiID().required())
|
||||||
|
.required(),
|
||||||
|
})
|
||||||
.noUnknown()
|
.noUnknown()
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
validateCreateFolder: validateYupSchema(validateCreateFolderSchema),
|
validateCreateFolder: validateYupSchema(validateCreateFolderSchema),
|
||||||
|
validateDeleteManyFolders: validateYupSchema(validateDeleteManyFoldersSchema),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,12 +1,23 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { yup, validateYupSchema } = require('@strapi/utils');
|
const { yup, validateYupSchema } = require('@strapi/utils');
|
||||||
|
const { isNil } = require('lodash/fp');
|
||||||
|
const { getService } = require('../../utils');
|
||||||
|
|
||||||
const fileInfoSchema = yup.object({
|
const fileInfoSchema = yup.object({
|
||||||
name: yup.string().nullable(),
|
name: yup.string().nullable(),
|
||||||
alternativeText: yup.string().nullable(),
|
alternativeText: yup.string().nullable(),
|
||||||
caption: yup.string().nullable(),
|
caption: yup.string().nullable(),
|
||||||
folder: yup.strapiID().nullable(),
|
folder: yup
|
||||||
|
.strapiID()
|
||||||
|
.nullable()
|
||||||
|
.test('folder-exists', "the folder doesn't exist", async folderId => {
|
||||||
|
if (isNil(folderId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getService('folder').exists({ id: folderId });
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const uploadSchema = yup.object({
|
const uploadSchema = yup.object({
|
||||||
|
|||||||
@ -123,5 +123,21 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/folders/batch-delete',
|
||||||
|
handler: 'admin-folder.deleteMany',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{
|
||||||
|
name: 'admin::hasPermissions',
|
||||||
|
config: {
|
||||||
|
actions: ['plugin::upload.read'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { getPath } = require('../file');
|
|
||||||
|
|
||||||
describe('file', () => {
|
|
||||||
describe('getPath', () => {
|
|
||||||
beforeAll(() => {
|
|
||||||
global.strapi = {
|
|
||||||
entityService: {
|
|
||||||
findOne: jest.fn(() => ({ path: '/parent-path' })),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
test.each([
|
|
||||||
[[1, 'myFile.txt'], '/parent-path/myFile.txt'],
|
|
||||||
[[undefined, 'myFile.txt'], '/myFile.txt'],
|
|
||||||
[[null, 'myFile.txt'], '/myFile.txt'],
|
|
||||||
])('inputs %s should give %s', async (args, expectedResult) => {
|
|
||||||
const result = await getPath(...args);
|
|
||||||
|
|
||||||
expect(result).toBe(expectedResult);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { trimChars, trimCharsEnd, trimCharsStart } = require('lodash/fp');
|
|
||||||
|
|
||||||
// TODO: to use once https://github.com/strapi/strapi/pull/12534 is merged
|
|
||||||
// const { joinBy } = require('@strapi/utils');
|
|
||||||
|
|
||||||
const folderModel = 'plugin::upload.folder';
|
|
||||||
|
|
||||||
const joinBy = (joint, ...args) => {
|
|
||||||
const trim = trimChars(joint);
|
|
||||||
const trimEnd = trimCharsEnd(joint);
|
|
||||||
const trimStart = trimCharsStart(joint);
|
|
||||||
|
|
||||||
return args.reduce((url, path, index) => {
|
|
||||||
if (args.length === 1) return path;
|
|
||||||
if (index === 0) return trimEnd(path);
|
|
||||||
if (index === args.length - 1) return url + joint + trimStart(path);
|
|
||||||
return url + joint + trim(path);
|
|
||||||
}, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
const getPath = async (folderId, fileName) => {
|
|
||||||
if (!folderId) return joinBy('/', '/', fileName);
|
|
||||||
|
|
||||||
const parentFolder = await strapi.entityService.findOne(folderModel, folderId);
|
|
||||||
return joinBy('/', parentFolder.path, fileName);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getPath,
|
|
||||||
};
|
|
||||||
@ -36,6 +36,29 @@ const setPathAndUID = async folder => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deleteByIds = async ids => {
|
||||||
|
const deletedFolders = [];
|
||||||
|
for (const id of ids) {
|
||||||
|
const deletedFolder = await strapi.entityService.delete(folderModel, id);
|
||||||
|
|
||||||
|
deletedFolders.push(deletedFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deletedFolders;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a folder exists in database
|
||||||
|
* @param params query params to find the folder
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
const exists = async (params = {}) => {
|
||||||
|
const count = await strapi.query(folderModel).count({ where: params });
|
||||||
|
return count > 0;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
exists,
|
||||||
|
deleteByIds,
|
||||||
setPathAndUID,
|
setPathAndUID,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,12 +4,10 @@ const provider = require('./provider');
|
|||||||
const upload = require('./upload');
|
const upload = require('./upload');
|
||||||
const imageManipulation = require('./image-manipulation');
|
const imageManipulation = require('./image-manipulation');
|
||||||
const folder = require('./folder');
|
const folder = require('./folder');
|
||||||
const file = require('./file');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
provider,
|
provider,
|
||||||
upload,
|
upload,
|
||||||
folder,
|
folder,
|
||||||
file,
|
|
||||||
'image-manipulation': imageManipulation,
|
'image-manipulation': imageManipulation,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -64,8 +64,6 @@ module.exports = ({ strapi }) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async formatFileInfo({ filename, type, size }, fileInfo = {}, metas = {}) {
|
async formatFileInfo({ filename, type, size }, fileInfo = {}, metas = {}) {
|
||||||
const fileService = getService('file');
|
|
||||||
|
|
||||||
const ext = path.extname(filename);
|
const ext = path.extname(filename);
|
||||||
const basename = path.basename(fileInfo.name || filename, ext);
|
const basename = path.basename(fileInfo.name || filename, ext);
|
||||||
const usedName = fileInfo.name || filename;
|
const usedName = fileInfo.name || filename;
|
||||||
@ -75,7 +73,6 @@ module.exports = ({ strapi }) => ({
|
|||||||
alternativeText: fileInfo.alternativeText,
|
alternativeText: fileInfo.alternativeText,
|
||||||
caption: fileInfo.caption,
|
caption: fileInfo.caption,
|
||||||
folder: fileInfo.folder,
|
folder: fileInfo.folder,
|
||||||
path: await fileService.getPath(fileInfo.folder, usedName),
|
|
||||||
hash: generateFileName(basename),
|
hash: generateFileName(basename),
|
||||||
ext,
|
ext,
|
||||||
mime: type,
|
mime: type,
|
||||||
@ -208,15 +205,12 @@ module.exports = ({ strapi }) => ({
|
|||||||
throw new NotFoundError();
|
throw new NotFoundError();
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileService = getService('file');
|
|
||||||
|
|
||||||
const newName = _.isNil(name) ? dbFile.name : name;
|
const newName = _.isNil(name) ? dbFile.name : name;
|
||||||
const newInfos = {
|
const newInfos = {
|
||||||
name: newName,
|
name: newName,
|
||||||
alternativeText: _.isNil(alternativeText) ? dbFile.alternativeText : alternativeText,
|
alternativeText: _.isNil(alternativeText) ? dbFile.alternativeText : alternativeText,
|
||||||
caption: _.isNil(caption) ? dbFile.caption : caption,
|
caption: _.isNil(caption) ? dbFile.caption : caption,
|
||||||
folder: _.isUndefined(folder) ? dbFile.folder : folder,
|
folder: _.isUndefined(folder) ? dbFile.folder : folder,
|
||||||
path: _.isUndefined(folder) ? dbFile.path : await fileService.getPath(folder, newName),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.update(id, newInfos, { user });
|
return this.update(id, newInfos, { user });
|
||||||
|
|||||||
@ -26,13 +26,21 @@ describe('File', () => {
|
|||||||
const folderRes = await rq({
|
const folderRes = await rq({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/upload/folders',
|
url: '/upload/folders',
|
||||||
body: { name: `folder ${i}` },
|
body: { name: `my folder ${i}` },
|
||||||
});
|
});
|
||||||
data.folders.push(folderRes.body.data);
|
data.folders.push(folderRes.body.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/upload/folders/batch-delete',
|
||||||
|
body: {
|
||||||
|
ids: data.folders.map(f => f.id),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await strapi.destroy();
|
await strapi.destroy();
|
||||||
await builder.cleanup();
|
await builder.cleanup();
|
||||||
});
|
});
|
||||||
@ -67,7 +75,6 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/rec.jpg',
|
|
||||||
folder: null,
|
folder: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -106,12 +113,27 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/folder 1/rec.jpg',
|
folder: { id: data.folders[0].id },
|
||||||
folder: { id: 1 },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
data.files.push(file);
|
data.files.push(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Cannot create a file inside a folder that doesn't exist", async () => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/upload',
|
||||||
|
formData: {
|
||||||
|
files: fs.createReadStream(path.join(__dirname, '../utils/rec.jpg')),
|
||||||
|
fileInfo: JSON.stringify({
|
||||||
|
folder: '1234', // id that doesn't exist
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error.message).toBe("the folder doesn't exist");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Update info', () => {
|
describe('Update info', () => {
|
||||||
@ -145,7 +167,6 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/folder 2/rec.pdf',
|
|
||||||
folder: { id: data.folders[1].id },
|
folder: { id: data.folders[1].id },
|
||||||
});
|
});
|
||||||
data.files[1] = file;
|
data.files[1] = file;
|
||||||
@ -179,7 +200,6 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/folder 1/rec.pdf',
|
|
||||||
folder: { id: data.folders[0].id },
|
folder: { id: data.folders[0].id },
|
||||||
});
|
});
|
||||||
data.files[1] = file;
|
data.files[1] = file;
|
||||||
@ -215,7 +235,6 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/folder 1/rec.pdf',
|
|
||||||
folder: { id: data.folders[0].id },
|
folder: { id: data.folders[0].id },
|
||||||
});
|
});
|
||||||
data.files[0] = file;
|
data.files[0] = file;
|
||||||
@ -249,7 +268,6 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/folder 2/rec.pdf',
|
|
||||||
folder: { id: data.folders[1].id },
|
folder: { id: data.folders[1].id },
|
||||||
});
|
});
|
||||||
data.files[1] = file;
|
data.files[1] = file;
|
||||||
@ -286,7 +304,6 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/rec.jpg',
|
|
||||||
folder: null,
|
folder: null,
|
||||||
});
|
});
|
||||||
data.files[0] = file;
|
data.files[0] = file;
|
||||||
@ -320,11 +337,44 @@ describe('File', () => {
|
|||||||
height: expect.any(Number),
|
height: expect.any(Number),
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
path: '/rec.pdf',
|
|
||||||
folder: null,
|
folder: null,
|
||||||
});
|
});
|
||||||
data.files[1] = file;
|
data.files[1] = file;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Cannot create a file inside a folder that doesn't exist", () => {
|
||||||
|
test('when replacing the file', async () => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: `/upload?id=${data.files[1].id}`,
|
||||||
|
formData: {
|
||||||
|
files: fs.createReadStream(path.join(__dirname, '../utils/rec.jpg')),
|
||||||
|
fileInfo: JSON.stringify({
|
||||||
|
folder: '1234', // id that doesn't exist
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('res.body', res.body);
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error.message).toBe("the folder doesn't exist");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('whithout replacing the file', async () => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: `/upload?id=${data.files[1].id}`,
|
||||||
|
formData: {
|
||||||
|
fileInfo: JSON.stringify({
|
||||||
|
folder: '1234', // id that doesn't exist
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error.message).toBe("the folder doesn't exist");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -38,6 +38,7 @@ describe('Folder', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
expect(res.body.data).toMatchObject({
|
expect(res.body.data).toMatchObject({
|
||||||
id: expect.anything(),
|
id: expect.anything(),
|
||||||
name: 'folder 1',
|
name: 'folder 1',
|
||||||
@ -51,51 +52,6 @@ describe('Folder', () => {
|
|||||||
data.folders.push(omit('parent', res.body.data));
|
data.folders.push(omit('parent', res.body.data));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Cannot create a folder with duplicated name at root level', async () => {
|
|
||||||
const res = await rq({
|
|
||||||
method: 'POST',
|
|
||||||
url: '/upload/folders?populate=parent',
|
|
||||||
body: {
|
|
||||||
name: 'folder 1',
|
|
||||||
parent: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.status).toBe(400);
|
|
||||||
expect(res.body.error.message).toBe('name already taken');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Cannot create a folder with name containing a slash', async () => {
|
|
||||||
const res = await rq({
|
|
||||||
method: 'POST',
|
|
||||||
url: '/upload/folders?populate=parent',
|
|
||||||
body: {
|
|
||||||
name: 'folder 1/2',
|
|
||||||
parent: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.status).toBe(400);
|
|
||||||
expect(res.body.error.message).toBe('name cannot contain slashes');
|
|
||||||
});
|
|
||||||
|
|
||||||
test.each([[' abc'], [' abc '], ['abc '], [' abc '], [' abc ']])(
|
|
||||||
'Cannot create a folder with name starting or ending with a whitespace',
|
|
||||||
async name => {
|
|
||||||
const res = await rq({
|
|
||||||
method: 'POST',
|
|
||||||
url: '/upload/folders?populate=parent',
|
|
||||||
body: {
|
|
||||||
name,
|
|
||||||
parent: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.status).toBe(400);
|
|
||||||
expect(res.body.error.message).toBe('name cannot start or end with a whitespace');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
test('Can create a folder inside another folder', async () => {
|
test('Can create a folder inside another folder', async () => {
|
||||||
const res = await rq({
|
const res = await rq({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -118,6 +74,65 @@ describe('Folder', () => {
|
|||||||
|
|
||||||
data.folders.push(omit('parent', res.body.data));
|
data.folders.push(omit('parent', res.body.data));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Cannot create a folder with duplicated name at root level', async () => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/upload/folders?populate=parent',
|
||||||
|
body: {
|
||||||
|
name: 'folder 1',
|
||||||
|
parent: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error.message).toBe('name already taken');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Cannot create a folder with duplicated name inside a folder', async () => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/upload/folders?populate=parent',
|
||||||
|
body: {
|
||||||
|
name: 'folder-2',
|
||||||
|
parent: data.folders[0],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error.message).toBe('name already taken');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Cannot create a folder with name containing a slash', async () => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/upload/folders?populate=parent',
|
||||||
|
body: {
|
||||||
|
name: 'folder 1/2',
|
||||||
|
parent: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error.message).toBe('name cannot contain slashes');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each([[' abc'], [' abc '], ['abc '], [' abc '], [' abc ']])(
|
||||||
|
'Cannot create a folder with name starting or ending with a whitespace (%p)',
|
||||||
|
async name => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/upload/folders?populate=parent',
|
||||||
|
body: {
|
||||||
|
name,
|
||||||
|
parent: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error.message).toBe('name cannot start or end with a whitespace');
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('read', () => {
|
describe('read', () => {
|
||||||
@ -133,7 +148,6 @@ describe('Folder', () => {
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 2,
|
total: 2,
|
||||||
});
|
});
|
||||||
expect(res.body.results).toHaveLength(2);
|
|
||||||
expect(res.body.results).toEqual(
|
expect(res.body.results).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{
|
{
|
||||||
@ -193,4 +207,37 @@ describe('Folder', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('delete', () => {
|
||||||
|
test('Can delete folders', async () => {
|
||||||
|
const res = await rq({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/upload/folders/batch-delete',
|
||||||
|
body: {
|
||||||
|
ids: data.folders.map(f => f.id),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.body.data).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
createdAt: expect.anything(),
|
||||||
|
id: expect.anything(),
|
||||||
|
name: 'folder 1',
|
||||||
|
path: '/folder 1',
|
||||||
|
uid: expect.anything(),
|
||||||
|
updatedAt: expect.anything(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createdAt: expect.anything(),
|
||||||
|
id: expect.anything(),
|
||||||
|
name: 'folder-2',
|
||||||
|
path: '/folder 1/folder-2',
|
||||||
|
uid: expect.anything(),
|
||||||
|
updatedAt: expect.anything(),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user