--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+describe('Collection panel tests', function () {
+ let activeUser;
+ let adminUser;
+
+ before(function () {
+ cy.getUser('admin', 'Admin', 'User', true, true)
+ .as('adminUser').then(function () {
+ adminUser = this.adminUser;
+ }
+ );
+ cy.getUser('collectionuser1', 'Collection', 'User', false, true)
+ .as('activeUser').then(function () {
+ activeUser = this.activeUser;
+ }
+ );
+ });
+
+ beforeEach(function () {
+ cy.clearCookies();
+ cy.clearLocalStorage();
+ });
+
+ it('deletes all files from root dir', function () {
+ cy.createCollection(adminUser.token, {
+ name: `Test collection ${Math.floor(Math.random() * 999999)}`,
+ owner_uuid: activeUser.user.uuid,
+ manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:baz\n"
+ })
+ .as('testCollection').then(function () {
+ cy.loginAs(activeUser);
+ cy.visit(`/collections/${this.testCollection.uuid}`);
+ cy.get('[data-cy=collection-files-panel]').within(() => {
+ cy.get('[type="checkbox"]').first().check();
+ cy.get('[type="checkbox"]').last().check();
+ });
+ cy.get('[data-cy=collection-files-panel-options-btn]').click();
+ cy.get('[data-cy=context-menu] div').contains('Remove selected').click();
+ cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+ cy.get('[data-cy=collection-files-panel]')
+ .should('not.contain', 'baz')
+ .and('not.contain', 'bar');
+ });
+ });
+
+ it('deletes all files from non root dir', function () {
+ cy.createCollection(adminUser.token, {
+ name: `Test collection ${Math.floor(Math.random() * 999999)}`,
+ owner_uuid: activeUser.user.uuid,
+ manifest_text: "./subdir 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo\n. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:baz\n"
+ })
+ .as('testCollection').then(function () {
+ cy.loginAs(activeUser);
+ cy.visit(`/collections/${this.testCollection.uuid}`);
+
+ cy.get('[data-cy=virtual-file-tree] > div > i').first().click();
+ cy.get('[data-cy=collection-files-panel]')
+ .should('contain', 'foo');
+
+ cy.get('[data-cy=collection-files-panel]')
+ .contains('foo').closest('[data-cy=virtual-file-tree]').find('[type="checkbox"]').click();
+
+ cy.get('[data-cy=collection-files-panel-options-btn]').click();
+ cy.get('[data-cy=context-menu] div').contains('Remove selected').click();
+ cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+
+ cy.get('[data-cy=collection-files-panel]')
+ .should('not.contain', 'subdir')
+ .and('contain', 'baz');
+ });
+ });
+})
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { AxiosInstance } from 'axios';
+import { WebDAV } from '~/common/webdav';
+import { ApiActions } from '../api/api-actions';
+import { AuthService } from '../auth-service/auth-service';
+import { CollectionService } from './collection-service';
+
+describe('collection-service', () => {
+ let collectionService: CollectionService;
+ let serverApi;
+ let webdavClient: any;
+ let authService;
+ let actions;
+
+ beforeEach(() => {
+ serverApi = {} as AxiosInstance;
+ webdavClient = {
+ delete: jest.fn(),
+ } as any;
+ authService = {} as AuthService;
+ actions = {} as ApiActions;
+ collectionService = new CollectionService(serverApi, webdavClient, authService, actions);
+ });
+
+ describe('deleteFiles', () => {
+ it('should remove no files', async () => {
+ // given
+ const filePaths: string[] = [];
+ const collectionUUID = '';
+
+ // when
+ await collectionService.deleteFiles(collectionUUID, filePaths);
+
+ // then
+ expect(webdavClient.delete).not.toHaveBeenCalled();
+ });
+
+ it('should remove only root files', async () => {
+ // given
+ const filePaths: string[] = ['/root/1', '/root/1/100', '/root/1/100/test.txt', '/root/2', '/root/2/200', '/root/3/300/test.txt'];
+ const collectionUUID = '';
+
+ // when
+ await collectionService.deleteFiles(collectionUUID, filePaths);
+
+ // then
+ expect(webdavClient.delete).toHaveBeenCalledTimes(3);
+ expect(webdavClient.delete).toHaveBeenCalledWith("c=/root/3/300/test.txt");
+ expect(webdavClient.delete).toHaveBeenCalledWith("c=/root/2");
+ expect(webdavClient.delete).toHaveBeenCalledWith("c=/root/1");
+ });
+
+ it('should remove files with uuid prefix', async () => {
+ // given
+ const filePaths: string[] = ['/root/1'];
+ const collectionUUID = 'zzzzz-tpzed-5o5tg0l9a57gxxx';
+
+ // when
+ await collectionService.deleteFiles(collectionUUID, filePaths);
+
+ // then
+ expect(webdavClient.delete).toHaveBeenCalledTimes(1);
+ expect(webdavClient.delete).toHaveBeenCalledWith("c=zzzzz-tpzed-5o5tg0l9a57gxxx/root/1");
+ });
+ });
+});
\ No newline at end of file
}
async deleteFiles(collectionUuid: string, filePaths: string[]) {
- if (collectionUuid === "" || filePaths.length === 0) { return; }
- for (const path of filePaths) {
- const splittedPath = path.split('/');
- if (collectionUuid) {
- await this.webdavClient.delete(`c=${collectionUuid}/${splittedPath[1]}`);
- } else {
+ const sortedUniquePaths = Array.from(new Set(filePaths))
+ .sort((a, b) => a.length - b.length)
+ .reduce((acc, currentPath) => {
+ const parentPathFound = acc.find((parentPath) => currentPath.indexOf(`${parentPath}/`) > -1);
+
+ if (!parentPathFound) {
+ return [...acc, currentPath];
+ }
+
+ return acc;
+ }, []);
+
+ for (const path of sortedUniquePaths) {
+ if (path.indexOf(collectionUuid) === -1) {
await this.webdavClient.delete(`c=${collectionUuid}${path}`);
+ } else {
+ await this.webdavClient.delete(`c=${path}`);
}
}
await this.update(collectionUuid, { preserveVersion: true });
dispatch(snackbarActions.OPEN_SNACKBAR({
message: `Error getting file list`,
hideDuration: 2000,
- kind: SnackbarKind.ERROR }));
+ kind: SnackbarKind.ERROR
+ }));
});
};
dispatch<any>(loadCollectionPanel(currentCollection.uuid, true));
dispatch(dialogActions.CLOSE_DIALOG({ id: RENAME_FILE_DIALOG }));
dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'File name changed.', hideDuration: 2000 }));
- }).catch (e => {
+ }).catch(e => {
const errors: FormErrors<RenameFileDialogData, string> = {
path: `Could not rename the file: ${e.responseText}`
};