mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			521 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			521 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
const fs = require('fs');
 | 
						|
const path = require('path');
 | 
						|
 | 
						|
const { createTestBuilder } = require('api-tests/builder');
 | 
						|
const { createStrapiInstance } = require('api-tests/strapi');
 | 
						|
const { createAuthRequest } = require('api-tests/request');
 | 
						|
 | 
						|
let strapi;
 | 
						|
let rq;
 | 
						|
const data = {
 | 
						|
  folders: [],
 | 
						|
  files: [],
 | 
						|
};
 | 
						|
 | 
						|
const createFolder = async (name, parent = null) => {
 | 
						|
  const res = await rq({
 | 
						|
    method: 'POST',
 | 
						|
    url: '/upload/folders',
 | 
						|
    body: { name, parent },
 | 
						|
  });
 | 
						|
  return res.body.data;
 | 
						|
};
 | 
						|
 | 
						|
const createAFile = async (parent = null) => {
 | 
						|
  const res = await rq({
 | 
						|
    method: 'POST',
 | 
						|
    url: '/upload',
 | 
						|
    formData: {
 | 
						|
      files: fs.createReadStream(path.join(__dirname, '../utils/rec.jpg')),
 | 
						|
      fileInfo: JSON.stringify({ folder: parent }),
 | 
						|
    },
 | 
						|
  });
 | 
						|
  return res.body[0];
 | 
						|
};
 | 
						|
 | 
						|
