[ACA-9380] fix Incorrect behavior when doing a multiple selection Copy or Move and only some of the items fail to be copied (#31)

* [ACA-938] Incorrect behavior when doing a multiple selection Copy or Move and only some of the items fail to be copied

* [ACA-938] Incorrect behavior when doing a multiple selection Copy or Move and only some of the items fail to be copied

unit tests changes according to partial action changes
This commit is contained in:
suzanadirla
2017-11-02 18:50:24 +02:00
committed by Denys Vuika
parent 7007c735e4
commit 8401f939cc
15 changed files with 156 additions and 70 deletions

View File

@@ -116,6 +116,82 @@ describe('NodeCopyDirective', () => {
); );
}); });
it('notifies partially copy of one node out of a multiple selection of nodes', () => {
spyOn(service, 'copyNodes').and.returnValue(Observable.of('OPERATION.SUCCES.CONTENT.COPY'));
component.selection = [
{ entry: { id: 'node-to-copy-1', name: 'name1' } },
{ entry: { id: 'node-to-copy-2', name: 'name2' } }];
const createdItems = [
{ entry: { id: 'copy-of-node-1', name: 'name1' } }];
fixture.detectChanges();
element.triggerEventHandler('click', null);
service.contentCopied.next(<any>createdItems);
expect(service.copyNodes).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction).toHaveBeenCalledWith(
'APP.MESSAGES.INFO.NODE_COPY.PARTIAL_SINGULAR', 'Undo', 10000
);
});
it('notifies partially copy of more nodes out of a multiple selection of nodes', () => {
spyOn(service, 'copyNodes').and.returnValue(Observable.of('OPERATION.SUCCES.CONTENT.COPY'));
component.selection = [
{ entry: { id: 'node-to-copy-0', name: 'name0' } },
{ entry: { id: 'node-to-copy-1', name: 'name1' } },
{ entry: { id: 'node-to-copy-2', name: 'name2' } }];
const createdItems = [
{ entry: { id: 'copy-of-node-0', name: 'name0' } },
{ entry: { id: 'copy-of-node-1', name: 'name1' } }];
fixture.detectChanges();
element.triggerEventHandler('click', null);
service.contentCopied.next(<any>createdItems);
expect(service.copyNodes).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction).toHaveBeenCalledWith(
'APP.MESSAGES.INFO.NODE_COPY.PARTIAL_PLURAL', 'Undo', 10000
);
});
it('notifies of failed copy of multiple nodes', () => {
spyOn(service, 'copyNodes').and.returnValue(Observable.of('OPERATION.SUCCES.CONTENT.COPY'));
component.selection = [
{ entry: { id: 'node-to-copy-0', name: 'name0' } },
{ entry: { id: 'node-to-copy-1', name: 'name1' } },
{ entry: { id: 'node-to-copy-2', name: 'name2' } }];
const createdItems = [];
fixture.detectChanges();
element.triggerEventHandler('click', null);
service.contentCopied.next(<any>createdItems);
expect(service.copyNodes).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction).toHaveBeenCalledWith(
'APP.MESSAGES.INFO.NODE_COPY.FAIL_PLURAL', '', 3000
);
});
it('notifies of failed copy of one node', () => {
spyOn(service, 'copyNodes').and.returnValue(Observable.of('OPERATION.SUCCES.CONTENT.COPY'));
component.selection = [
{ entry: { id: 'node-to-copy', name: 'name' } }];
const createdItems = [];
fixture.detectChanges();
element.triggerEventHandler('click', null);
service.contentCopied.next(<any>createdItems);
expect(service.copyNodes).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction).toHaveBeenCalledWith(
'APP.MESSAGES.INFO.NODE_COPY.FAIL_SINGULAR', '', 3000
);
});
it('notifies error if success message was not emitted', () => { it('notifies error if success message was not emitted', () => {
spyOn(service, 'copyNodes').and.returnValue(Observable.of('')); spyOn(service, 'copyNodes').and.returnValue(Observable.of(''));

View File

@@ -60,14 +60,27 @@ export class NodeCopyDirective {
} }
private toastMessage(info: any, newItems?: MinimalNodeEntity[]) { private toastMessage(info: any, newItems?: MinimalNodeEntity[]) {
const numberOfCopiedItems = newItems ? newItems.length : ''; const numberOfCopiedItems = newItems ? newItems.length : 0;
const failedItems = this.selection.length - numberOfCopiedItems;
let i18nMessageString = 'APP.MESSAGES.ERRORS.GENERIC'; let i18nMessageString = 'APP.MESSAGES.ERRORS.GENERIC';
if (typeof info === 'string') { if (typeof info === 'string') {
if (info.toLowerCase().indexOf('succes') !== -1) { if (info.toLowerCase().indexOf('succes') !== -1) {
let i18MessageSuffix;
if (failedItems) {
if (numberOfCopiedItems) {
i18MessageSuffix = ( numberOfCopiedItems === 1 ) ? 'PARTIAL_SINGULAR' : 'PARTIAL_PLURAL';
} else {
i18MessageSuffix = ( failedItems === 1 ) ? 'FAIL_SINGULAR' : 'FAIL_PLURAL';
}
} else {
i18MessageSuffix = ( numberOfCopiedItems === 1 ) ? 'SINGULAR' : 'PLURAL';
}
const i18MessageSuffix = ( numberOfCopiedItems === 1 ) ? 'SINGULAR' : 'PLURAL';
i18nMessageString = `APP.MESSAGES.INFO.NODE_COPY.${i18MessageSuffix}`; i18nMessageString = `APP.MESSAGES.INFO.NODE_COPY.${i18MessageSuffix}`;
} }
@@ -86,7 +99,7 @@ export class NodeCopyDirective {
const undo = (numberOfCopiedItems > 0) ? 'Undo' : ''; const undo = (numberOfCopiedItems > 0) ? 'Undo' : '';
const withUndo = (numberOfCopiedItems > 0) ? '_WITH_UNDO' : ''; const withUndo = (numberOfCopiedItems > 0) ? '_WITH_UNDO' : '';
this.translation.get(i18nMessageString, { number: numberOfCopiedItems }).subscribe(message => { this.translation.get(i18nMessageString, { success: numberOfCopiedItems, failed: failedItems }).subscribe(message => {
this.notification.openSnackMessageAction(message, undo, NodeActionsService[`SNACK_MESSAGE_DURATION${withUndo}`]) this.notification.openSnackMessageAction(message, undo, NodeActionsService[`SNACK_MESSAGE_DURATION${withUndo}`])
.onAction() .onAction()
.subscribe(() => this.deleteCopy(newItems)); .subscribe(() => this.deleteCopy(newItems));

View File

@@ -369,8 +369,8 @@ describe('NodeActionsService', () => {
spyOnSuccess.calls.reset(); spyOnSuccess.calls.reset();
spyOnError.calls.reset(); spyOnError.calls.reset();
copyObservable.toPromise().then( copyObservable.toPromise().then(
() => { (response) => {
spyOnSuccess(); spyOnSuccess(response);
}, },
() => { () => {
spyOnError(); spyOnError();
@@ -382,8 +382,9 @@ describe('NodeActionsService', () => {
{ targetParentId: folderDestination.entry.id, name: undefined } { targetParentId: folderDestination.entry.id, name: undefined }
); );
}).then(() => { }).then(() => {
expect(spyOnSuccess.calls.count()).toEqual(0); expect(spyOnSuccess.calls.count()).toEqual(1);
expect(spyOnError.calls.count()).toEqual(1); expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
expect(spyOnError.calls.count()).toEqual(0);
}); });
})); }));
@@ -401,16 +402,16 @@ describe('NodeActionsService', () => {
spyOnError.calls.reset(); spyOnError.calls.reset();
copyObservable.toPromise() copyObservable.toPromise()
.then( .then(
() => { (response) => {
spyOnSuccess(); spyOnSuccess(response);
}, },
() => { () => {
spyOnError(); spyOnError();
}) })
.then( .then(
() => { () => {
expect(spyOnSuccess).not.toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
expect(spyOnError).toHaveBeenCalled(); expect(spyOnError).not.toHaveBeenCalled();
expect(spyContentAction).toHaveBeenCalled(); expect(spyContentAction).toHaveBeenCalled();
expect(spyFolderAction).not.toHaveBeenCalled(); expect(spyFolderAction).not.toHaveBeenCalled();
@@ -694,7 +695,7 @@ describe('NodeActionsService', () => {
}); });
})); }));
it('should throw permission error in case it occurs', async(() => { it('should not throw permission error, to be able to show message in case of partial move of files', async(() => {
spyOnDocumentListServiceAction = spyOn(documentListService, 'moveNode').and spyOnDocumentListServiceAction = spyOn(documentListService, 'moveNode').and
.returnValue(Observable.throw(permissionError)); .returnValue(Observable.throw(permissionError));
@@ -711,8 +712,8 @@ describe('NodeActionsService', () => {
.then(() => { .then(() => {
expect(spyOnDocumentListServiceAction).toHaveBeenCalled(); expect(spyOnDocumentListServiceAction).toHaveBeenCalled();
expect(spyOnSuccess).not.toHaveBeenCalledWith(permissionError); expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
expect(spyOnError).toHaveBeenCalledWith(permissionError); expect(spyOnError).not.toHaveBeenCalledWith(permissionError);
}); });
})); }));
@@ -750,15 +751,15 @@ describe('NodeActionsService', () => {
spyOnError.calls.reset(); spyOnError.calls.reset();
}); });
it('should throw permission error in case it occurs on folder move', async(() => { it('should not throw permission error in case it occurs on folder move', async(() => {
spyOnDocumentListServiceAction = spyOn(documentListService, 'moveNode').and spyOnDocumentListServiceAction = spyOn(documentListService, 'moveNode').and
.returnValue(Observable.throw(permissionError)); .returnValue(Observable.throw(permissionError));
const moveFolderActionObservable = service.moveFolderAction(folderToMove.entry, folderDestinationId); const moveFolderActionObservable = service.moveFolderAction(folderToMove.entry, folderDestinationId);
moveFolderActionObservable.toPromise() moveFolderActionObservable.toPromise()
.then( .then(
() => { (value) => {
spyOnSuccess(); spyOnSuccess(value);
}, },
(error) => { (error) => {
spyOnError(error); spyOnError(error);
@@ -766,8 +767,8 @@ describe('NodeActionsService', () => {
.then(() => { .then(() => {
expect(spyOnDocumentListServiceAction).toHaveBeenCalled(); expect(spyOnDocumentListServiceAction).toHaveBeenCalled();
expect(spyOnSuccess).not.toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
expect(spyOnError).toHaveBeenCalledWith(permissionError); expect(spyOnError).not.toHaveBeenCalled();
}); });
})); }));

View File

@@ -103,11 +103,11 @@ export class NodeActionsService {
(newContent) => { (newContent) => {
observable.next(`OPERATION.SUCCES.${type.toUpperCase()}.${action.toUpperCase()}`); observable.next(`OPERATION.SUCCES.${type.toUpperCase()}.${action.toUpperCase()}`);
const processedData = this.processResponse(newContent);
if (action === 'copy') { if (action === 'copy') {
this.contentCopied.next(newContent); this.contentCopied.next(processedData.succeeded);
} else if (action === 'move') { } else if (action === 'move') {
const processedData = this.processResponse(newContent);
this.contentMoved.next(processedData); this.contentMoved.next(processedData);
} }
@@ -219,7 +219,8 @@ export class NodeActionsService {
if (errStatusCode && errStatusCode === 409) { if (errStatusCode && errStatusCode === 409) {
return this.copyContentAction(contentEntry, selectionId, this.getNewNameFrom(_oldName, contentEntry.name)); return this.copyContentAction(contentEntry, selectionId, this.getNewNameFrom(_oldName, contentEntry.name));
} else { } else {
return Observable.throw(err || 'Server error'); // do not throw error, to be able to show message in case of partial copy of files
return Observable.of(err || 'Server error');
} }
}); });
} }
@@ -268,7 +269,8 @@ export class NodeActionsService {
}); });
} else { } else {
return Observable.throw(err || 'Server error'); // do not throw error, to be able to show message in case of partial copy of files
return Observable.of(err || 'Server error');
} }
}); });
} }
@@ -367,7 +369,8 @@ export class NodeActionsService {
return Observable.zip(...batch); return Observable.zip(...batch);
}); });
} else { } else {
return Observable.throw(err); // do not throw error, to be able to show message in case of partial move of files
return Observable.of(err);
} }
}); });
} }
@@ -382,19 +385,8 @@ export class NodeActionsService {
return { itemMoved, initialParentId }; return { itemMoved, initialParentId };
}) })
.catch((err) => { .catch((err) => {
let errStatusCode;
try {
const {error: {statusCode}} = JSON.parse(err.message);
errStatusCode = statusCode;
} catch (e) { //
}
if (errStatusCode && errStatusCode === 409) {
// do not throw error, to be able to show message in case of partial move of files // do not throw error, to be able to show message in case of partial move of files
return Observable.of(err); return Observable.of(err);
} else {
return Observable.throw(err);
}
}); });
} }
@@ -413,7 +405,7 @@ export class NodeActionsService {
} }
}, },
(err) => { (err) => {
return Observable.throw(err || 'Server error'); return Observable.of(err || 'Server error');
}); });
return matchedNodes; return matchedNodes;
} }

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "{{ success }} Elemente gelöscht, {{ failed }} konnte(n) nicht gelöscht werden" "PARTIAL_PLURAL": "{{ success }} Elemente gelöscht, {{ failed }} konnte(n) nicht gelöscht werden"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "{{ number }} Element kopiert.", "SINGULAR": "{{ success }} Element kopiert.",
"PLURAL": "{{ number }} Elemente kopiert." "PLURAL": "{{ success }} Elemente kopiert."
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "{{ success }} Element verschoben.", "SINGULAR": "{{ success }} Element verschoben.",

