mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
* [ACS-5540] changes for edit aspect button * added aspect edit button * [ACS-5540]fixed unit test cases and added unit test cases * [ACS-5540] Modified changes * [ACS-5540] fixed file lock issue * [ACS-5645]Implemented changes as per review comments * [ACS-5540]Modified the test case title * [ACS-5645] changes for aspect icon * [ACS-5645] fixed aspect lock issue in small screen * [ACS-5540] modified the aspect button changes * [ACS-5540] modified the changes * [ACS-5645] added unit test cases * [ACS-5540] removed unwanted code * [ACS-5540] fixed lock-file bug * [ACS-5540] revert the unwanted changes * [ACS-5540] modified changes * [ACS-5540]Implemented the changes as per the review comments * [ACS-5540] added group lock changes * [ACS-5540] added tooltip * [ACS-5540] Implemented the review comments * [ACS-5540] added tooltips * [ACS-5540] Added styles * [ACS-5540]Added focus * [ACS-5551]updated property panel design * [ACS-5551]added null checks * [ACS-5551] update style * [ACS-5540] changes for edit aspect button * added aspect edit button * [ACS-5540]fixed unit test cases and added unit test cases * [ACS-5540] Modified changes * [ACS-5645]Implemented changes as per review comments * [ACS-5645] changes for aspect icon * [ACS-5540] modified the aspect button changes * [ACS-5540] modified the changes * [ACS-5540] revert the unwanted changes * [ACS-5540] added group lock changes * [ACS-5551]updated property panel design * [ACS-5551]added null checks * [ACS-5551] update style * [ACS-5551] name updated * [ACS-5551] unit test fix * [ACS-5551] header issue fixed * [ACS-5645] style updated * [ACS-5645] border updated * [ACS-6117] fixed aspect dispaly issue * [ACS-5645] different node open issu fixed * [ACS-5645] unit test issue fix * [ACS-5645] unit test fix * [ACS-5645] tabs design modify * [ACS-5645] dependency updated * [link-adf:ACS-564 5-property-panel-feature] test linking * "[link-adf:ACS-5645-property-panel-feature]" * [ACS-5645] revert adf linking changes * add adf configs to libs * fix issue with empty paths * try using adf target * [link-adf:ACS-5645-property-panel-feature] fix core mapping * [link-adf:ACS-5645-property-panel-feature] revert target changes * remove useless styles * remove css hacks * cleanup useless properties * remove useless properties * remove useless code * [ACS-5645] added missing code * [ACS-5654] add icon for full screen * [ACS-5654] nodei con methods moved to thumbnail * [ACS-5654] unit test added and code refactor * [ACS-5645] unit test added * [ACS-5645] panel issue fix * [ACS-5645] removed unit test for editable property * [ACS-5645] removed unused unit test * [ACS-5645] unit test updated * [ACS-5645] updated the unit test * Modified the unit test cases for getNodeIcon * Upsteam ADF-6.6.0-7287333895, Js-api-7.5.0-7287333895 version * Fix failing test cases * Fix failing e2e --------- Co-authored-by: Yasa-Nataliya <yasa.nataliya@globallogic.com> Co-authored-by: pkundu <priyanka.kundu@hyland.com> Co-authored-by: Denys Vuika <denys.vuika@gmail.com> Co-authored-by: rbahirsheth <raviraj.bahirsheth@globallogic.com>
1232 lines
44 KiB
TypeScript
1232 lines
44 KiB
TypeScript
/*!
|
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
|
*
|
|
* Alfresco Example Content Application
|
|
*
|
|
* This file is part of the Alfresco Example Content Application.
|
|
* If the software was purchased under a paid Alfresco license, the terms of
|
|
* the paid license agreement will prevail. Otherwise, the software is
|
|
* provided under the following open source license terms:
|
|
*
|
|
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import { TestBed } from '@angular/core/testing';
|
|
import { MatDialog, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
|
import { of, throwError, Subject, Observable } from 'rxjs';
|
|
import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
|
|
import { DocumentListService, NodeAction } from '@alfresco/adf-content-services';
|
|
import { NodeActionsService } from './node-actions.service';
|
|
import { Node, NodeChildAssociationEntry, NodeEntry } from '@alfresco/js-api';
|
|
import { AppTestingModule } from '../testing/app-testing.module';
|
|
import { ContentApiService } from '@alfresco/aca-shared';
|
|
|
|
class TestNode {
|
|
entry: Node;
|
|
|
|
constructor(id?: string, isFile?: boolean, name?: string, permission?: string[], nodeType?: string, properties?: any) {
|
|
this.entry = {} as any;
|
|
this.entry.id = id || 'node-id';
|
|
this.entry.isFile = isFile;
|
|
this.entry.isFolder = !isFile;
|
|
this.entry.nodeType = nodeType ? nodeType : isFile ? 'content' : 'folder';
|
|
this.entry.name = name;
|
|
if (permission) {
|
|
this.entry['allowableOperations'] = permission;
|
|
}
|
|
if (properties) {
|
|
this.entry.properties = properties;
|
|
}
|
|
}
|
|
}
|
|
|
|
describe('NodeActionsService', () => {
|
|
const actionIsForbidden = true;
|
|
const isFile = true;
|
|
const folderDestinationId = 'folder-destination-id';
|
|
const fileId = 'file-to-be-copied-id';
|
|
const conflictError = new Error(JSON.stringify({ error: { statusCode: 409 } }));
|
|
const permissionError = new Error(JSON.stringify({ error: { statusCode: 403 } }));
|
|
const badRequestError = new Error(JSON.stringify({ error: { statusCode: 400 } }));
|
|
const emptyChildrenList = { list: { entries: [] } };
|
|
let service: any;
|
|
let apiService: AlfrescoApiService;
|
|
let nodesApi: any;
|
|
let spyOnSuccess: jasmine.Spy;
|
|
let spyOnError: jasmine.Spy;
|
|
let contentApi: ContentApiService;
|
|
let dialog: MatDialog;
|
|
|
|
const helper = {
|
|
fakeCopyNode:
|
|
(isForbidden: boolean = false, nameExistingOnDestination?: string) =>
|
|
(_entryId, options) =>
|
|
new Promise((resolve, reject) => {
|
|
if (isForbidden) {
|
|
reject(permissionError);
|
|
} else if (nameExistingOnDestination && options && options.name === nameExistingOnDestination) {
|
|
reject(conflictError);
|
|
} else {
|
|
resolve('');
|
|
}
|
|
}),
|
|
fakeGetNodeChildren:
|
|
(familyNodes: { parentNodeId: string; nodeChildren: any[] }[], isForbidden: boolean = false) =>
|
|
(parentId) =>
|
|
new Promise((resolve, reject) => {
|
|
if (isForbidden) {
|
|
reject(permissionError);
|
|
} else {
|
|
const node = familyNodes.filter((familyNode) => familyNode.parentNodeId === parentId);
|
|
resolve(node.length > 0 ? { list: { entries: node[0].nodeChildren } } : emptyChildrenList);
|
|
}
|
|
})
|
|
};
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [AppTestingModule, MatDialogModule]
|
|
});
|
|
|
|
spyOnSuccess = jasmine.createSpy('spyOnSuccess');
|
|
spyOnError = jasmine.createSpy('spyOnError');
|
|
|
|
contentApi = TestBed.inject(ContentApiService);
|
|
|
|
service = TestBed.inject(NodeActionsService);
|
|
apiService = TestBed.inject(AlfrescoApiService);
|
|
dialog = TestBed.inject(MatDialog);
|
|
|
|
apiService.reset();
|
|
|
|
nodesApi = service['nodesApi'];
|
|
});
|
|
|
|
describe('ContentNodeSelector configuration', () => {
|
|
it('should validate selection when allowableOperation has `create`', () => {
|
|
spyOn(dialog, 'open').and.returnValue({
|
|
afterClosed: of
|
|
} as MatDialogRef<any>);
|
|
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
|
|
service.getContentNodeSelection(NodeAction.CHOOSE, contentEntities as NodeEntry[]);
|
|
|
|
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
|
|
name: 'some-folder-template',
|
|
isFile: false,
|
|
isFolder: true,
|
|
path: { elements: [{}, {}] },
|
|
allowableOperations: ['create']
|
|
});
|
|
|
|
expect(isSelectionValid).toBe(true);
|
|
});
|
|
|
|
it('should invalidate selection when allowableOperation does not have `create`', () => {
|
|
spyOn(dialog, 'open').and.returnValue({
|
|
afterClosed: of
|
|
} as MatDialogRef<any>);
|
|
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
|
|
service.getContentNodeSelection(NodeAction.CHOOSE, contentEntities as NodeEntry[]);
|
|
|
|
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
|
|
name: 'some-folder-template',
|
|
isFile: false,
|
|
isFolder: true,
|
|
path: { elements: [{}, {}] },
|
|
allowableOperations: ['any']
|
|
});
|
|
|
|
expect(isSelectionValid).toBe(false);
|
|
});
|
|
|
|
it('should invalidate selection if isSite', () => {
|
|
spyOn(dialog, 'open').and.returnValue({
|
|
afterClosed: of
|
|
} as MatDialogRef<any>);
|
|
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
|
|
service.getContentNodeSelection(NodeAction.CHOOSE, contentEntities as NodeEntry[]);
|
|
|
|
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
|
|
name: 'some-folder-template',
|
|
isFile: false,
|
|
isFolder: true,
|
|
path: { elements: [{}, {}] },
|
|
nodeType: 'st:site',
|
|
allowableOperations: ['create']
|
|
});
|
|
|
|
expect(isSelectionValid).toBe(false);
|
|
});
|
|
|
|
it('should validate selection if not a Site', () => {
|
|
spyOn(dialog, 'open').and.returnValue({
|
|
afterClosed: of
|
|
} as MatDialogRef<any>);
|
|
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
|
|
service.getContentNodeSelection(NodeAction.CHOOSE, contentEntities as NodeEntry[]);
|
|
|
|
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
|
|
name: 'some-folder-template',
|
|
isFile: false,
|
|
isFolder: true,
|
|
path: { elements: [{}, {}] },
|
|
nodeType: 'cm:folder',
|
|
allowableOperations: ['create']
|
|
});
|
|
|
|
expect(isSelectionValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('doBatchOperation', () => {
|
|
it('should throw error if "contentEntities" required parameter is missing', (done) => {
|
|
const contentEntities = undefined;
|
|
const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable();
|
|
|
|
doCopyBatchOperation
|
|
.toPromise()
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).not.toHaveBeenCalled();
|
|
expect(spyOnError).toHaveBeenCalled();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should throw error if "contentEntities" is not an array of entry entities', (done) => {
|
|
const contentEntities = [new TestNode(), {}];
|
|
const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable();
|
|
|
|
doCopyBatchOperation
|
|
.toPromise()
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).not.toHaveBeenCalled();
|
|
expect(spyOnError).toHaveBeenCalledWith(badRequestError);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should throw error if an entry in "contentEntities" does not have id nor nodeId property', (done) => {
|
|
const contentEntities = [new TestNode(), { entry: {} }];
|
|
const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable();
|
|
|
|
doCopyBatchOperation
|
|
.toPromise()
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).not.toHaveBeenCalled();
|
|
expect(spyOnError).toHaveBeenCalledWith(badRequestError);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should not throw error if entry in "contentEntities" does not have id, but has nodeId property', () => {
|
|
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
|
|
const subject = new Subject<Node[]>();
|
|
|
|
spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
|
|
spyOn(service, 'copyNodeAction').and.returnValue(of({}));
|
|
|
|
service.copyNodes(contentEntities).subscribe(spyOnSuccess, spyOnError);
|
|
subject.next([new TestNode().entry]);
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalledWith(badRequestError);
|
|
});
|
|
});
|
|
|
|
describe('getEntryParentId', () => {
|
|
it('should return the parentId, if that exists on the node entry', () => {
|
|
const parentID = 'parent-id';
|
|
const entry: any = { nodeId: '1234', parentId: parentID };
|
|
|
|
expect(service.getEntryParentId(entry)).toBe(parentID);
|
|
});
|
|
|
|
it('should give the last element in path property, if parentId is missing and path exists on the node entry', () => {
|
|
const firstParentId = 'parent-0-id';
|
|
const entry: any = {
|
|
nodeId: '1234',
|
|
path: { elements: [{ id: 'parent-1-id' }, { id: firstParentId }] }
|
|
};
|
|
|
|
expect(service.getEntryParentId(entry)).toBe(firstParentId);
|
|
});
|
|
});
|
|
|
|
describe('rowFilter', () => {
|
|
let fileToCopy: TestNode;
|
|
let folderToCopy: TestNode;
|
|
let dialogData: any;
|
|
|
|
beforeEach(() => {
|
|
fileToCopy = new TestNode(fileId, isFile, 'file-name');
|
|
folderToCopy = new TestNode();
|
|
|
|
spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
|
|
|
|
spyOn(dialog, 'open').and.callFake((_contentNodeSelectorComponent: any, data: any) => {
|
|
dialogData = data;
|
|
return { componentInstance: {}, afterClosed: of } as MatDialogRef<any>;
|
|
});
|
|
|
|
service.copyNodes([fileToCopy, folderToCopy]);
|
|
});
|
|
|
|
it('should filter destination nodes and not show files', () => {
|
|
const file = new TestNode('a-file', isFile);
|
|
expect(dialogData.data.rowFilter({ node: file })).toBe(false);
|
|
});
|
|
|
|
it('should filter destination nodes and not show the symlinks', () => {
|
|
const symlinkDestinationFolder = new TestNode('symlink-id', !isFile, 'symlink-name', [], 'app:folderlink');
|
|
expect(
|
|
dialogData.data.rowFilter({
|
|
node: symlinkDestinationFolder
|
|
})
|
|
).toBe(false);
|
|
});
|
|
|
|
it('should filter destination nodes and show folders', () => {
|
|
const destinationFolder = new TestNode(folderDestinationId);
|
|
expect(
|
|
dialogData.data.rowFilter({
|
|
node: destinationFolder
|
|
})
|
|
).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('copyNodes', () => {
|
|
let fileToCopy: TestNode;
|
|
let folderToCopy: TestNode;
|
|
let destinationFolder: TestNode;
|
|
let translationService: TranslationService;
|
|
|
|
beforeEach(() => {
|
|
fileToCopy = new TestNode(fileId, isFile, 'file-name');
|
|
folderToCopy = new TestNode();
|
|
destinationFolder = new TestNode(folderDestinationId);
|
|
translationService = TestBed.inject(TranslationService);
|
|
|
|
spyOn(translationService, 'instant').and.callFake((key) => key);
|
|
});
|
|
|
|
it('should be called', () => {
|
|
const subject = new Subject<Node[]>();
|
|
const spyOnBatchOperation = spyOn(service, 'doBatchOperation').and.callThrough();
|
|
spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
|
|
spyOn(service, 'copyNodeAction').and.returnValue(of({}));
|
|
|
|
service.copyNodes([fileToCopy, folderToCopy]);
|
|
subject.next([destinationFolder.entry]);
|
|
|
|
expect(spyOnBatchOperation.calls.count()).toEqual(1);
|
|
expect(spyOnBatchOperation).toHaveBeenCalledWith(NodeAction.COPY, [fileToCopy, folderToCopy], undefined, undefined);
|
|
});
|
|
|
|
it('should use the custom data object with custom rowFilter & imageResolver & title with destination picker', () => {
|
|
const spyOnBatchOperation = spyOn(service, 'doBatchOperation').and.callThrough();
|
|
const spyOnDestinationPicker = spyOn(service, 'getContentNodeSelection').and.callThrough();
|
|
spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
|
|
|
|
let dialogData = null;
|
|
const spyOnDialog = spyOn(dialog, 'open').and.callFake((_contentNodeSelectorComponent: any, data: any) => {
|
|
dialogData = data;
|
|
return { componentInstance: {}, afterClosed: of } as MatDialogRef<any>;
|
|
});
|
|
|
|
service.copyNodes([fileToCopy, folderToCopy]);
|
|
|
|
expect(spyOnBatchOperation).toHaveBeenCalledWith(NodeAction.COPY, [fileToCopy, folderToCopy], undefined, undefined);
|
|
expect(spyOnDestinationPicker.calls.count()).toEqual(1);
|
|
expect(spyOnDialog.calls.count()).toEqual(1);
|
|
|
|
expect(dialogData).toBeDefined();
|
|
expect(
|
|
dialogData.data.rowFilter({
|
|
node: destinationFolder
|
|
})
|
|
).toBeDefined();
|
|
expect(
|
|
dialogData.data.imageResolver({
|
|
node: destinationFolder
|
|
})
|
|
).toBeDefined();
|
|
expect(dialogData.data.title).toBe('NODE_SELECTOR.COPY_ITEMS');
|
|
expect(translationService.instant).toHaveBeenCalledWith('NODE_SELECTOR.COPY_ITEMS', {
|
|
name: '',
|
|
number: 2
|
|
});
|
|
|
|
destinationFolder.entry['allowableOperations'] = ['update'];
|
|
expect(
|
|
dialogData.data.imageResolver({
|
|
node: destinationFolder
|
|
})
|
|
).toBeDefined();
|
|
});
|
|
|
|
it('should use the ContentNodeSelectorComponentData object with file name in title', () => {
|
|
const spyOnBatchOperation = spyOn(service, 'doBatchOperation').and.callThrough();
|
|
spyOn(service, 'getContentNodeSelection').and.callThrough();
|
|
spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
|
|
|
|
let dialogData: any;
|
|
spyOn(dialog, 'open').and.callFake((_contentNodeSelectorComponent: any, data: any) => {
|
|
dialogData = data;
|
|
return { componentInstance: {}, afterClosed: of } as MatDialogRef<any>;
|
|
});
|
|
|
|
service.copyNodes([{ entry: { id: 'entry-id', name: 'entry-name' } }]);
|
|
|
|
expect(spyOnBatchOperation).toHaveBeenCalled();
|
|
expect(dialogData).toBeDefined();
|
|
expect(dialogData.data.title).toBe('NODE_SELECTOR.COPY_ITEM');
|
|
expect(translationService.instant).toHaveBeenCalledWith('NODE_SELECTOR.COPY_ITEM', {
|
|
name: 'entry-name',
|
|
number: 1
|
|
});
|
|
});
|
|
|
|
it('should use the ContentNodeSelectorComponentData object without file name in title, if no name exists', () => {
|
|
const spyOnBatchOperation = spyOn(service, 'doBatchOperation').and.callThrough();
|
|
spyOn(service, 'getContentNodeSelection').and.callThrough();
|
|
spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
|
|
|
|
let dialogData = null;
|
|
spyOn(dialog, 'open').and.callFake((_contentNodeSelectorComponent: any, data: any) => {
|
|
dialogData = data;
|
|
return { componentInstance: {}, afterClosed: of } as MatDialogRef<any>;
|
|
});
|
|
|
|
service.copyNodes([{ entry: { id: 'entry-id' } }]);
|
|
|
|
expect(spyOnBatchOperation).toHaveBeenCalled();
|
|
expect(dialogData).toBeDefined();
|
|
expect(dialogData.data.title).toBe('NODE_SELECTOR.COPY_ITEMS');
|
|
expect(translationService.instant).toHaveBeenCalledWith('NODE_SELECTOR.COPY_ITEMS', {
|
|
name: '',
|
|
number: 1
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('copyNodeAction', () => {
|
|
it('should copy one folder node to destination', () => {
|
|
spyOn(nodesApi, 'copyNode').and.callFake(helper.fakeCopyNode());
|
|
|
|
const folderToCopy = new TestNode();
|
|
const folderDestination = new TestNode(folderDestinationId);
|
|
service.copyNodeAction(folderToCopy.entry, folderDestination.entry.id);
|
|
|
|
expect(nodesApi.copyNode).toHaveBeenCalledWith(folderToCopy.entry.id, {
|
|
targetParentId: folderDestination.entry.id,
|
|
name: undefined
|
|
});
|
|
});
|
|
|
|
it('should copy one file node to destination', () => {
|
|
spyOn(nodesApi, 'copyNode').and.callFake(helper.fakeCopyNode());
|
|
|
|
const fileToCopy = new TestNode(fileId, isFile, 'file-name');
|
|
const folderDestination = new TestNode(folderDestinationId);
|
|
service.copyNodeAction(fileToCopy.entry, folderDestination.entry.id);
|
|
|
|
expect(nodesApi.copyNode).toHaveBeenCalledWith(fileToCopy.entry.id, {
|
|
targetParentId: folderDestination.entry.id,
|
|
name: 'file-name'
|
|
});
|
|
});
|
|
|
|
it('should fail to copy folder node if action is forbidden', (done) => {
|
|
spyOn(nodesApi, 'copyNode').and.callFake(helper.fakeCopyNode(actionIsForbidden));
|
|
|
|
const folderToCopy = new TestNode();
|
|
const folderDestination = new TestNode(folderDestinationId);
|
|
|
|
const spyContentAction = spyOn(service, 'copyContentAction').and.callThrough();
|
|
const spyFolderAction = spyOn(service, 'copyFolderAction').and.callThrough();
|
|
const copyObservable = service.copyNodeAction(folderToCopy.entry, folderDestination.entry.id);
|
|
|
|
copyObservable
|
|
.toPromise()
|
|
.then(
|
|
(response) => spyOnSuccess(response),
|
|
() => {
|
|
spyOnError();
|
|
|
|
expect(spyContentAction.calls.count()).toEqual(0);
|
|
expect(spyFolderAction.calls.count()).toEqual(1);
|
|
expect(nodesApi.copyNode).toHaveBeenCalledWith(folderToCopy.entry.id, {
|
|
targetParentId: folderDestination.entry.id,
|
|
name: undefined
|
|
});
|
|
}
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess.calls.count()).toEqual(1);
|
|
expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
|
|
expect(spyOnError.calls.count()).toEqual(0);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should fail to copy file node if action is forbidden', (done) => {
|
|
spyOn(nodesApi, 'copyNode').and.callFake(helper.fakeCopyNode(actionIsForbidden));
|
|
|
|
const spyContentAction = spyOn(service, 'copyContentAction').and.callThrough();
|
|
const spyFolderAction = spyOn(service, 'copyFolderAction').and.callThrough();
|
|
|
|
const fileToCopy = new TestNode(fileId, isFile, 'test-name');
|
|
const folderDestination = new TestNode(folderDestinationId);
|
|
const copyObservable = service.copyNodeAction(fileToCopy.entry, folderDestination.entry.id);
|
|
|
|
copyObservable
|
|
.toPromise()
|
|
.then(
|
|
(response) => spyOnSuccess(response),
|
|
() => spyOnError()
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
|
|
expect(spyContentAction).toHaveBeenCalled();
|
|
expect(spyFolderAction).not.toHaveBeenCalled();
|
|
expect(nodesApi.copyNode).toHaveBeenCalledWith(fileToCopy.entry.id, {
|
|
targetParentId: folderDestination.entry.id,
|
|
name: 'test-name'
|
|
});
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should copy one file node to same destination and autoRename it', (done) => {
|
|
spyOn(nodesApi, 'copyNode').and.callFake(helper.fakeCopyNode(!actionIsForbidden, 'file-name'));
|
|
|
|
const spyContentAction = spyOn(service, 'copyContentAction').and.callThrough();
|
|
|
|
const fileToCopy = new TestNode(fileId, isFile, 'file-name');
|
|
const folderDestination = new TestNode(folderDestinationId);
|
|
const copyObservable = service.copyNodeAction(fileToCopy.entry, folderDestination.entry.id);
|
|
|
|
copyObservable
|
|
.toPromise()
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
() => spyOnError()
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
|
|
expect(spyContentAction.calls.count()).toEqual(2);
|
|
expect(nodesApi.copyNode).toHaveBeenCalledWith(fileToCopy.entry.id, {
|
|
targetParentId: folderDestination.entry.id,
|
|
name: 'file-name-1'
|
|
});
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe('should copy content of folder-to-copy to folder with same name from destination folder', () => {
|
|
let folderToCopy: TestNode;
|
|
let fileChildOfFolderToCopy: TestNode;
|
|
let folderParentAndDestination: TestNode;
|
|
let existingFolder: NodeChildAssociationEntry;
|
|
let spy: jasmine.Spy;
|
|
let spyOnContentAction: jasmine.Spy;
|
|
let spyOnFolderAction: jasmine.Spy;
|
|
let copyObservable: Observable<any>;
|
|
let subject: Subject<NodeChildAssociationEntry>;
|
|
|
|
beforeEach(() => {
|
|
subject = new Subject<NodeChildAssociationEntry>();
|
|
folderToCopy = new TestNode('folder-to-copy-id', !isFile, 'conflicting-name');
|
|
fileChildOfFolderToCopy = new TestNode(fileId, isFile, 'file-name');
|
|
|
|
folderParentAndDestination = new TestNode(folderDestinationId);
|
|
existingFolder = new TestNode('existing-folder-id', !isFile, 'conflicting-name') as NodeChildAssociationEntry;
|
|
|
|
spy = spyOn(nodesApi, 'copyNode').and.callFake(helper.fakeCopyNode(!actionIsForbidden, 'conflicting-name'));
|
|
|
|
spyOnContentAction = spyOn(service, 'copyContentAction').and.callThrough();
|
|
spyOnFolderAction = spyOn(service, 'copyFolderAction').and.callThrough();
|
|
|
|
copyObservable = service.copyNodeAction(folderToCopy.entry, folderParentAndDestination.entry.id);
|
|
});
|
|
|
|
it('when folder to copy has a file as content', (done) => {
|
|
const testFamilyNodes = [
|
|
{
|
|
parentNodeId: folderToCopy.entry.id,
|
|
nodeChildren: [fileChildOfFolderToCopy]
|
|
},
|
|
{
|
|
parentNodeId: folderParentAndDestination.entry.id,
|
|
nodeChildren: [existingFolder]
|
|
}
|
|
];
|
|
spyOn(nodesApi, 'listNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
|
|
spyOn(service, 'getChildByName').and.returnValue(of(existingFolder) as any);
|
|
|
|
copyObservable
|
|
.toPromise()
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
() => spyOnError()
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
|
|
expect(spyOnContentAction).toHaveBeenCalled();
|
|
expect(spyOnFolderAction).toHaveBeenCalled();
|
|
expect(spy.calls.allArgs()).toEqual([
|
|
[
|
|
folderToCopy.entry.id,
|
|
{
|
|
targetParentId: folderParentAndDestination.entry.id,
|
|
name: 'conflicting-name'
|
|
}
|
|
],
|
|
[
|
|
fileChildOfFolderToCopy.entry.id,
|
|
{
|
|
targetParentId: existingFolder.entry.id,
|
|
name: 'file-name'
|
|
}
|
|
]
|
|
]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('when folder to copy is empty', (done) => {
|
|
const testFamilyNodes = [
|
|
{
|
|
parentNodeId: folderToCopy.entry.id,
|
|
nodeChildren: []
|
|
},
|
|
{
|
|
parentNodeId: folderParentAndDestination.entry.id,
|
|
nodeChildren: [existingFolder]
|
|
}
|
|
];
|
|
spyOn(nodesApi, 'listNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
|
|
spyOn(service, 'getChildByName').and.returnValue(of({}) as any);
|
|
|
|
copyObservable
|
|
.toPromise()
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
() => spyOnError()
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
|
|
expect(spyOnContentAction).not.toHaveBeenCalled();
|
|
expect(spyOnFolderAction).toHaveBeenCalled();
|
|
expect(spy.calls.allArgs()).toEqual([
|
|
[
|
|
folderToCopy.entry.id,
|
|
{
|
|
targetParentId: folderParentAndDestination.entry.id,
|
|
name: 'conflicting-name'
|
|
}
|
|
]
|
|
]);
|
|
done();
|
|
});
|
|
|
|
subject.next(existingFolder);
|
|
});
|
|
|
|
it('when folder to copy has another folder as child', (done) => {
|
|
const folderChild = new TestNode('folder-child-id');
|
|
const testFamilyNodes = [
|
|
{
|
|
parentNodeId: folderToCopy.entry.id,
|
|
nodeChildren: [folderChild]
|
|
},
|
|
{
|
|
parentNodeId: folderParentAndDestination.entry.id,
|
|
nodeChildren: [existingFolder]
|
|
}
|
|
];
|
|
spyOn(nodesApi, 'listNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
|
|
spyOn(service, 'getChildByName').and.returnValue(of(existingFolder) as any);
|
|
|
|
copyObservable
|
|
.toPromise()
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
() => spyOnError()
|
|
)
|
|
.then(() => {
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
|
|
expect(spyOnContentAction).not.toHaveBeenCalled();
|
|
expect(spyOnFolderAction.calls.count()).toEqual(2);
|
|
expect(spy.calls.allArgs()).toEqual([
|
|
[
|
|
folderToCopy.entry.id,
|
|
{
|
|
targetParentId: folderParentAndDestination.entry.id,
|
|
name: 'conflicting-name'
|
|
}
|
|
],
|
|
[
|
|
folderChild.entry.id,
|
|
{
|
|
targetParentId: existingFolder.entry.id,
|
|
name: undefined
|
|
}
|
|
]
|
|
]);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('moveNodes', () => {
|
|
const permissionToMove = 'delete';
|
|
let fileToMove: TestNode;
|
|
let folderToMove: TestNode;
|
|
let destinationFolder: TestNode;
|
|
let spyOnBatchOperation: jasmine.Spy;
|
|
let documentListService: DocumentListService;
|
|
let subject: Subject<Node[]>;
|
|
|
|
beforeEach(() => {
|
|
subject = new Subject<Node[]>();
|
|
fileToMove = new TestNode('file-to-be-moved', isFile, 'file-name');
|
|
folderToMove = new TestNode('fid', !isFile, 'folder-name');
|
|
destinationFolder = new TestNode(folderDestinationId);
|
|
|
|
documentListService = TestBed.inject(DocumentListService);
|
|
spyOnBatchOperation = spyOn(service, 'doBatchOperation').and.callThrough();
|
|
});
|
|
|
|
it('should allow to select destination for nodes that have permission to be moved', () => {
|
|
const spyOnDestinationPicker = spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
|
|
spyOn(service, 'moveContentAction').and.returnValue(of({}));
|
|
spyOn(service, 'moveFolderAction').and.returnValue(of({}));
|
|
|
|
fileToMove.entry['allowableOperations'] = [permissionToMove];
|
|
folderToMove.entry['allowableOperations'] = [permissionToMove];
|
|
|
|
service.moveNodes([fileToMove, folderToMove], permissionToMove);
|
|
subject.next([destinationFolder.entry]);
|
|
|
|
expect(spyOnBatchOperation).toHaveBeenCalledWith(NodeAction.MOVE, [fileToMove, folderToMove], permissionToMove, undefined);
|
|
expect(spyOnDestinationPicker).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not allow to select destination for nodes that do not have permission to be moved', () => {
|
|
const spyOnDestinationPicker = spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
|
|
|
|
fileToMove.entry['allowableOperations'] = [];
|
|
folderToMove.entry['allowableOperations'] = [];
|
|
|
|
service.moveNodes([fileToMove, folderToMove], permissionToMove);
|
|
subject.next([destinationFolder.entry]);
|
|
|
|
expect(spyOnBatchOperation).toHaveBeenCalledWith(NodeAction.MOVE, [fileToMove, folderToMove], permissionToMove, undefined);
|
|
expect(spyOnDestinationPicker).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should call the documentListService moveNode directly for moving a file that has permission to be moved', () => {
|
|
spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
|
|
fileToMove.entry['allowableOperations'] = [permissionToMove];
|
|
const moveNodeSpy = spyOn(documentListService, 'moveNode').and.returnValue(of(fileToMove));
|
|
spyOn(service, 'moveNodeAction');
|
|
|
|
service.moveNodes([fileToMove], permissionToMove);
|
|
subject.next([destinationFolder.entry]);
|
|
|
|
expect(service.moveNodeAction).not.toHaveBeenCalled();
|
|
expect(moveNodeSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
describe('moveContentAction', () => {
|
|
it('should not throw error on conflict, to be able to show message in case of partial move of files', (done) => {
|
|
const moveNodeSpy = spyOn(documentListService, 'moveNode').and.returnValue(throwError(conflictError));
|
|
|
|
const moveContentActionObservable = service.moveContentAction(fileToMove.entry, folderDestinationId);
|
|
moveContentActionObservable
|
|
.toPromise()
|
|
.then(
|
|
(value) => spyOnSuccess(value),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(moveNodeSpy).toHaveBeenCalled();
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalledWith(conflictError);
|
|
expect(spyOnError).not.toHaveBeenCalledWith(conflictError);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should not throw permission error, to be able to show message in case of partial move of files', (done) => {
|
|
const moveNodeSpy = spyOn(documentListService, 'moveNode').and.returnValue(throwError(permissionError));
|
|
|
|
const moveContentActionObservable = service.moveContentAction(fileToMove.entry, folderDestinationId);
|
|
moveContentActionObservable
|
|
.toPromise()
|
|
.then(
|
|
(value) => spyOnSuccess(value),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(moveNodeSpy).toHaveBeenCalled();
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
|
|
expect(spyOnError).not.toHaveBeenCalledWith(permissionError);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('in case of success, should return also the initial parent id of the moved node', (done) => {
|
|
const parentID = 'parent-id';
|
|
fileToMove.entry['parentId'] = parentID;
|
|
fileToMove.entry['allowableOperations'] = [permissionToMove];
|
|
const moveNodeSpy = spyOn(documentListService, 'moveNode').and.returnValue(of(fileToMove));
|
|
|
|
service
|
|
.moveContentAction(fileToMove.entry, folderDestinationId)
|
|
.toPromise()
|
|
.then(
|
|
(value) => spyOnSuccess(value),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(moveNodeSpy).toHaveBeenCalled();
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalledWith({
|
|
itemMoved: fileToMove,
|
|
initialParentId: parentID
|
|
});
|
|
expect(spyOnError).not.toHaveBeenCalledWith(permissionError);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('moveFolderAction', () => {
|
|
it('should not throw permission error in case it occurs on folder move', (done) => {
|
|
const moveNodeSpy = spyOn(documentListService, 'moveNode').and.returnValue(throwError(permissionError));
|
|
|
|
service
|
|
.moveFolderAction(folderToMove.entry, folderDestinationId)
|
|
.toPromise()
|
|
.then(
|
|
(value) => spyOnSuccess(value),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(moveNodeSpy).toHaveBeenCalled();
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalledWith(permissionError);
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should not throw error on conflict in case it occurs on folder move', () => {
|
|
const newDestination = new TestNode('new-destination', !isFile, folderToMove.entry.name) as NodeChildAssociationEntry;
|
|
spyOn(documentListService, 'moveNode').and.returnValue(throwError(conflictError));
|
|
|
|
const subject$ = new Subject<NodeChildAssociationEntry>();
|
|
spyOn(service, 'getChildByName').and.returnValue(subject$);
|
|
spyOn(nodesApi, 'listNodeChildren').and.returnValue(of(emptyChildrenList));
|
|
|
|
service.moveFolderAction(folderToMove.entry, folderDestinationId).subscribe(spyOnSuccess, spyOnError);
|
|
|
|
subject$.next(newDestination);
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalledWith(conflictError);
|
|
});
|
|
|
|
it('should try to move children nodes of a folder to already existing folder with same name', () => {
|
|
const parentFolderToMove = new TestNode('parent-folder', !isFile, 'conflicting-name');
|
|
const moveNodeSpy = spyOn(documentListService, 'moveNode').and.callFake((nodeId: string) => {
|
|
if (nodeId === parentFolderToMove.entry.id) {
|
|
return throwError(conflictError);
|
|
}
|
|
return of({} as NodeEntry);
|
|
});
|
|
spyOn(service, 'moveContentAction').and.returnValue(of({}));
|
|
|
|
const newDestination = new TestNode('new-destination', !isFile, 'conflicting-name') as NodeChildAssociationEntry;
|
|
const subject$ = new Subject<NodeChildAssociationEntry>();
|
|
spyOn(service, 'getChildByName').and.returnValue(subject$);
|
|
const childrenNodes = [fileToMove, folderToMove];
|
|
spyOn(nodesApi, 'listNodeChildren').and.returnValue(of({ list: { entries: childrenNodes } }));
|
|
|
|
service.moveFolderAction(parentFolderToMove.entry, folderDestinationId).subscribe(spyOnSuccess, spyOnError);
|
|
subject$.next(newDestination);
|
|
|
|
expect(moveNodeSpy).toHaveBeenCalled();
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalledWith(conflictError);
|
|
});
|
|
});
|
|
|
|
describe('moveNodeAction', () => {
|
|
describe('on moving folder to a destination where a folder with the same name exists', () => {
|
|
let parentFolderToMove: TestNode;
|
|
let spyOnDelete: jasmine.Spy;
|
|
let subject$: Subject<NodeChildAssociationEntry>;
|
|
|
|
beforeEach(() => {
|
|
subject$ = new Subject<NodeChildAssociationEntry>();
|
|
parentFolderToMove = new TestNode('parent-folder', !isFile, 'conflicting-name');
|
|
spyOnDelete = spyOn(contentApi, 'deleteNode').and.returnValue(of(null));
|
|
});
|
|
|
|
it('should take no extra delete action, if folder was moved to the same location', (done) => {
|
|
spyOn(service, 'moveFolderAction').and.returnValue(of(null));
|
|
|
|
parentFolderToMove.entry.parentId = folderDestinationId;
|
|
const moveNodeActionPromise = service.moveNodeAction(parentFolderToMove.entry, folderDestinationId).toPromise();
|
|
moveNodeActionPromise
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(spyOnDelete).not.toHaveBeenCalled();
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should take no extra delete action, if its children were partially moved', (done) => {
|
|
const movedChildrenNodes = [fileToMove, folderToMove];
|
|
spyOn(service, 'moveFolderAction').and.returnValue(of(movedChildrenNodes));
|
|
spyOn(service, 'processResponse').and.returnValue({
|
|
succeeded: [fileToMove],
|
|
failed: [folderToMove],
|
|
partiallySucceeded: []
|
|
});
|
|
|
|
parentFolderToMove.entry.parentId = `not-${folderDestinationId}`;
|
|
const moveNodeActionPromise = service.moveNodeAction(parentFolderToMove.entry, folderDestinationId).toPromise();
|
|
moveNodeActionPromise
|
|
.then(
|
|
() => spyOnSuccess(),
|
|
(error) => spyOnError(error)
|
|
)
|
|
.then(() => {
|
|
expect(spyOnDelete).not.toHaveBeenCalled();
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should take extra delete action, if children successfully moved and folder is still on location', () => {
|
|
const movedChildrenNodes = [fileToMove, folderToMove];
|
|
spyOn(service, 'moveFolderAction').and.returnValue(of(movedChildrenNodes));
|
|
spyOn(service, 'processResponse').and.returnValue({
|
|
succeeded: [movedChildrenNodes],
|
|
failed: [],
|
|
partiallySucceeded: []
|
|
});
|
|
const folderOnLocation = parentFolderToMove;
|
|
spyOn(service, 'getChildByName').and.returnValue(subject$);
|
|
|
|
parentFolderToMove.entry.parentId = `not-${folderDestinationId}`;
|
|
service.moveNodeAction(parentFolderToMove.entry, folderDestinationId).subscribe(spyOnSuccess, spyOnError);
|
|
subject$.next(folderOnLocation);
|
|
|
|
expect(spyOnDelete).toHaveBeenCalled();
|
|
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should take no extra delete action, if folder is no longer on location', () => {
|
|
const movedChildrenNodes = [fileToMove, folderToMove];
|
|
|
|
spyOn(service, 'moveFolderAction').and.returnValue(of(movedChildrenNodes));
|
|
spyOn(service, 'processResponse').and.returnValue({
|
|
succeeded: [movedChildrenNodes],
|
|
failed: [],
|
|
partiallySucceeded: []
|
|
});
|
|
spyOn(service, 'getChildByName').and.returnValue(subject$);
|
|
|
|
parentFolderToMove.entry.parentId = `not-${folderDestinationId}`;
|
|
service.moveNodeAction(parentFolderToMove.entry, folderDestinationId).subscribe(spyOnSuccess, spyOnError);
|
|
subject$.next(null);
|
|
|
|
expect(spyOnDelete).not.toHaveBeenCalled();
|
|
expect(spyOnSuccess).toHaveBeenCalled();
|
|
expect(spyOnError).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getChildByName', () => {
|
|
let testFamilyNodes: Array<{ parentNodeId: string; nodeChildren: TestNode[] }>;
|
|
let notChildNode: TestNode;
|
|
let childNode: TestNode;
|
|
|
|
beforeEach(() => {
|
|
childNode = new TestNode(fileId, isFile, 'child-name');
|
|
const parentNode = new TestNode();
|
|
|
|
notChildNode = new TestNode('not-child-id', !isFile, 'not-child-name');
|
|
testFamilyNodes = [
|
|
{
|
|
parentNodeId: parentNode.entry.id,
|
|
nodeChildren: [childNode]
|
|
},
|
|
{
|
|
parentNodeId: notChildNode.entry.id,
|
|
nodeChildren: []
|
|
}
|
|
];
|
|
});
|
|
|
|
it('emits child node with specified name, when it exists in folder', (done) => {
|
|
spyOn(nodesApi, 'listNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
|
|
|
|
service.getChildByName(testFamilyNodes[0].parentNodeId, childNode.entry.name).subscribe((value) => {
|
|
expect(value).toEqual(childNode);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('emits null value when child with specified name is not found in folder', (done) => {
|
|
spyOn(nodesApi, 'listNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
|
|
|
|
service.getChildByName(testFamilyNodes[0].parentNodeId, notChildNode.entry.name).subscribe((value) => {
|
|
expect(value).toEqual(null);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('emits error when permission error occurs', (done) => {
|
|
spyOn(nodesApi, 'listNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes, actionIsForbidden));
|
|
|
|
service.getChildByName(testFamilyNodes[0].parentNodeId, notChildNode.entry.name).subscribe(
|
|
() => {},
|
|
(err) => {
|
|
expect(err.message).toBe('{"error":{"statusCode":403}}');
|
|
done();
|
|
}
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('getNewNameFrom', () => {
|
|
const testData: Array<{ name: string; baseName: string; expected: string }> = [
|
|
{
|
|
name: 'noExtension',
|
|
baseName: 'noExtension',
|
|
expected: 'noExtension-1'
|
|
},
|
|
{
|
|
name: 'withExtension.txt',
|
|
baseName: 'withExtension.txt',
|
|
expected: 'withExtension-1.txt'
|
|
},
|
|
{
|
|
name: 'with-lineStringSuffix.txt',
|
|
baseName: 'with-lineStringSuffix.txt',
|
|
expected: 'with-lineStringSuffix-1.txt'
|
|
},
|
|
{
|
|
name: 'noExtension-1',
|
|
baseName: 'noExtension-1',
|
|
expected: 'noExtension-1-1'
|
|
},
|
|
{
|
|
name: 'with-lineNumberSuffix-1.txt',
|
|
baseName: 'with-lineNumberSuffix-1.txt',
|
|
expected: 'with-lineNumberSuffix-1-1.txt'
|
|
},
|
|
{
|
|
name: 'with-lineNumberSuffix.txt',
|
|
baseName: undefined,
|
|
expected: 'with-lineNumberSuffix-1.txt'
|
|
},
|
|
{
|
|
name: 'noExtension-1',
|
|
baseName: 'noExtension',
|
|
expected: 'noExtension-2'
|
|
},
|
|
{
|
|
name: 'noExtension-7',
|
|
baseName: undefined,
|
|
expected: 'noExtension-8'
|
|
},
|
|
{
|
|
name: 'noExtension-007',
|
|
baseName: undefined,
|
|
expected: 'noExtension-007-1'
|
|
}
|
|
];
|
|
testData.forEach((data) => {
|
|
it(`new name should be \'${data.expected}\' for given name: \'${data.name}\', and baseName: \'${data.baseName}\'`, () => {
|
|
const result = service.getNewNameFrom(data.name, data.baseName);
|
|
expect(result).toBe(data.expected);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('flatten', () => {
|
|
const testNode1 = new TestNode('node1-id', isFile, 'node1-name');
|
|
const testNode2 = new TestNode('node2-id', !isFile, 'node2-name');
|
|
|
|
const testData = [
|
|
{
|
|
nDimArray: [testNode1],
|
|
expected: [testNode1]
|
|
},
|
|
{
|
|
nDimArray: [[testNode1], [testNode2]],
|
|
expected: [testNode1, testNode2]
|
|
},
|
|
{
|
|
nDimArray: [[[[testNode1]], testNode2]],
|
|
expected: [testNode2, testNode1]
|
|
}
|
|
];
|
|
|
|
testData.forEach((data) => {
|
|
it(`flattened array should be \'${data.expected}\' for given data: \'${data.nDimArray}\'`, () => {
|
|
const result = service.flatten(data.nDimArray);
|
|
|
|
expect(result.length).toBe(data.expected.length);
|
|
expect(JSON.stringify(result)).toEqual(JSON.stringify(data.expected));
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('processResponse', () => {
|
|
const testNode1 = new TestNode('node1-id', isFile, 'node1-name');
|
|
const testNode2 = new TestNode('node2-id', !isFile, 'node2-name');
|
|
|
|
const parentID = 'patent-1-id';
|
|
testNode1.entry['parentId'] = parentID;
|
|
|
|
const testData = [
|
|
{
|
|
data: [testNode1],
|
|
expected: {
|
|
succeeded: [testNode1],
|
|
failed: [],
|
|
partiallySucceeded: []
|
|
}
|
|
},
|
|
{
|
|
data: [[{ itemMoved: testNode1, initialParentId: parentID }]],
|
|
expected: {
|
|
succeeded: [[{ itemMoved: testNode1, initialParentId: parentID }]],
|
|
failed: [],
|
|
partiallySucceeded: []
|
|
}
|
|
},
|
|
{
|
|
data: [conflictError],
|
|
expected: {
|
|
succeeded: [],
|
|
failed: [conflictError],
|
|
partiallySucceeded: []
|
|
}
|
|
},
|
|
{
|
|
data: [conflictError, testNode2],
|
|
expected: {
|
|
succeeded: [testNode2],
|
|
failed: [conflictError],
|
|
partiallySucceeded: []
|
|
}
|
|
},
|
|
{
|
|
data: [conflictError, [testNode2, conflictError]],
|
|
expected: {
|
|
succeeded: [],
|
|
failed: [conflictError],
|
|
partiallySucceeded: [[testNode2, conflictError]]
|
|
}
|
|
},
|
|
{
|
|
data: [conflictError, [{}, conflictError]],
|
|
expected: {
|
|
succeeded: [],
|
|
failed: [conflictError, [{}, conflictError]],
|
|
partiallySucceeded: []
|
|
}
|
|
},
|
|
{
|
|
data: {},
|
|
expected: {
|
|
succeeded: [],
|
|
failed: [{}],
|
|
partiallySucceeded: []
|
|
}
|
|
},
|
|
{
|
|
data: testNode1,
|
|
expected: {
|
|
succeeded: [testNode1],
|
|
failed: [],
|
|
partiallySucceeded: []
|
|
}
|
|
},
|
|
{
|
|
data: { itemMoved: testNode1, initialParentId: parentID },
|
|
expected: {
|
|
succeeded: [{ itemMoved: testNode1, initialParentId: parentID }],
|
|
failed: [],
|
|
partiallySucceeded: []
|
|
}
|
|
}
|
|
];
|
|
|
|
testData.forEach((response) => {
|
|
it(`processed response should be \'${response.expected}\' for given input: \'${response.data}\'`, () => {
|
|
const result = service.processResponse(response.data);
|
|
|
|
expect(JSON.stringify(result)).toEqual(JSON.stringify(response.expected));
|
|
});
|
|
});
|
|
});
|
|
});
|