mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
568 lines
19 KiB
TypeScript
568 lines
19 KiB
TypeScript
/*!
|
|
* Copyright © 2005-2024 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 { fakeAsync, TestBed, tick } from '@angular/core/testing';
|
|
import { AppTestingModule } from '../../testing/app-testing.module';
|
|
import { NodeEffects } from './node.effects';
|
|
import { EffectsModule } from '@ngrx/effects';
|
|
import { Store } from '@ngrx/store';
|
|
import { ContentManagementService } from '../../services/content-management.service';
|
|
import {
|
|
CopyNodesAction,
|
|
CreateFolderAction,
|
|
DeleteNodesAction,
|
|
EditFolderAction,
|
|
ExpandInfoDrawerAction,
|
|
FullscreenViewerAction,
|
|
ManageAspectsAction,
|
|
ManagePermissionsAction,
|
|
MoveNodesAction,
|
|
NavigateUrlAction,
|
|
PrintFileAction,
|
|
PurgeDeletedNodesAction,
|
|
RestoreDeletedNodesAction,
|
|
RouterEffects,
|
|
SetCurrentFolderAction,
|
|
SetInfoDrawerStateAction,
|
|
SetSelectedNodesAction,
|
|
ShareNodeAction,
|
|
ShowLoaderAction,
|
|
SnackbarEffects,
|
|
UndoDeleteNodesAction,
|
|
UnlockWriteAction,
|
|
UnshareNodesAction
|
|
} from '@alfresco/aca-shared/store';
|
|
import { RenditionService } from '@alfresco/adf-content-services';
|
|
import { ViewerEffects } from './viewer.effects';
|
|
import { NavigationEnd, Router } from '@angular/router';
|
|
import { of } from 'rxjs';
|
|
import { MatDialogModule } from '@angular/material/dialog';
|
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
|
|
describe('NodeEffects', () => {
|
|
let store: Store<any>;
|
|
let contentService: ContentManagementService;
|
|
let renditionViewerService: RenditionService;
|
|
let viewerEffects: ViewerEffects;
|
|
let router: Router;
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [
|
|
AppTestingModule,
|
|
EffectsModule.forRoot([NodeEffects, ViewerEffects, SnackbarEffects, RouterEffects]),
|
|
MatDialogModule,
|
|
MatSnackBarModule
|
|
],
|
|
providers: [RenditionService]
|
|
});
|
|
|
|
store = TestBed.inject(Store);
|
|
contentService = TestBed.inject(ContentManagementService);
|
|
renditionViewerService = TestBed.inject(RenditionService);
|
|
viewerEffects = TestBed.inject(ViewerEffects);
|
|
router = TestBed.inject(Router);
|
|
});
|
|
|
|
describe('shareNode$', () => {
|
|
it('should share node from payload', () => {
|
|
spyOn(contentService, 'shareNode').and.stub();
|
|
|
|
const node: any = {
|
|
entry: {}
|
|
};
|
|
store.dispatch(new ShareNodeAction(node));
|
|
|
|
expect(contentService.shareNode).toHaveBeenCalledWith(node, undefined);
|
|
});
|
|
|
|
it('should share node from active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'shareNode').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new ShareNodeAction(null));
|
|
expect(contentService.shareNode).toHaveBeenCalledWith(node, undefined);
|
|
}));
|
|
|
|
it('should do nothing if invoking share with no data', () => {
|
|
spyOn(contentService, 'shareNode').and.stub();
|
|
|
|
store.dispatch(new ShareNodeAction(null));
|
|
|
|
expect(contentService.shareNode).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('unshareNodes$', () => {
|
|
it('should unshare nodes from the payload', () => {
|
|
spyOn(contentService, 'unshareNodes').and.stub();
|
|
|
|
const node: any = {};
|
|
store.dispatch(new UnshareNodesAction([node]));
|
|
|
|
expect(contentService.unshareNodes).toHaveBeenCalledWith([node]);
|
|
});
|
|
|
|
it('should unshare nodes from the active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'unshareNodes').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new UnshareNodesAction(null));
|
|
expect(contentService.unshareNodes).toHaveBeenCalledWith([node]);
|
|
}));
|
|
|
|
it('should do nothing if invoking unshare with no data', () => {
|
|
spyOn(contentService, 'unshareNodes').and.stub();
|
|
|
|
store.dispatch(new UnshareNodesAction(null));
|
|
|
|
expect(contentService.unshareNodes).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('purgeDeletedNodes$', () => {
|
|
it('should purge deleted nodes from the payload', () => {
|
|
spyOn(contentService, 'purgeDeletedNodes').and.stub();
|
|
|
|
const node: any = {};
|
|
store.dispatch(new PurgeDeletedNodesAction([node]));
|
|
|
|
expect(contentService.purgeDeletedNodes).toHaveBeenCalledWith([node]);
|
|
});
|
|
|
|
it('should purge nodes from the active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'purgeDeletedNodes').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new PurgeDeletedNodesAction(null));
|
|
expect(contentService.purgeDeletedNodes).toHaveBeenCalledWith([node]);
|
|
}));
|
|
|
|
it('should do nothing if invoking purge with no data', () => {
|
|
spyOn(contentService, 'purgeDeletedNodes').and.stub();
|
|
|
|
store.dispatch(new PurgeDeletedNodesAction(null));
|
|
|
|
expect(contentService.purgeDeletedNodes).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('restoreDeletedNodes$', () => {
|
|
it('should restore deleted nodes from the payload', () => {
|
|
spyOn(contentService, 'restoreDeletedNodes').and.stub();
|
|
|
|
const node: any = {};
|
|
store.dispatch(new RestoreDeletedNodesAction([node]));
|
|
|
|
expect(contentService.restoreDeletedNodes).toHaveBeenCalledWith([node]);
|
|
});
|
|
|
|
it('should restore deleted nodes from the active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'restoreDeletedNodes').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new RestoreDeletedNodesAction(null));
|
|
expect(contentService.restoreDeletedNodes).toHaveBeenCalledWith([node]);
|
|
}));
|
|
|
|
it('should do nothing if invoking restore with no data', () => {
|
|
spyOn(contentService, 'restoreDeletedNodes').and.stub();
|
|
|
|
store.dispatch(new RestoreDeletedNodesAction(null));
|
|
|
|
expect(contentService.restoreDeletedNodes).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('deleteNodes$', () => {
|
|
it('should delete nodes from the payload', () => {
|
|
spyOn(contentService, 'deleteNodes').and.stub();
|
|
spyOn(store, 'dispatch').and.callThrough();
|
|
const node: any = {};
|
|
store.dispatch(new DeleteNodesAction([node]));
|
|
|
|
expect(store.dispatch).toHaveBeenCalledWith(new DeleteNodesAction([node]));
|
|
expect(store.dispatch).toHaveBeenCalledWith(new ShowLoaderAction(true));
|
|
expect(contentService.deleteNodes).toHaveBeenCalledWith([node]);
|
|
});
|
|
|
|
it('should delete nodes from the active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'deleteNodes').and.stub();
|
|
spyOn(store, 'dispatch').and.callThrough();
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new DeleteNodesAction(null));
|
|
|
|
expect(store.dispatch).toHaveBeenCalledWith(new DeleteNodesAction(null));
|
|
expect(store.dispatch).toHaveBeenCalledWith(new ShowLoaderAction(true));
|
|
expect(contentService.deleteNodes).toHaveBeenCalledWith([node]);
|
|
}));
|
|
|
|
it('should do nothing if invoking delete with no data', () => {
|
|
spyOn(contentService, 'deleteNodes').and.stub();
|
|
spyOn(store, 'dispatch').and.callThrough();
|
|
store.dispatch(new DeleteNodesAction(null));
|
|
|
|
expect(store.dispatch).toHaveBeenCalledWith(new DeleteNodesAction(null));
|
|
expect(store.dispatch).toHaveBeenCalledWith(new ShowLoaderAction(true));
|
|
expect(contentService.deleteNodes).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('undoDeleteNodes$', () => {
|
|
it('should undo deleted nodes from the payload', () => {
|
|
spyOn(contentService, 'undoDeleteNodes').and.stub();
|
|
|
|
const node: any = {};
|
|
store.dispatch(new UndoDeleteNodesAction([node]));
|
|
|
|
expect(contentService.undoDeleteNodes).toHaveBeenCalledWith([node]);
|
|
});
|
|
|
|
it('should do nothing if undoing deletion with no data', () => {
|
|
spyOn(contentService, 'undoDeleteNodes').and.stub();
|
|
|
|
store.dispatch(new UndoDeleteNodesAction([]));
|
|
|
|
expect(contentService.undoDeleteNodes).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('createFolder$', () => {
|
|
beforeEach(() => {
|
|
spyOn(contentService, 'createFolder').and.stub();
|
|
});
|
|
|
|
it('should create folder from the payload', () => {
|
|
const currentFolder = 'folder1';
|
|
store.dispatch(new CreateFolderAction(currentFolder));
|
|
|
|
expect(contentService.createFolder).toHaveBeenCalledWith(currentFolder);
|
|
});
|
|
|
|
it('should create folder in the active selected one', fakeAsync(() => {
|
|
const currentFolder: any = { isFolder: true, id: 'folder1' };
|
|
store.dispatch(new SetCurrentFolderAction(currentFolder));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new CreateFolderAction(null));
|
|
expect(contentService.createFolder).toHaveBeenCalledWith(currentFolder.id);
|
|
}));
|
|
});
|
|
|
|
describe('editFolder$', () => {
|
|
it('should edit folder from the payload', () => {
|
|
spyOn(contentService, 'editFolder').and.stub();
|
|
|
|
const node: any = { entry: { isFolder: true, id: 'folder1' } };
|
|
store.dispatch(new EditFolderAction(node));
|
|
|
|
expect(contentService.editFolder).toHaveBeenCalledWith(node);
|
|
});
|
|
|
|
it('should edit folder from the active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'editFolder').and.stub();
|
|
|
|
const currentFolder: any = {
|
|
entry: { isFolder: true, isFile: false, id: 'folder1' }
|
|
};
|
|
store.dispatch(new SetSelectedNodesAction([currentFolder]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new EditFolderAction(null));
|
|
expect(contentService.editFolder).toHaveBeenCalledWith(currentFolder, undefined);
|
|
}));
|
|
|
|
it('should do nothing if editing folder with no selection and payload', () => {
|
|
spyOn(contentService, 'editFolder').and.stub();
|
|
|
|
store.dispatch(new EditFolderAction(null));
|
|
|
|
expect(contentService.editFolder).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('copyNodes$', () => {
|
|
it('should copy nodes from the payload', () => {
|
|
spyOn(contentService, 'copyNodes').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new CopyNodesAction([node]));
|
|
|
|
expect(contentService.copyNodes).toHaveBeenCalledWith([node]);
|
|
});
|
|
|
|
it('should copy nodes from the active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'copyNodes').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new CopyNodesAction(null));
|
|
|
|
expect(contentService.copyNodes).toHaveBeenCalledWith([node], undefined);
|
|
}));
|
|
|
|
it('should do nothing if invoking copy with no data', () => {
|
|
spyOn(contentService, 'copyNodes').and.stub();
|
|
|
|
store.dispatch(new CopyNodesAction(null));
|
|
|
|
expect(contentService.copyNodes).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('moveNodes$', () => {
|
|
it('should move nodes from the payload', () => {
|
|
spyOn(contentService, 'moveNodes').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new MoveNodesAction([node]));
|
|
|
|
expect(contentService.moveNodes).toHaveBeenCalledWith([node]);
|
|
});
|
|
|
|
it('should move nodes from the active selection', fakeAsync(() => {
|
|
spyOn(contentService, 'moveNodes').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new MoveNodesAction(null));
|
|
|
|
expect(contentService.moveNodes).toHaveBeenCalledWith([node], undefined);
|
|
}));
|
|
|
|
it('should do nothing if invoking move with no data', () => {
|
|
spyOn(contentService, 'moveNodes').and.stub();
|
|
|
|
store.dispatch(new MoveNodesAction(null));
|
|
|
|
expect(contentService.moveNodes).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('managePermissions$', () => {
|
|
it('should manage permissions from the payload', () => {
|
|
spyOn(router, 'navigateByUrl').and.stub();
|
|
const node: any = { entry: { isFile: true, id: 'fileId' } };
|
|
store.dispatch(new ManagePermissionsAction(node));
|
|
|
|
expect(router.navigateByUrl).toHaveBeenCalledWith('personal-files/details/fileId/permissions');
|
|
});
|
|
|
|
it('should manage permissions from the active selection', () => {
|
|
spyOn(store, 'select').and.returnValue(of({ isEmpty: false, last: { entry: { id: 'fileId' } } }));
|
|
spyOn(router, 'navigateByUrl').and.stub();
|
|
store.dispatch(new ManagePermissionsAction(null));
|
|
|
|
expect(router.navigateByUrl).toHaveBeenCalledWith('personal-files/details/fileId/permissions');
|
|
});
|
|
|
|
it('should do nothing if invoking manage permissions with no data', () => {
|
|
spyOn(store, 'select').and.returnValue(of(null));
|
|
spyOn(router, 'navigate').and.stub();
|
|
store.dispatch(new ManagePermissionsAction(null));
|
|
|
|
expect(router.navigate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should call dispatch on store with SetInfoDrawerStateAction when NavigationEnd event occurs', () => {
|
|
spyOn(store, 'dispatch').and.callThrough();
|
|
Object.defineProperty(router, 'events', {
|
|
value: of(new NavigationEnd(1, '', ''))
|
|
});
|
|
|
|
store.dispatch(new ManagePermissionsAction(null));
|
|
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(SetInfoDrawerStateAction));
|
|
expect(store.dispatch).toHaveBeenCalledWith(
|
|
jasmine.objectContaining({
|
|
payload: true
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('printFile$', () => {
|
|
it('it should print node content from payload', () => {
|
|
spyOn(renditionViewerService, 'printFileGeneric').and.stub();
|
|
const node: any = {
|
|
entry: { id: 'node-id', content: { mimeType: 'text/json' } }
|
|
};
|
|
|
|
store.dispatch(new PrintFileAction(node));
|
|
|
|
expect(renditionViewerService.printFileGeneric).toHaveBeenCalledWith('node-id', 'text/json');
|
|
});
|
|
|
|
it('it should print node content from store', fakeAsync(() => {
|
|
spyOn(renditionViewerService, 'printFileGeneric').and.stub();
|
|
const node: any = {
|
|
entry: {
|
|
isFile: true,
|
|
id: 'node-id',
|
|
content: { mimeType: 'text/json' }
|
|
}
|
|
};
|
|
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new PrintFileAction(null));
|
|
|
|
expect(renditionViewerService.printFileGeneric).toHaveBeenCalledWith('node-id', 'text/json');
|
|
}));
|
|
});
|
|
|
|
describe('fullscreenViewer$', () => {
|
|
it('should call fullscreen viewer', () => {
|
|
spyOn(viewerEffects, 'enterFullScreen').and.stub();
|
|
|
|
store.dispatch(new FullscreenViewerAction(null));
|
|
|
|
expect(viewerEffects.enterFullScreen).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('unlockWrite$', () => {
|
|
it('should unlock node from payload', () => {
|
|
spyOn(contentService, 'unlockNode').and.stub();
|
|
const node: any = { entry: { id: 'node-id' } };
|
|
|
|
store.dispatch(new UnlockWriteAction(node));
|
|
|
|
expect(contentService.unlockNode).toHaveBeenCalledWith(node);
|
|
});
|
|
|
|
it('should unlock node from store selection', fakeAsync(() => {
|
|
spyOn(contentService, 'unlockNode').and.stub();
|
|
const node: any = { entry: { isFile: true, id: 'node-id' } };
|
|
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new UnlockWriteAction(null));
|
|
|
|
expect(contentService.unlockNode).toHaveBeenCalledWith(node);
|
|
}));
|
|
});
|
|
|
|
describe('aspectList$', () => {
|
|
it('should call aspect dialog', () => {
|
|
const node: any = { entry: { isFile: true } };
|
|
spyOn(contentService, 'manageAspects').and.stub();
|
|
|
|
store.dispatch(new ManageAspectsAction(node));
|
|
|
|
expect(contentService.manageAspects).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should call aspect dialog from the active file selection', fakeAsync(() => {
|
|
spyOn(contentService, 'manageAspects').and.stub();
|
|
|
|
const node: any = { entry: { isFile: true, id: 'file-node-id' } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new ManageAspectsAction(null));
|
|
|
|
expect(contentService.manageAspects).toHaveBeenCalledWith({ entry: { isFile: true, id: 'file-node-id' } }, undefined);
|
|
}));
|
|
|
|
it('should call aspect dialog from the active folder selection', fakeAsync(() => {
|
|
spyOn(contentService, 'manageAspects').and.stub();
|
|
|
|
const node: any = { entry: { isFile: false, id: 'folder-node-id' } };
|
|
store.dispatch(new SetSelectedNodesAction([node]));
|
|
|
|
tick(100);
|
|
|
|
store.dispatch(new ManageAspectsAction(null));
|
|
|
|
expect(contentService.manageAspects).toHaveBeenCalledWith({ entry: { isFile: false, id: 'folder-node-id' } }, undefined);
|
|
}));
|
|
});
|
|
|
|
describe('expandInfoDrawer$', () => {
|
|
it('should call dispatch on store with SetInfoDrawerStateAction when NavigationEnd event occurs', () => {
|
|
spyOn(store, 'dispatch').and.callThrough();
|
|
Object.defineProperty(router, 'events', {
|
|
value: of(new NavigationEnd(1, '', ''))
|
|
});
|
|
|
|
store.dispatch(new ExpandInfoDrawerAction(undefined));
|
|
expect(store.dispatch).toHaveBeenCalledWith(jasmine.any(SetInfoDrawerStateAction));
|
|
expect(store.dispatch).toHaveBeenCalledWith(
|
|
jasmine.objectContaining({
|
|
payload: true
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should redirect to correct url', () => {
|
|
spyOn(store, 'dispatch').and.callThrough();
|
|
Object.defineProperties(router, {
|
|
events: {
|
|
value: of(new NavigationEnd(1, 'test/(viewer:view/node-id)', ''))
|
|
},
|
|
navigateByUrl: {
|
|
value: jasmine.createSpy('navigateByUrl')
|
|
}
|
|
});
|
|
const node: any = { entry: { isFile: true, id: 'node-id' } };
|
|
|
|
store.dispatch(new ExpandInfoDrawerAction(node));
|
|
expect(store.dispatch).toHaveBeenCalledWith(new NavigateUrlAction('personal-files/details/node-id'));
|
|
});
|
|
});
|
|
});
|