View File

@@ -205,8 +205,12 @@
"PARTIAL_PLURAL": "Deleted {{ success }} items, {{ failed }} couldn't be deleted" "PARTIAL_PLURAL": "Deleted {{ success }} items, {{ failed }} couldn't be deleted"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "Copied {{ number }} item", "SINGULAR": "Copied {{ success }} item",
"PLURAL": "Copied {{ number }} items" "PLURAL": "Copied {{ success }} items",
"PARTIAL_SINGULAR": "Copied {{ success }} item, {{ failed }} couldn't be copied.",
"PARTIAL_PLURAL": "Copied {{ success }} items, {{ failed }} couldn't be copied.",
"FAIL_SINGULAR": "{{ failed }} item couldn't be copied.",
"FAIL_PLURAL": "{{ failed }} items couldn't be copied."
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "Moved {{ success }} item.", "SINGULAR": "Moved {{ success }} item.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "Se han eliminado {{ success }} elementos, {{ failed }} no se han podido eliminar" "PARTIAL_PLURAL": "Se han eliminado {{ success }} elementos, {{ failed }} no se han podido eliminar"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "Se ha copiado {{ number }} elemento", "SINGULAR": "Se ha copiado {{ success }} elemento",
"PLURAL": "Se han copiado {{ number }} elementos" "PLURAL": "Se han copiado {{ success }} elementos"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "Se ha movido {{ success }} elemento.", "SINGULAR": "Se ha movido {{ success }} elemento.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "{{ success }} éléments supprimés, {{ failed }} n'a/n'ont pas pu être supprimé(s)" "PARTIAL_PLURAL": "{{ success }} éléments supprimés, {{ failed }} n'a/n'ont pas pu être supprimé(s)"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "{{ number }} élément copié", "SINGULAR": "{{ success }} élément copié",
"PLURAL": "{{ number }} éléments copiés" "PLURAL": "{{ success }} éléments copiés"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "{{ success }} élément déplacé.", "SINGULAR": "{{ success }} élément déplacé.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "Elementi {{ success }} eliminati, impossibile eliminare {{ failed }}" "PARTIAL_PLURAL": "Elementi {{ success }} eliminati, impossibile eliminare {{ failed }}"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "Copiato {{ number }} elemento", "SINGULAR": "Copiato {{ success }} elemento",
"PLURAL": "Copiati {{ number }} elementi" "PLURAL": "Copiati {{ success }} elementi"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "Spostato {{ success }} elemento.", "SINGULAR": "Spostato {{ success }} elemento.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "{{ success }} 件のアイテムを削除しましたが、{{ failed }} 件は削除できませんでした" "PARTIAL_PLURAL": "{{ success }} 件のアイテムを削除しましたが、{{ failed }} 件は削除できませんでした"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "{{ number }} 件のアイテムをコピーしました", "SINGULAR": "{{ success }} 件のアイテムをコピーしました",
"PLURAL": "{{ number }} 件のアイテムをコピーしました" "PLURAL": "{{ success }} 件のアイテムをコピーしました"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "{{ success }} 件のアイテムを移動しました。", "SINGULAR": "{{ success }} 件のアイテムを移動しました。",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "Slettet {{ success }} elementer, {{ failed }} kunne ikke slettes" "PARTIAL_PLURAL": "Slettet {{ success }} elementer, {{ failed }} kunne ikke slettes"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "Kopierte {{ number }} element", "SINGULAR": "Kopierte {{ success }} element",
"PLURAL": "Kopierte {{ number }} elementer" "PLURAL": "Kopierte {{ success }} elementer"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "Flyttet {{ success }} element.", "SINGULAR": "Flyttet {{ success }} element.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "{{ success }} items verwijderd, kan {{ failed }} niet verwijderen" "PARTIAL_PLURAL": "{{ success }} items verwijderd, kan {{ failed }} niet verwijderen"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "{{ number }} item gekopieerd", "SINGULAR": "{{ success }} item gekopieerd",
"PLURAL": "{{ number }} items gekopieerd" "PLURAL": "{{ success }} items gekopieerd"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "{{ success }} item verplaatst.", "SINGULAR": "{{ success }} item verplaatst.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "Itens {{ success }} excluídos, não foi possível excluir {{ failed }}" "PARTIAL_PLURAL": "Itens {{ success }} excluídos, não foi possível excluir {{ failed }}"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "Item {{ number }} copiado", "SINGULAR": "Item {{ success }} copiado",
"PLURAL": "Itens {{ number }} copiados" "PLURAL": "Itens {{ success }} copiados"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "Item {{ success }} movido.", "SINGULAR": "Item {{ success }} movido.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "Удалено элементов: {{ success }}, не удалось удалить: {{ failed }}" "PARTIAL_PLURAL": "Удалено элементов: {{ success }}, не удалось удалить: {{ failed }}"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "Скопирован {{ number }} элемент", "SINGULAR": "Скопирован {{ success }} элемент",
"PLURAL": "Скопировано элементов: {{ number }}" "PLURAL": "Скопировано элементов: {{ success }}"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "Перемещен {{ success }} элемент.", "SINGULAR": "Перемещен {{ success }} элемент.",

View File

@@ -184,8 +184,8 @@
"PARTIAL_PLURAL": "已删除 {{ success }} 项目,{{ failed }} 无法删除" "PARTIAL_PLURAL": "已删除 {{ success }} 项目,{{ failed }} 无法删除"
}, },
"NODE_COPY": { "NODE_COPY": {
"SINGULAR": "已复制 {{ number }} 个项目", "SINGULAR": "已复制 {{ success }} 个项目",
"PLURAL": "已复制 {{ number }} 个项目" "PLURAL": "已复制 {{ success }} 个项目"
}, },
"NODE_MOVE": { "NODE_MOVE": {
"SINGULAR": "已移动 {{ success }} 项目。", "SINGULAR": "已移动 {{ success }} 项目。",