describe('Bulk actions for folders & files', () => {
 | 
						|
  const builder = createTestBuilder();
 | 
						|
 | 
						|
  beforeAll(async () => {
 | 
						|
    strapi = await createStrapiInstance();
 | 
						|
    rq = await createAuthRequest({ strapi });
 | 
						|
  });
 | 
						|
 | 
						|
  afterAll(async () => {
 | 
						|
    await rq({
 | 
						|
      method: 'POST',
 | 
						|
      url: '/upload/actions/bulk-delete',
 | 
						|
      body: {
 | 
						|
        folderIds: data.folders.map((f) => f.id),
 | 
						|
      },
 | 
						|
    });
 | 
						|
 | 
						|
    await strapi.destroy();
 | 
						|
    await builder.cleanup();
 | 
						|
  });
 | 
						|
 | 
						|
  describe('delete', () => {
 | 
						|
    test('Can delete folders and files', async () => {
 | 
						|
      const folder1 = await createFolder('folder-a-1', null);
 | 
						|
      const folder1a = await createFolder('folder-a-1a', folder1.id);
 | 
						|
      const folder1b = await createFolder('folder-a-1b', folder1.id);
 | 
						|
      const folder1a1 = await createFolder('folder-a-1a1', folder1a.id);
 | 
						|
      const file1 = await createAFile(null);
 | 
						|
      const file1b = await createAFile(folder1b.id);
 | 
						|
      const file1a = await createAFile(folder1a.id);
 | 
						|
      const file1a1 = await createAFile(folder1a1.id);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-delete',
 | 
						|
        body: {
 | 
						|
          fileIds: [file1.id],
 | 
						|
          folderIds: [folder1a.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.body.data).toMatchObject({
 | 
						|
        files: [
 | 
						|
          {
 | 
						|
            alternativeText: null,
 | 
						|
            caption: null,
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            ext: '.jpg',
 | 
						|
            folderPath: '/',
 | 
						|
            formats: null,
 | 
						|
            hash: expect.anything(),
 | 
						|
            height: 20,
 | 
						|
            id: file1.id,
 | 
						|
            mime: 'image/jpeg',
 | 
						|
            name: 'rec.jpg',
 | 
						|
            previewUrl: null,
 | 
						|
            provider: 'local',
 | 
						|
            provider_metadata: null,
 | 
						|
            size: 0.27,
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
            url: expect.anything(),
 | 
						|
            width: 20,
 | 
						|
          },
 | 
						|
        ],
 | 
						|
        folders: [
 | 
						|
          {
 | 
						|
            id: folder1a.id,
 | 
						|
            name: 'folder-a-1a',
 | 
						|
            path: expect.anything(),
 | 
						|
            pathId: expect.any(Number),
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      });
 | 
						|
 | 
						|
      const resFolder = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/folders',
 | 
						|
      });
 | 
						|
 | 
						|
      const existingfoldersIds = resFolder.body.data.map((f) => f.id);
 | 
						|
      expect(existingfoldersIds).toEqual(expect.not.arrayContaining([folder1a.id, folder1a1.id]));
 | 
						|
      expect(existingfoldersIds).toEqual(expect.arrayContaining([folder1.id, folder1b.id]));
 | 
						|
 | 
						|
      const resFiles = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/files',
 | 
						|
        qs: {
 | 
						|
          pageSize: 100,
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const existingfilesIds = resFiles.body.results.map((f) => f.id);
 | 
						|
      expect(existingfilesIds).toEqual(
 | 
						|
        expect.not.arrayContaining([file1.id, file1a.id, file1a1.id])
 | 
						|
      );
 | 
						|
      expect(existingfilesIds).toEqual(expect.arrayContaining([file1b.id]));
 | 
						|
 | 
						|
      data.folders.push(folder1, folder1b);
 | 
						|
      data.files.push(file1b);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Can delete only files', async () => {
 | 
						|
      const file = await createAFile(null);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-delete',
 | 
						|
        body: {
 | 
						|
          fileIds: [file.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.body.data).toMatchObject({
 | 
						|
        files: [
 | 
						|
          {
 | 
						|
            alternativeText: null,
 | 
						|
            caption: null,
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            ext: '.jpg',
 | 
						|
            folderPath: '/',
 | 
						|
            formats: null,
 | 
						|
            hash: expect.anything(),
 | 
						|
            height: 20,
 | 
						|
            id: file.id,
 | 
						|
            mime: 'image/jpeg',
 | 
						|
            name: 'rec.jpg',
 | 
						|
            previewUrl: null,
 | 
						|
            provider: 'local',
 | 
						|
            provider_metadata: null,
 | 
						|
            size: 0.27,
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
            url: expect.anything(),
 | 
						|
            width: 20,
 | 
						|
          },
 | 
						|
        ],
 | 
						|
        folders: [],
 | 
						|
      });
 | 
						|
 | 
						|
      const resFiles = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/files',
 | 
						|
        qs: {
 | 
						|
          pageSize: 100,
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const existingfilesIds = resFiles.body.results.map((f) => f.id);
 | 
						|
      expect(existingfilesIds).toEqual(expect.not.arrayContaining([file.id]));
 | 
						|
    });
 | 
						|
 | 
						|
    test('Can delete only folders', async () => {
 | 
						|
      const folder = await createFolder('a random folder', null);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-delete',
 | 
						|
        body: {
 | 
						|
          folderIds: [folder.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.body.data).toMatchObject({
 | 
						|
        files: [],
 | 
						|
        folders: [
 | 
						|
          {
 | 
						|
            id: folder.id,
 | 
						|
            name: 'a random folder',
 | 
						|
            path: expect.anything(),
 | 
						|
            pathId: expect.any(Number),
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      });
 | 
						|
 | 
						|
      const resFolder = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/folders',
 | 
						|
      });
 | 
						|
 | 
						|
      const existingfoldersIds = resFolder.body.data.map((f) => f.id);
 | 
						|
      expect(existingfoldersIds).toEqual(expect.not.arrayContaining([folder.id]));
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('move', () => {
 | 
						|
    test('Can move folders and files into another folder', async () => {
 | 
						|
      const folder1 = await createFolder('folder-b-1', null);
 | 
						|
      const folder1a = await createFolder('folder-b-1a', folder1.id);
 | 
						|
      const folder1b = await createFolder('folder-b-1b', folder1.id);
 | 
						|
      const folder1a1 = await createFolder('folder-b-1a1', folder1a.id);
 | 
						|
      const file1 = await createAFile(null);
 | 
						|
      const file1a = await createAFile(folder1a.id);
 | 
						|
      const file1b = await createAFile(folder1b.id);
 | 
						|
      const file1a1 = await createAFile(folder1a1.id);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-move',
 | 
						|
        body: {
 | 
						|
          destinationFolderId: folder1b.id,
 | 
						|
          fileIds: [file1a.id],
 | 
						|
          folderIds: [folder1a.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.body.data).toMatchObject({
 | 
						|
        files: [
 | 
						|
          {
 | 
						|
            alternativeText: null,
 | 
						|
            caption: null,
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            ext: '.jpg',
 | 
						|
            folderPath: folder1b.path,
 | 
						|
            formats: null,
 | 
						|
            hash: expect.anything(),
 | 
						|
            height: 20,
 | 
						|
            id: file1a.id,
 | 
						|
            mime: 'image/jpeg',
 | 
						|
            name: 'rec.jpg',
 | 
						|
            previewUrl: null,
 | 
						|
            provider: 'local',
 | 
						|
            provider_metadata: null,
 | 
						|
            size: 0.27,
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
            url: expect.anything(),
 | 
						|
            width: 20,
 | 
						|
          },
 | 
						|
        ],
 | 
						|
        folders: [
 | 
						|
          {
 | 
						|
            id: folder1a.id,
 | 
						|
            name: 'folder-b-1a',
 | 
						|
            path: `${folder1b.path}/${folder1a.pathId}`,
 | 
						|
            pathId: expect.any(Number),
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      });
 | 
						|
 | 
						|
      const {
 | 
						|
        body: { data: folderResults },
 | 
						|
      } = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/folders',
 | 
						|
        qs: {
 | 
						|
          populate: 'parent',
 | 
						|
          sort: 'id:asc',
 | 
						|
          filters: { id: { $in: [folder1.id, folder1a.id, folder1b.id, folder1a1.id] } },
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(folderResults[0]).toMatchObject({ ...folder1, parent: null });
 | 
						|
      expect(folderResults[1]).toMatchObject({
 | 
						|
        ...folder1a,
 | 
						|
        path: `${folder1b.path}/${folder1a.pathId}`,
 | 
						|
        parent: { id: folder1b.id },
 | 
						|
        updatedAt: expect.anything(),
 | 
						|
      });
 | 
						|
      expect(folderResults[2]).toMatchObject({ ...folder1b, parent: { id: folder1.id } });
 | 
						|
      expect(folderResults[3]).toMatchObject({
 | 
						|
        ...folder1a1,
 | 
						|
        path: `${folder1b.path}/${folder1a.pathId}/${folder1a1.pathId}`,
 | 
						|
        parent: { id: folder1a.id },
 | 
						|
      });
 | 
						|
 | 
						|
      const {
 | 
						|
        body: { results: fileResults },
 | 
						|
      } = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/files',
 | 
						|
        qs: {
 | 
						|
          pageSize: 100,
 | 
						|
          populate: 'folder',
 | 
						|
          sort: 'id:asc',
 | 
						|
          filters: { id: { $in: [file1.id, file1a.id, file1b.id, file1a1.id] } },
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(fileResults[0]).toMatchObject({ ...file1, folder: null });
 | 
						|
      expect(fileResults[1]).toMatchObject({
 | 
						|
        ...file1a,
 | 
						|
        folderPath: folder1b.path,
 | 
						|
        folder: { id: folder1b.id },
 | 
						|
        updatedAt: expect.anything(),
 | 
						|
      });
 | 
						|
      expect(fileResults[2]).toMatchObject({ ...file1b, folder: { id: folder1b.id } });
 | 
						|
      expect(fileResults[3]).toMatchObject({
 | 
						|
        ...file1a1,
 | 
						|
        folderPath: `${folder1b.path}/${folder1a.pathId}/${folder1a1.pathId}`,
 | 
						|
        folder: { id: folder1a1.id },
 | 
						|
      });
 | 
						|
 | 
						|
      data.folders.push(...folderResults);
 | 
						|
      data.files.push(...fileResults);
 | 
						|
    });
 | 
						|
    test('Can move folders and files to the root level', async () => {
 | 
						|
      const folder1 = await createFolder('folder-c-1', null);
 | 
						|
      const folder1a = await createFolder('folder-c-1a', folder1.id);
 | 
						|
      const folder1a1 = await createFolder('folder-c-1a1', folder1a.id);
 | 
						|
      const file1 = await createAFile(null);
 | 
						|
      const file1a = await createAFile(folder1a.id);
 | 
						|
      const file1a1 = await createAFile(folder1a1.id);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-move',
 | 
						|
        body: {
 | 
						|
          destinationFolderId: null,
 | 
						|
          fileIds: [file1a.id],
 | 
						|
          folderIds: [folder1a.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.body.data).toMatchObject({
 | 
						|
        files: [
 | 
						|
          {
 | 
						|
            alternativeText: null,
 | 
						|
            caption: null,
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            ext: '.jpg',
 | 
						|
            folderPath: '/',
 | 
						|
            formats: null,
 | 
						|
            hash: expect.anything(),
 | 
						|
            height: 20,
 | 
						|
            id: file1a.id,
 | 
						|
            mime: 'image/jpeg',
 | 
						|
            name: 'rec.jpg',
 | 
						|
            previewUrl: null,
 | 
						|
            provider: 'local',
 | 
						|
            provider_metadata: null,
 | 
						|
            size: 0.27,
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
            url: expect.anything(),
 | 
						|
            width: 20,
 | 
						|
          },
 | 
						|
        ],
 | 
						|
        folders: [
 | 
						|
          {
 | 
						|
            id: folder1a.id,
 | 
						|
            name: 'folder-c-1a',
 | 
						|
            path: `/${folder1a.pathId}`,
 | 
						|
            pathId: expect.any(Number),
 | 
						|
            createdAt: expect.anything(),
 | 
						|
            updatedAt: expect.anything(),
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      });
 | 
						|
 | 
						|
      const {
 | 
						|
        body: { data: folderResults },
 | 
						|
      } = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/folders?populate=parent',
 | 
						|
        qs: {
 | 
						|
          populate: 'parent',
 | 
						|
          sort: 'id:asc',
 | 
						|
          filters: { id: { $in: [folder1.id, folder1a.id, folder1a1.id] } },
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(folderResults[0]).toMatchObject({ ...folder1, parent: null });
 | 
						|
      expect(folderResults[1]).toMatchObject({
 | 
						|
        ...folder1a,
 | 
						|
        path: `/${folder1a.pathId}`,
 | 
						|
        parent: null,
 | 
						|
        updatedAt: expect.anything(),
 | 
						|
      });
 | 
						|
      expect(folderResults[2]).toMatchObject({
 | 
						|
        ...folder1a1,
 | 
						|
        path: `/${folder1a.pathId}/${folder1a1.pathId}`,
 | 
						|
        parent: { id: folder1a.id },
 | 
						|
      });
 | 
						|
 | 
						|
      const {
 | 
						|
        body: { results: fileResults },
 | 
						|
      } = await rq({
 | 
						|
        method: 'GET',
 | 
						|
        url: '/upload/files',
 | 
						|
        qs: {
 | 
						|
          pageSize: 100,
 | 
						|
          populate: 'folder',
 | 
						|
          sort: 'id:asc',
 | 
						|
          filters: { id: { $in: [file1.id, file1a.id, file1a1.id] } },
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(fileResults[0]).toMatchObject({ ...file1, folder: null });
 | 
						|
      expect(fileResults[1]).toMatchObject({
 | 
						|
        ...file1a,
 | 
						|
        folderPath: '/',
 | 
						|
        folder: null,
 | 
						|
        updatedAt: expect.anything(),
 | 
						|
      });
 | 
						|
      expect(fileResults[2]).toMatchObject({
 | 
						|
        ...file1a1,
 | 
						|
        folderPath: `/${folder1a.pathId}/${folder1a1.pathId}`,
 | 
						|
        folder: { id: folder1a1.id },
 | 
						|
      });
 | 
						|
 | 
						|
      data.folders.push(...folderResults);
 | 
						|
      data.files.push(...fileResults);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Cannot move a folder inside itself (0 level)', async () => {
 | 
						|
      const folder1 = await createFolder('folder-d-1', null);
 | 
						|
      data.folders.push(folder1);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-move',
 | 
						|
        body: {
 | 
						|
          destinationFolderId: folder1.id,
 | 
						|
          folderIds: [folder1.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
      expect(res.status).toBe(400);
 | 
						|
      expect(res.body.error.message).toBe(
 | 
						|
        'folders cannot be moved inside themselves or one of its children: folder-d-1'
 | 
						|
      );
 | 
						|
    });
 | 
						|
 | 
						|
    test('Cannot move a folder inside itself (1 level)', async () => {
 | 
						|
      const folder1 = await createFolder('folder-e-1', null);
 | 
						|
      const folder1a = await createFolder('folder-e-1a', folder1.id);
 | 
						|
      data.folders.push(folder1, folder1a);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-move',
 | 
						|
        body: {
 | 
						|
          destinationFolderId: folder1a.id,
 | 
						|
          folderIds: [folder1.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
      expect(res.status).toBe(400);
 | 
						|
      expect(res.body.error.message).toBe(
 | 
						|
        'folders cannot be moved inside themselves or one of its children: folder-e-1'
 | 
						|
      );
 | 
						|
    });
 | 
						|
 | 
						|
    test('Cannot move a folder inside itself (2 levels)', async () => {
 | 
						|
      const folder1 = await createFolder('folder-f-1', null);
 | 
						|
      const folder1a = await createFolder('folder-f-1a', folder1.id);
 | 
						|
      const folder1a1 = await createFolder('folder-f-1a1', folder1a.id);
 | 
						|
      data.folders.push(folder1, folder1a, folder1a1);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-move',
 | 
						|
        body: {
 | 
						|
          destinationFolderId: folder1a1.id,
 | 
						|
          folderIds: [folder1.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
      expect(res.status).toBe(400);
 | 
						|
      expect(res.body.error.message).toBe(
 | 
						|
        'folders cannot be moved inside themselves or one of its children: folder-f-1'
 | 
						|
      );
 | 
						|
    });
 | 
						|
 | 
						|
    test('Cannot move a folder if it creates a duplicate', async () => {
 | 
						|
      const folder1 = await createFolder('folder-g-1', null);
 | 
						|
      const folder1a = await createFolder('folder-g-1a', folder1.id);
 | 
						|
      const folder2 = await createFolder('folder-g-1a', null);
 | 
						|
      data.folders.push(folder1, folder1a, folder2);
 | 
						|
 | 
						|
      const res = await rq({
 | 
						|
        method: 'POST',
 | 
						|
        url: '/upload/actions/bulk-move',
 | 
						|
        body: {
 | 
						|
          destinationFolderId: folder1.id,
 | 
						|
          folderIds: [folder2.id],
 | 
						|
        },
 | 
						|
      });
 | 
						|
      expect(res.status).toBe(400);
 | 
						|
      expect(res.body.error.message).toBe('some folders already exists: folder-g-1a');
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 |