Skip to content

Commit

Permalink
Merge pull request #370 from internxt/feat/move-folders-can-now-accep…
Browse files Browse the repository at this point in the history
…t-trashed-folders

[_] fix: trashed folders can now be moved as expected
  • Loading branch information
apsantiso authored Jul 22, 2024
2 parents 8615a34 + 8d2a933 commit baba140
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 29 deletions.
3 changes: 3 additions & 0 deletions src/modules/folder/folder.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,9 @@ export class FolderController {
}

@Patch('/:uuid')
@WorkspacesInBehalfValidationFolder([
{ sourceKey: 'params', fieldName: 'uuid', newFieldName: 'itemId' },
])
async moveFolder(
@UserDecorator() user: User,
@Param('uuid') folderUuid: Folder['uuid'],
Expand Down
65 changes: 37 additions & 28 deletions src/modules/folder/folder.usecase.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ describe('FolderUseCases', () => {
attributes: { userId: userMocked.id, removed: false },
});

jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(folder);
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(folder);
jest
.spyOn(folderRepository, 'findById')
.mockResolvedValueOnce(mockParentFolder);
Expand Down Expand Up @@ -726,57 +726,68 @@ describe('FolderUseCases', () => {
);
});

it('When folder is moved but it is removed, then an error is thrown', () => {
it('When folder is moved but it is removed, then an error is thrown', async () => {
const mockFolder = newFolder({
attributes: { userId: userMocked.id, removed: true },
});

jest
.spyOn(folderRepository, 'findByUuid')
.mockResolvedValueOnce(mockFolder);
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(mockFolder);

expect(
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(`Folder ${folder.uuid} can not be moved`);
});

it('When folder is moved but its parent folder is removed, then an error is thrown', () => {
it('When moved folder is not owned by user, then an error is thrown', async () => {
const notOwnerUser = newUser();
const mockFolder = newFolder({
attributes: { userId: userMocked.id, removed: true },
});

jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(mockFolder);

await expect(
service.moveFolder(notOwnerUser, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(ForbiddenException);
});

it('When folder is moved but its parent folder is removed, then an error is thrown', async () => {
const mockParentFolder = newFolder({
attributes: { userId: userMocked.id, removed: true },
});

jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(folder);
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(folder);
jest
.spyOn(folderRepository, 'findById')
.mockResolvedValueOnce(mockParentFolder);

expect(
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(`Folder ${folder.uuid} can not be moved`);
});

it('When folder is moved but the destination folder is removed, then an error is thrown', () => {
it('When folder is moved but the destination folder is removed, then an error is thrown', async () => {
const mockParentFolder = newFolder({
attributes: { userId: userMocked.id, removed: false },
});
const mockDestinationFolder = newFolder({
attributes: { userId: userMocked.id, removed: true },
});

jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(folder);
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(folder);
jest
.spyOn(folderRepository, 'findById')
.mockResolvedValueOnce(mockParentFolder);
jest
.spyOn(folderRepository, 'findByUuid')
.mockResolvedValueOnce(mockDestinationFolder);

expect(
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(`Folder can not be moved to ${destinationFolder.uuid}`);
});

it('When root folder is moved, then an error is thrown', () => {
it('When root folder is moved, then an error is thrown', async () => {
const mockFolder = newFolder({
attributes: {
userId: userMocked.id,
Expand All @@ -785,30 +796,28 @@ describe('FolderUseCases', () => {
},
});

jest
.spyOn(folderRepository, 'findByUuid')
.mockResolvedValueOnce(mockFolder);
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(mockFolder);

expect(
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow('The root folder can not be moved');
});

it('When folder is moved from/to a non-existent folder, then it should throw a not found error', () => {
jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(null);
expect(
it('When folder is moved from/to a non-existent folder, then it should throw a not found error', async () => {
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(null);
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(NotFoundException);

jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(folder);
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(folder);
jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(null);
expect(
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(NotFoundException);
});

it('When folder is moved to a folder that has been already moved to, then it should throw a conflict error', () => {
jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(folder);
it('When folder is moved to a folder that has been already moved to, then it should throw a conflict error', async () => {
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(folder);
jest
.spyOn(folderRepository, 'findByUuid')
.mockResolvedValueOnce(destinationFolder);
Expand All @@ -820,21 +829,21 @@ describe('FolderUseCases', () => {
.spyOn(folderRepository, 'findByNameAndParentUuid')
.mockResolvedValueOnce(folder);

expect(
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(
`Folder ${folder.uuid} was already moved to that location`,
);
});

it('When folder is moved to a folder that has already a folder with the same name, then it should throw a conflict error', () => {
it('When folder is moved to a folder that has already a folder with the same name, then it should throw a conflict error', async () => {
const conflictFolder = newFolder({
attributes: {
...folder,
uuid: v4(),
},
});
jest.spyOn(folderRepository, 'findByUuid').mockResolvedValueOnce(folder);
jest.spyOn(folderRepository, 'findOne').mockResolvedValueOnce(folder);
jest
.spyOn(folderRepository, 'findByUuid')
.mockResolvedValueOnce(destinationFolder);
Expand All @@ -846,7 +855,7 @@ describe('FolderUseCases', () => {
.spyOn(folderRepository, 'findByNameAndParentUuid')
.mockResolvedValueOnce(conflictFolder);

expect(
await expect(
service.moveFolder(userMocked, folder.uuid, destinationFolder.uuid),
).rejects.toThrow(
'A folder with the same name already exists in destination folder',
Expand Down
13 changes: 12 additions & 1 deletion src/modules/folder/folder.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,18 @@ export class FolderUseCases {
folderUuid: Folder['uuid'],
destinationUuid: Folder['uuid'],
): Promise<Folder> {
const folder = await this.getFolderByUuidAndUser(folderUuid, user);
const folder = await this.folderRepository.findOne({
uuid: folderUuid,
});

if (!folder) {
throw new NotFoundException('Folder does not exist');
}

if (!folder.isOwnedBy(user)) {
throw new ForbiddenException();
}

if (folder.isRootFolder()) {
throw new UnprocessableEntityException(
'The root folder can not be moved',
Expand Down

0 comments on commit baba140

Please sign in to comment.