From 0f3f580e24c4e612506f4b75605f6f1f23006082 Mon Sep 17 00:00:00 2001 From: MichalKinas <113341662+MichalKinas@users.noreply.github.com> Date: Wed, 8 May 2024 08:53:30 +0200 Subject: [PATCH] [ACS-6366] Add missing unit tests for app rules (#3831) * [ACS-6366] Aca-shared rules cleanup * [ACS-6366] Add missing unit tests for app rules * [ACS-6366] Move context creation to beforeEach --- .../aca-content/assets/app.extensions.json | 6 +- .../aca-content/src/lib/aca-content.module.ts | 2 - .../aca-shared/rules/src/app.rules.spec.ts | 1598 +++++++++++------ projects/aca-shared/rules/src/app.rules.ts | 36 +- .../aca-shared/rules/src/test-rule-context.ts | 8 +- 5 files changed, 1044 insertions(+), 606 deletions(-) diff --git a/projects/aca-content/assets/app.extensions.json b/projects/aca-content/assets/app.extensions.json index 4d6afba72..c1e9a0fb5 100644 --- a/projects/aca-content/assets/app.extensions.json +++ b/projects/aca-content/assets/app.extensions.json @@ -377,7 +377,7 @@ "type": "separator", "order": 89, "rules": { - "visible": "app.isSearchSupported" + "visible": "app.navigation.isNotSearchResults" } }, { @@ -393,7 +393,7 @@ "click": "SEARCH" }, "rules": { - "visible": "app.isSearchSupported" + "visible": "app.navigation.isNotSearchResults" } }, { @@ -1252,7 +1252,7 @@ "click": "ASPECT_LIST" }, "rules": { - "visible": "editAspects" + "visible": "canEditAspects" } }, { diff --git a/projects/aca-content/src/lib/aca-content.module.ts b/projects/aca-content/src/lib/aca-content.module.ts index 04b333773..47df9abc1 100644 --- a/projects/aca-content/src/lib/aca-content.module.ts +++ b/projects/aca-content/src/lib/aca-content.module.ts @@ -171,7 +171,6 @@ export class ContentServiceExtensionModule { canToggleFavorite: rules.canToggleFavorite, isLibraryManager: rules.isLibraryManager, canEditAspects: rules.canEditAspects, - editAspects: rules.editAspects, canShowExpand: rules.canShowExpand, canInfoPreview: rules.canInfoPreview, showInfoSelectionButton: rules.showInfoSelectionButton, @@ -225,7 +224,6 @@ export class ContentServiceExtensionModule { 'app.isContentServiceEnabled': rules.isContentServiceEnabled, 'app.isUploadSupported': rules.isUploadSupported, 'app.canCreateLibrary': rules.canCreateLibrary, - 'app.isSearchSupported': rules.isSearchSupported, 'app.areTagsEnabled': rules.areTagsEnabled, 'app.areCategoriesEnabled': rules.areCategoriesEnabled }); diff --git a/projects/aca-shared/rules/src/app.rules.spec.ts b/projects/aca-shared/rules/src/app.rules.spec.ts index 9a45840fe..e45da1d52 100644 --- a/projects/aca-shared/rules/src/app.rules.spec.ts +++ b/projects/aca-shared/rules/src/app.rules.spec.ts @@ -25,9 +25,15 @@ import * as app from './app.rules'; import { getFileExtension } from './app.rules'; import { TestRuleContext } from './test-rule-context'; -import { NodeEntry, RepositoryInfo } from '@alfresco/js-api'; +import { NodeEntry, RepositoryInfo, StatusInfo } from '@alfresco/js-api'; describe('app.evaluators', () => { + let context: TestRuleContext; + + beforeEach(() => { + context = createTestContext(); + }); + describe('getFileExtension', () => { it('should return no extension when input is null', () => { expect(getFileExtension(null)).toBe(null); @@ -44,14 +50,12 @@ describe('app.evaluators', () => { describe('canDownloadSelection', () => { it('should return [false] if selection is empty', () => { - const context = new TestRuleContext(); + context.selection.isEmpty = true; - expect(context.selection.isEmpty).toBe(true); expect(app.canDownloadSelection(context)).toBe(false); }); it('should return [false] for the trashcan entries', () => { - const context = new TestRuleContext(); context.selection.isEmpty = false; context.navigation = { url: '/trashcan' }; @@ -59,7 +63,6 @@ describe('app.evaluators', () => { }); it('should allow downloading files', () => { - const context = new TestRuleContext(); context.selection.isEmpty = false; context.selection.nodes = [{ entry: { isFile: true } } as NodeEntry]; @@ -67,7 +70,6 @@ describe('app.evaluators', () => { }); it('should allow downloading folders', () => { - const context = new TestRuleContext(); context.selection.isEmpty = false; context.selection.nodes = [{ entry: { isFolder: true } } as NodeEntry]; @@ -75,7 +77,6 @@ describe('app.evaluators', () => { }); it('should now allow downloading unknown selection', () => { - const context = new TestRuleContext(); context.selection.isEmpty = false; context.selection.nodes = [{ entry: {} } as NodeEntry]; @@ -85,37 +86,19 @@ describe('app.evaluators', () => { describe('isWriteLocked', () => { it('should return [true] if lock type is set', () => { - const context: any = { - selection: { - file: { - entry: { - properties: { - 'cm:lockType': 'WRITE_LOCK' - } - } - } - } - }; + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK' } } } as any; expect(app.isWriteLocked(context)).toBe(true); }); it('should return [false] if lock type is not set', () => { - const context: any = { - selection: { - file: { - entry: { - properties: {} - } - } - } - }; + context.selection.file = { entry: { properties: {} } } as any; expect(app.isWriteLocked(context)).toBe(false); }); it('should return [false] if selection not present', () => { - const context: any = {}; + context = {} as any; expect(app.isWriteLocked(context)).toBe(false); }); @@ -123,21 +106,13 @@ describe('app.evaluators', () => { describe('canShowExpand', () => { it('should return false when isLibraries returns true', () => { - const context: any = { - navigation: { - url: '/libraries' - } - }; + context.navigation.url = '/libraries'; expect(app.canShowExpand(context)).toBe(false); }); it('should return false when isDetails returns true', () => { - const context: any = { - navigation: { - url: '/details' - } - }; + context.navigation.url = '/details'; expect(app.canShowExpand(context)).toBe(false); }); @@ -145,86 +120,33 @@ describe('app.evaluators', () => { describe('hasLockedFiles', () => { it('should return [false] if selection not present', () => { - const context: any = {}; + context = {} as any; expect(app.hasLockedFiles(context)).toBe(false); }); it('should return [false] if nodes not present', () => { - const context: any = { - selection: { - nodes: null - } - }; + context.selection.nodes = null; expect(app.hasLockedFiles(context)).toBe(false); }); it('should return [false] if no files selected', () => { - const context: any = { - selection: { - nodes: [ - { - entry: { - isFile: false - } - }, - { - entry: { - isFile: false - } - } - ] - } - }; + context.selection.nodes = [{ entry: { isFile: false } } as any, { entry: { isFile: false } } as any]; expect(app.hasLockedFiles(context)).toBe(false); }); it('should return [true] when one of files is locked', () => { - const context: any = { - selection: { - nodes: [ - { - entry: { - isFile: true, - isLocked: true - } - }, - { - entry: { - isFile: true, - isLocked: false - } - } - ] - } - }; + context.selection.nodes = [{ entry: { isFile: true, isLocked: true } } as any, { entry: { isFile: true, isLocked: false } } as any]; expect(app.hasLockedFiles(context)).toBe(true); }); it('should return [true] when one of files has readonly lock', () => { - const context: any = { - selection: { - nodes: [ - { - entry: { - isFile: true, - isLocked: false - } - }, - { - entry: { - isFile: true, - isLocked: false, - properties: { - 'cm:lockType': 'READ_ONLY_LOCK' - } - } - } - ] - } - }; + context.selection.nodes = [ + { entry: { isFile: true, isLocked: false } } as any, + { entry: { isFile: true, isLocked: false, properties: { 'cm:lockType': 'READ_ONLY_LOCK' } } } as any + ]; expect(app.hasLockedFiles(context)).toBe(true); }); @@ -232,89 +154,41 @@ describe('app.evaluators', () => { describe('canUpdateSelectedNode', () => { it('should return [false] if selection not preset', () => { - const context: any = {}; + context = {} as any; expect(app.canUpdateSelectedNode(context)).toBe(false); }); it('should return [false] if selection is empty', () => { - const context: any = { - selection: { - isEmpty: true - } - }; + context.selection.isEmpty = true; expect(app.canUpdateSelectedNode(context)).toBe(false); }); it('should return [false] if first selection is not a file', () => { - const context: any = { - permissions: { - check: () => false - }, - selection: { - isEmpty: false, - first: { - entry: { - isFile: false - } - } - } - }; + context.selection.isEmpty = false; + context.selection.first = { entry: { isFile: false } } as any; + context.permissions = { check: () => false }; expect(app.canUpdateSelectedNode(context)).toBe(false); }); it('should return [false] if the file is locked', () => { - const context: any = { - permissions: { - check: () => true - }, - selection: { - isEmpty: false, - nodes: [ - { - entry: { - isFile: true, - isLocked: true - } - } - ], - first: { - entry: { - isFile: true, - isLocked: true - } - } - } - }; + context.selection.isEmpty = false; + context.selection.nodes = [{ entry: { isFile: true, isLocked: true } } as any]; + context.selection.first = { entry: { isFile: true, isLocked: true } } as any; + context.permissions = { check: () => true }; expect(app.canUpdateSelectedNode(context)).toBe(false); }); it('should evaluate allowable operation for the file', () => { - const context: any = { - permissions: { - check: () => true - }, - selection: { - isEmpty: false, - nodes: [ - { - entry: { - isFile: true, - allowableOperationsOnTarget: [] - } - } - ], - first: { - entry: { - isFile: true, - allowableOperationsOnTarget: [] - } - } - } - }; + context.selection.isEmpty = false; + context.selection.nodes = [ + { entry: { isFile: true, allowableOperationsOnTarget: [] } } as any, + { entry: { isFile: true, allowableOperationsOnTarget: [] } } as any + ]; + context.permissions = { check: () => true }; expect(app.canUpdateSelectedNode(context)).toBe(true); }); @@ -322,125 +196,44 @@ describe('app.evaluators', () => { describe('canUploadVersion', () => { it('should return [true] if user has locked it previously', () => { - const context: any = { - navigation: { - url: '/personal-files' - }, - profile: { - id: 'user1' - }, - selection: { - file: { - entry: { - properties: { - 'cm:lockType': 'WRITE_LOCK', - 'cm:lockOwner': { - id: 'user1' - } - } - } - } - } - }; + context.navigation.url = '/personal-files'; + context.profile = { id: 'user1' } as any; + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'user1' } } } } as any; expect(app.canUploadVersion(context)).toBe(true); }); it('should return [false] if other user has locked it previously', () => { - const context: any = { - navigation: { - url: '/personal-files' - }, - profile: { - id: 'user2' - }, - selection: { - file: { - entry: { - properties: { - 'cm:lockType': 'WRITE_LOCK', - 'cm:lockOwner': { - id: 'user1' - } - } - } - } - } - }; + context.navigation.url = '/personal-files'; + context.profile = { id: 'user2' } as any; + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'user1' } } } } as any; expect(app.canUploadVersion(context)).toBe(false); }); it('should check the [update] operation when no write lock present', () => { let checked = false; - const context: any = { - navigation: { - url: '/personal-files' - }, - permissions: { - check: () => (checked = true) - }, - selection: { - file: { - entry: { - isFile: true - } - }, - isEmpty: false, - nodes: [ - { - entry: { - isFile: true - } - } - ], - first: { - entry: { - isFile: true - } - } - } - }; + context.navigation.url = '/personal-files'; + context.selection.isEmpty = false; + context.selection.file = { entry: { isFile: true } } as any; + context.selection.nodes = [{ entry: { isFile: true } } as any]; + context.selection.first = { entry: { isFile: true } } as any; + context.permissions = { check: () => (checked = true) }; expect(app.canUploadVersion(context)).toBe(true); expect(checked).toBe(true); }); it('should return [true] if route is `/favorites`', () => { - const context: any = { - selection: { - file: {} - }, - navigation: { - url: '/favorites' - } - }; - - expect(app.canUploadVersion(context)).toBe(true); - }); - - it('should return [true] if route is `/favorites`', () => { - const context: any = { - selection: { - file: {} - }, - navigation: { - url: '/favorites' - } - }; + context.navigation.url = '/favorites'; + context.selection.file = {} as any; expect(app.canUploadVersion(context)).toBe(true); }); it('should return [true] if route is `/shared`', () => { - const context: any = { - selection: { - file: {} - }, - navigation: { - url: '/shared' - } - }; + context.navigation.url = '/shared'; + context.selection.file = {} as any; expect(app.canUploadVersion(context)).toBe(true); }); @@ -448,76 +241,36 @@ describe('app.evaluators', () => { describe('isShared', () => { it('should return true if route is shared files and single selection', () => { - const context: any = { - selection: { - file: {} - }, - navigation: { - url: '/shared' - } - }; + context.navigation.url = '/shared'; + context.selection.file = {} as any; expect(app.isShared(context)).toBe(true); }); it('should return false if route is shared files and multiple selection', () => { - const context: any = { - selection: { - file: null - }, - navigation: { - url: '/shared' - } - }; + context.navigation.url = '/shared'; + context.selection.file = null; expect(app.isShared(context)).toBe(false); }); it('should return false if route is trashcan route', () => { - const context: any = { - selection: { - file: {} - }, - navigation: { - url: '/trashcan' - } - }; + context.navigation.url = '/trashcan'; + context.selection.file = {} as any; expect(app.isShared(context)).toBe(false); }); it('should return false if selection is not shared', () => { - const context: any = { - selection: { - file: { - entry: { - properties: {} - } - } - }, - navigation: { - url: '/other' - } - }; + context.navigation.url = '/other'; + context.selection.file = { entry: { properties: {} } } as any; expect(app.isShared(context)).toBe(false); }); it('should return true if selection is shared', () => { - const context: any = { - selection: { - file: { - entry: { - properties: { - 'qshare:sharedId': 'some-id' - } - } - } - }, - navigation: { - url: '/other' - } - }; + context.navigation.url = '/other'; + context.selection.file = { entry: { properties: { 'qshare:sharedId': 'some-id' } } } as any; expect(app.isShared(context)).toBe(true); }); @@ -525,17 +278,13 @@ describe('app.evaluators', () => { describe('canShowLogout', () => { it('should return false when `withCredentials` property is true', () => { - const context: any = { - withCredentials: true - }; + context.withCredentials = true; expect(app.canShowLogout(context)).toBe(false); }); it('should return true when `withCredentials` property is false', () => { - const context: any = { - withCredentials: false - }; + context.withCredentials = false; expect(app.canShowLogout(context)).toBe(true); }); @@ -543,45 +292,21 @@ describe('app.evaluators', () => { describe('isLibraryManager', () => { it('should return true when role is SiteManager', () => { - const context: any = { - selection: { - library: { - entry: { - role: 'SiteManager' - } - } - } - }; + context.selection.library = { entry: { role: 'SiteManager' } } as any; expect(app.isLibraryManager(context)).toBe(true); }); it('should return false when role is different than SiteManager and user is not an admin', () => { - const context: any = { - selection: { - library: { - entry: { - role: 'SiteCollaborator' - } - } - }, - profile: { isAdmin: false } - }; + context.selection.library = { entry: { role: 'SiteCollaborator' } } as any; + context.profile = { isAdmin: false } as any; expect(app.isLibraryManager(context)).toBe(false); }); it('should return true if user is an admin no matter what the role is', () => { - const context: any = { - selection: { - library: { - entry: { - role: null - } - } - }, - profile: { isAdmin: true } - }; + context.selection.library = { entry: { role: null } } as any; + context.profile = { isAdmin: true } as any; expect(app.isLibraryManager(context)).toBe(true); }); @@ -593,252 +318,113 @@ describe('app.evaluators', () => { }; it('should return [false] if using SSO', () => { - const context: any = { - appConfig, - auth: { - isOauth: () => true - } - }; + context.appConfig = appConfig as any; + context.auth = { isOauth: () => true }; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if no selection present', () => { - const context: any = { - appConfig, - selection: null - }; + context.appConfig = appConfig as any; + context.selection = null; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if no file selected', () => { - const context: any = { - appConfig, - selection: { - file: null - } - }; + context.appConfig = appConfig as any; + context.selection.file = null; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if selected file has no entry', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: null - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: null }; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if selected file has no properties', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: { - properties: null - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: { properties: null } } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if selected file is locked', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: { - isLocked: true, - properties: {} - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: { isLocked: true, properties: {} } } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if selected file has no extension', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: { - name: 'readme', - isLocked: false, - properties: {} - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: { name: 'readme', isLocked: false, properties: {} } } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if extension is not supported', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: { - name: 'run.exe', - isLocked: false, - properties: {} - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: { name: 'run.exe', isLocked: false, properties: {} } } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if selected file has write lock', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: { - name: 'document.docx', - isLocked: false, - properties: { - 'cm:lockType': 'WRITE_LOCK' - } - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: { name: 'document.docx', isLocked: false, properties: { 'cm:lockType': 'WRITE_LOCK' } } } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if selected file has read-only lock', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: { - name: 'document.docx', - isLocked: false, - properties: { - 'cm:lockType': 'READ_ONLY_LOCK' - } - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: { name: 'document.docx', isLocked: false, properties: { 'cm:lockType': 'READ_ONLY_LOCK' } } } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if current user is not lock owner', () => { - const context: any = { - appConfig, - profile: { - id: 'user1' - }, - selection: { - file: { - entry: { - name: 'document.docx', - isLocked: false, - properties: { - 'cm:lockType': 'READ_ONLY_LOCK', - 'cm:lockOwner': { - id: 'user2' - } - } - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { + entry: { name: 'document.docx', isLocked: false, properties: { 'cm:lockType': 'READ_ONLY_LOCK', 'cm:lockOwner': { id: 'user2' } } } + } as any; + context.profile = { id: 'user1' } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if current user is lock owner', () => { - const context: any = { - appConfig, - profile: { - id: 'user1' - }, - selection: { - file: { - entry: { - name: 'document.docx', - isLocked: false, - properties: { - 'cm:lockType': 'READ_ONLY_LOCK', - 'cm:lockOwner': { - id: 'user1' - } - } - } - } - } - }; + context.appConfig = appConfig as any; + context.selection.file = { + entry: { name: 'document.docx', isLocked: false, properties: { 'cm:lockType': 'READ_ONLY_LOCK', 'cm:lockOwner': { id: 'user1' } } } + } as any; + context.profile = { id: 'user1' } as any; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [false] if permissions check is false', () => { - const context: any = { - appConfig, - selection: { - file: { - entry: { - name: 'document.docx', - isLocked: false, - properties: {} - } - } - }, - permissions: { - check: () => false - } - }; + context.appConfig = appConfig as any; + context.selection.file = { entry: { name: 'document.docx', isLocked: false, properties: {} } } as any; + context.permissions = { check: () => false }; expect(app.canOpenWithOffice(context)).toBeFalsy(); }); it('should return [true] if all checks succeed', () => { - const context: any = { - appConfig: { - get: () => true - }, - selection: { - file: { - entry: { - name: 'document.docx', - isLocked: false, - properties: {} - } - } - }, - permissions: { - check: () => true - } - }; + context.appConfig = { get: () => true } as any; + context.selection.file = { entry: { name: 'document.docx', isLocked: false, properties: {} } } as any; + context.permissions = { check: () => true }; expect(app.canOpenWithOffice(context)).toBeTruthy(); }); }); describe('canEditAspects', () => { - let context: TestRuleContext; - - beforeEach(() => { - context = createTestContext(); - }); - it('should return false for multiselection', () => { context.selection.count = 2; @@ -868,49 +454,7 @@ describe('app.evaluators', () => { }); }); - describe('editAspects', () => { - let context: TestRuleContext; - - beforeEach(() => { - context = createTestContext(); - }); - - it('should return true for multiselection', () => { - context.selection.count = 2; - - expect(app.editAspects(context)).toBe(true); - }); - - it('should return false if user cannot update the selected node', () => { - context.permissions.check = spyOn(context.permissions, 'check').and.returnValue(false); - - expect(app.editAspects(context)).toBe(false); - }); - - it('should return false if the selected node is write locked', () => { - context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK' } } } as NodeEntry; - - expect(app.editAspects(context)).toBe(false); - }); - - it('should return false if the context is trashcan', () => { - context.navigation = { url: '/trashcan' }; - - expect(app.editAspects(context)).toBe(false); - }); - - it('should return true if all conditions are met', () => { - expect(app.editAspects(context)).toBe(true); - }); - }); - describe('canManagePermissions', () => { - let context: TestRuleContext; - - beforeEach(() => { - context = createTestContext(); - }); - it('should return false if user cannot update the selected node', () => { context.permissions.check = spyOn(context.permissions, 'check').and.returnValue(false); @@ -940,11 +484,7 @@ describe('app.evaluators', () => { describe('areTagsEnabled', () => { it('should call context.appConfig.get with correct parameters', () => { - const context: any = { - appConfig: { - get: jasmine.createSpy() - } - }; + context.appConfig = { get: jasmine.createSpy() } as any; app.areTagsEnabled(context); expect(context.appConfig.get).toHaveBeenCalledWith('plugins.tagsEnabled', true); @@ -973,11 +513,7 @@ describe('app.evaluators', () => { describe('areCategoriesEnabled', () => { it('should call context.appConfig.get with correct parameters', () => { - const context: any = { - appConfig: { - get: jasmine.createSpy() - } - }; + context.appConfig = { get: jasmine.createSpy() } as any; app.areCategoriesEnabled(context); expect(context.appConfig.get).toHaveBeenCalledWith('plugins.categoriesEnabled', true); @@ -1003,6 +539,926 @@ describe('app.evaluators', () => { ).toBeFalse(); }); }); + + describe('isContentServiceEnabled', () => { + it('should call context.appConfig.get with correct parameters', () => { + context.appConfig = { get: jasmine.createSpy() } as any; + + app.isContentServiceEnabled(context); + expect(context.appConfig.get).toHaveBeenCalledWith('plugins.contentService'); + }); + + it('should return true if contentService plugin is enabled', () => { + expect( + app.isContentServiceEnabled({ + appConfig: { + get: () => true + } + } as any) + ).toBeTrue(); + expect( + app.isContentServiceEnabled({ + appConfig: { + get: () => 'true' + } + } as any) + ).toBeTrue(); + }); + + it('should return false if contentService plugin is disabled', () => { + expect( + app.isContentServiceEnabled({ + appConfig: { + get: () => false + } + } as any) + ).toBeFalse(); + }); + }); + + describe('canCopyNode', () => { + it('should return false when nothing is selected', () => { + context.selection.isEmpty = true; + expect(app.canCopyNode(context)).toBeFalse(); + }); + + it('should return false when selection exists and user is in trashcan', () => { + context.selection.isEmpty = false; + context.navigation.url = '/trashcan/test'; + expect(app.canCopyNode(context)).toBeFalse(); + }); + + it('should return false when selection exists and user is in library', () => { + context.selection.isEmpty = false; + context.navigation.url = '/test/libraries'; + expect(app.canCopyNode(context)).toBeFalse(); + + context.navigation.url = '/search-libraries/test'; + expect(app.canCopyNode(context)).toBeFalse(); + }); + + it('should return true when selection exists and user is outside library and trashcan', () => { + context.selection.isEmpty = false; + context.navigation.url = '/personal-files'; + expect(app.canCopyNode(context)).toBeTrue(); + }); + }); + + describe('canAddFavorite', () => { + it('should return false when nothing is selected', () => { + context.selection.isEmpty = true; + expect(app.canAddFavorite(context)).toBeFalse(); + }); + + it('should return false when selection exists but user is in trashcan, favorites or library', () => { + context.selection.isEmpty = false; + context.navigation.url = '/trashcan/test'; + expect(app.canAddFavorite(context)).toBeFalse(); + + context.navigation.url = '/favorites/test'; + expect(app.canAddFavorite(context)).toBeFalse(); + + context.navigation.url = '/test/libraries'; + expect(app.canAddFavorite(context)).toBeFalse(); + + context.navigation.url = '/search-libraries/test'; + expect(app.canAddFavorite(context)).toBeFalse(); + }); + + it('should return false when each selected node is already a favorite', () => { + context.selection.isEmpty = false; + context.selection.nodes = [{ entry: { isFavorite: true } as any }, { entry: { isFavorite: true } as any }]; + context.navigation.url = '/personal-files'; + expect(app.canAddFavorite(context)).toBeFalse(); + }); + + it('should return true when some selected nodes are not favorite', () => { + context.selection.isEmpty = false; + context.selection.nodes = [{ entry: { isFavorite: true } as any }, { entry: { isFavorite: false } as any }]; + context.navigation.url = '/personal-files'; + expect(app.canAddFavorite(context)).toBeTrue(); + }); + }); + + describe('canRemoveFavorite', () => { + it('should return false when nothing is selected', () => { + context.selection.isEmpty = true; + expect(app.canRemoveFavorite(context)).toBeFalse(); + }); + + it('should return false when selection exists but user is in trashcan', () => { + context.selection.isEmpty = false; + context.navigation.url = '/trashcan/test'; + expect(app.canRemoveFavorite(context)).toBeFalse(); + }); + + it('should return true when user is in favorites page', () => { + context.selection.isEmpty = false; + context.navigation.url = '/favorites/test'; + expect(app.canRemoveFavorite(context)).toBeTrue(); + }); + + it('should return false when only some selected nodes are favorite', () => { + context.selection.isEmpty = false; + context.selection.nodes = [{ entry: { isFavorite: true } as any }, { entry: { isFavorite: false } as any }]; + context.navigation.url = '/personal-files'; + expect(app.canRemoveFavorite(context)).toBeFalse(); + }); + + it('should return true when each selected node is favorite', () => { + context.selection.isEmpty = false; + context.selection.nodes = [{ entry: { isFavorite: true } as any }, { entry: { isFavorite: true } as any }]; + context.navigation.url = '/personal-files'; + expect(app.canRemoveFavorite(context)).toBeTrue(); + }); + }); + + describe('canShareFile', () => { + beforeEach(() => { + context.repository.status = new StatusInfo(); + context.selection.isEmpty = false; + }); + + it('should return false when nothing is selected', () => { + context.selection.file = null; + expect(app.canShareFile(context)).toBeFalse(); + }); + + it('should return false when selection exists and user is in trashcan', () => { + context.selection.file = {} as any; + context.navigation.url = '/trashcan/test'; + expect(app.canShareFile(context)).toBeFalse(); + }); + + it('should return false when quick share is disabled', () => { + context.selection.file = {} as any; + context.navigation.url = '/personal-files'; + context.repository.status.isQuickShareEnabled = false; + expect(app.canShareFile(context)).toBeFalse(); + }); + + it('should return false when selected file is already shared', () => { + context.selection.file = { entry: { properties: { 'qshare:sharedId': 'some-id' } } as any }; + context.navigation.url = '/personal-files'; + context.repository.status.isQuickShareEnabled = true; + expect(app.canShareFile(context)).toBeFalse(); + }); + + it('should return true when selected file is not already shared', () => { + context.selection.file = {} as any; + context.navigation.url = '/personal-files'; + context.repository.status.isQuickShareEnabled = true; + expect(app.canShareFile(context)).toBeTrue(); + }); + }); + + describe('canToggleJoinLibrary', () => { + beforeEach(() => { + context.profile = {} as any; + }); + + it('should return false when no library is selected', () => { + context.selection.library = null; + expect(app.canToggleJoinLibrary(context)).toBeFalse(); + }); + + it('should return false when selected library is private and user is not admin', () => { + context.selection.library = { entry: { visibility: 'PRIVATE' } } as any; + context.profile.isAdmin = false; + expect(app.canToggleJoinLibrary(context)).toBeFalse(); + }); + + it('should return false when user already has a library role', () => { + context.selection.library = { entry: { role: 'test' } } as any; + context.profile.isAdmin = false; + expect(app.canToggleJoinLibrary(context)).toBeFalse(); + }); + + it('should return true when user has no role in not private library', () => { + context.selection.library = { entry: { visibility: 'PUBLIC' } } as any; + context.profile.isAdmin = false; + expect(app.canToggleJoinLibrary(context)).toBeTrue(); + }); + + it('should return true when user has no role in private library with admin rights', () => { + context.selection.library = { entry: { visibility: 'PRIVATE' } } as any; + context.profile.isAdmin = true; + expect(app.canToggleJoinLibrary(context)).toBeTrue(); + }); + }); + + describe('canEditFolder', () => { + it('should return false when no folder is selected', () => { + context.selection.folder = null; + expect(app.canEditFolder(context)).toBeFalse(); + }); + + it('should return false when user is in trashcan', () => { + context.navigation.url = '/trashcan/test'; + expect(app.canEditFolder(context)).toBeFalse(); + }); + + it('should return true when user is in favorites and has selected folder', () => { + context.navigation.url = '/favorites/test'; + context.selection.folder = {} as any; + expect(app.canEditFolder(context)).toBeTrue(); + }); + + it('should return false when selected folder cannot be updated', () => { + context.navigation.url = '/personal-files'; + context.selection.folder = {} as any; + context.permissions = { check: () => false }; + expect(app.canEditFolder(context)).toBeFalse(); + }); + + it('should return true when selected folder can be updated', () => { + context.navigation.url = '/personal-files'; + context.selection.folder = {} as any; + context.permissions = { check: () => true }; + expect(app.canEditFolder(context)).toBeTrue(); + }); + + it('should verify if user has update permission in the folder', () => { + context.navigation.url = '/personal-files'; + context.selection.folder = { entry: { allowableOperations: ['update'] } } as any; + spyOn(context.permissions, 'check'); + app.canEditFolder(context); + expect(context.permissions.check).toHaveBeenCalledWith(context.selection.folder.entry, ['update']); + }); + }); + + describe('canDeleteSelection', () => { + it('should return false when selection is empty', () => { + context.selection.isEmpty = true; + expect(app.canDeleteSelection(context)).toBeFalse(); + }); + + it('should return false when user is in trashcan, library or search results page', () => { + context.selection.isEmpty = false; + context.navigation.url = '/trashcan/tets'; + expect(app.canDeleteSelection(context)).toBeFalse(); + + context.navigation.url = '/test/libraries'; + expect(app.canDeleteSelection(context)).toBeFalse(); + + context.navigation.url = '/search-libraries/tets'; + expect(app.canDeleteSelection(context)).toBeFalse(); + + context.navigation.url = '/search/tets'; + expect(app.canDeleteSelection(context)).toBeFalse(); + }); + + it('should return false when selection contain locked file', () => { + context.selection.isEmpty = false; + context.navigation.url = '/personal-files'; + context.selection.nodes = [{ entry: { isFile: true, isLocked: true } } as any]; + expect(app.canDeleteSelection(context)).toBeFalse(); + }); + + it('should return true when user is in favorites', () => { + context.selection.isEmpty = false; + context.navigation.url = '/favorites/test'; + context.selection.nodes = []; + expect(app.canDeleteSelection(context)).toBeTrue(); + }); + + it('should return false when permission check fails', () => { + context.selection.isEmpty = false; + context.navigation.url = '/personal-files'; + context.selection.nodes = [{ entry: {} } as any]; + context.permissions = { check: () => false }; + expect(app.canDeleteSelection(context)).toBeFalse(); + }); + + it('should return true when permission requirements are met', () => { + context.selection.isEmpty = false; + context.navigation.url = '/personal-files'; + context.selection.nodes = [{ entry: {} } as any]; + context.permissions = { check: () => true }; + expect(app.canDeleteSelection(context)).toBeTrue(); + }); + + it('should verify if user has delete permissions on node', () => { + context.selection.isEmpty = false; + context.navigation.url = '/personal-files'; + context.selection.nodes = [{ entry: { allowableOperations: ['delete'] } } as any]; + spyOn(context.permissions, 'check'); + app.canDeleteSelection(context); + expect(context.permissions.check).toHaveBeenCalledWith(context.selection.nodes, ['delete']); + }); + }); + + describe('canUnshareNodes', () => { + it('should return false when selection is empty', () => { + context.selection.isEmpty = true; + expect(app.canUnshareNodes(context)).toBeFalse(); + }); + + it('should return false when permission check fails', () => { + context.selection.isEmpty = false; + context.selection.nodes = [{} as any]; + context.permissions = { check: () => false }; + expect(app.canUnshareNodes(context)).toBeFalse(); + }); + + it('should return true when permission requirements are met', () => { + context.selection.isEmpty = false; + context.selection.nodes = [{} as any]; + context.permissions = { check: () => true }; + expect(app.canUnshareNodes(context)).toBeTrue(); + }); + + it('should verify if user have delete permission on selected node', () => { + context.selection.isEmpty = false; + context.selection.nodes = [{ allowableOperationsOnTarget: ['delete'] } as any]; + spyOn(context.permissions, 'check'); + app.canUnshareNodes(context); + expect(context.permissions.check).toHaveBeenCalledWith(context.selection.nodes, ['delete'], { target: 'allowableOperationsOnTarget' }); + }); + }); + + describe('hasSelection', () => { + it('should return false when nothing is selected', () => { + context.selection.isEmpty = true; + expect(app.hasSelection(context)).toBeFalse(); + }); + + it('should return true when something is selected', () => { + context.selection.isEmpty = false; + expect(app.hasSelection(context)).toBeTrue(); + }); + }); + + describe('canCreateFolder', () => { + it('should return false when content service is disabled', () => { + context.appConfig = { get: () => false } as any; + expect(app.canCreateFolder(context)).toBeFalse(); + }); + + it('should return false when user is outside personal files or libraries', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/favorite/test'; + expect(app.canCreateFolder(context)).toBeFalse(); + }); + + it('should return false when current folder does not exist', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = null; + expect(app.canCreateFolder(context)).toBeFalse(); + }); + + it('should return false when permission check fails', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = {} as any; + context.permissions = { check: () => false }; + expect(app.canCreateFolder(context)).toBeFalse(); + }); + + it('should return true when permission requirements are met', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = {} as any; + context.permissions = { check: () => true }; + expect(app.canCreateFolder(context)).toBeTrue(); + }); + + it('should verify is user has create permission on current folder', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = { allowableOperations: ['create'] } as any; + spyOn(context.permissions, 'check'); + app.canCreateFolder(context); + expect(context.permissions.check).toHaveBeenCalledWith(context.navigation.currentFolder, ['create']); + }); + }); + + describe('canCreateLibrary', () => { + it('should return false when content service is disabled', () => { + context.appConfig = { get: () => false } as any; + expect(app.canCreateLibrary(context)).toBeFalse(); + }); + + it('should return false when user is outside libraries', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/favorite/test'; + expect(app.canCreateLibrary(context)).toBeFalse(); + }); + + it('should return true when content service is enabled and user is in libraries', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/test/libraries'; + expect(app.canCreateLibrary(context)).toBeTrue(); + }); + }); + + describe('canUpload', () => { + it('should return false when content service is disabled', () => { + context.appConfig = { get: () => false } as any; + expect(app.canUpload(context)).toBeFalse(); + }); + + it('should return false when user is outside personal files or libraries', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/favorite/test'; + expect(app.canUpload(context)).toBeFalse(); + }); + + it('should return false when current folder does not exist', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = null; + expect(app.canUpload(context)).toBeFalse(); + }); + + it('should return false when permission check fails', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = {} as any; + context.permissions = { check: () => false }; + expect(app.canUpload(context)).toBeFalse(); + }); + + it('should return true when permission requirements are met', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = {} as any; + context.permissions = { check: () => true }; + expect(app.canUpload(context)).toBeTrue(); + }); + + it('should verify if user has create permission on current folder', () => { + context.appConfig = { get: () => true } as any; + context.navigation.url = '/personal-files/test'; + context.navigation.currentFolder = { allowableOperations: ['create'] } as any; + spyOn(context.permissions, 'check'); + app.canCreateFolder(context); + expect(context.permissions.check).toHaveBeenCalledWith(context.navigation.currentFolder, ['create']); + }); + }); + + describe('hasFileSelected', () => { + it('should return false when no file is selected', () => { + context.selection.file = null; + expect(app.hasFileSelected(context)).toBeFalse(); + }); + + it('should return true when file is selected', () => { + context.selection.file = {} as any; + expect(app.hasFileSelected(context)).toBeTrue(); + }); + }); + + describe('hasFolderSelected', () => { + it('should return false when no folder is selected', () => { + context.selection.folder = null; + expect(app.hasFolderSelected(context)).toBeFalse(); + }); + + it('should return true when folder is selected', () => { + context.selection.folder = {} as any; + expect(app.hasFolderSelected(context)).toBeTrue(); + }); + }); + + describe('hasLibrarySelected', () => { + it('should return false when no library is selected', () => { + context.selection.library = null; + expect(app.hasLibrarySelected(context)).toBeFalse(); + }); + + it('should return true when library is selected', () => { + context.selection.library = {} as any; + expect(app.hasLibrarySelected(context)).toBeTrue(); + }); + }); + + describe('isPrivateLibrary', () => { + it('should return false when library is not private', () => { + context.selection.library = { entry: { visibility: 'PUBLIC' } } as any; + expect(app.isPrivateLibrary(context)).toBeFalse(); + }); + + it('should return true when library is private', () => { + context.selection.library = { entry: { visibility: 'PRIVATE' } } as any; + expect(app.isPrivateLibrary(context)).toBeTrue(); + }); + }); + + describe('hasLibraryRole', () => { + it('should return false when library has no role', () => { + context.selection.library = { entry: { role: '' } } as any; + expect(app.hasLibraryRole(context)).toBeFalse(); + }); + + it('should return true when library has a role', () => { + context.selection.library = { entry: { role: 'test' } } as any; + expect(app.hasLibraryRole(context)).toBeTrue(); + }); + }); + + describe('hasNoLibraryRole', () => { + it('should return false when library has a role', () => { + context.selection.library = { entry: { role: 'test' } } as any; + expect(app.hasNoLibraryRole(context)).toBeFalse(); + }); + + it('should return true when library has no role', () => { + context.selection.library = { entry: { role: '' } } as any; + expect(app.hasNoLibraryRole(context)).toBeTrue(); + }); + }); + + describe('isMultiselection', () => { + it('should return false when there is no or single selection', () => { + context.selection.isEmpty = true; + expect(app.isMultiselection(context)).toBeFalse(); + + context.selection.isEmpty = false; + context.selection.count = 1; + expect(app.isMultiselection(context)).toBeFalse(); + }); + + it('should return true when there is multiple selection', () => { + context.selection.isEmpty = false; + context.selection.count = 5; + expect(app.isMultiselection(context)).toBeTrue(); + }); + }); + + describe('canUpdateSelectedFolder', () => { + it('should return false when no folder is selected', () => { + context.selection.folder = null; + expect(app.canUpdateSelectedFolder(context)).toBeFalse(); + }); + + it('should return true when user is in favorites', () => { + context.selection.folder = {} as any; + context.navigation.url = '/favorites/test'; + expect(app.canUpdateSelectedFolder(context)).toBeTrue(); + }); + + it('should return false when permission check fails', () => { + context.selection.folder = {} as any; + context.navigation.url = '/personal-files/test'; + context.permissions = { check: () => false }; + expect(app.canUpdateSelectedFolder(context)).toBeFalse(); + }); + + it('should return true when permission requirements are met', () => { + context.selection.folder = {} as any; + context.navigation.url = '/personal-files/test'; + context.permissions = { check: () => true }; + expect(app.canUpdateSelectedFolder(context)).toBeTrue(); + }); + + it('should verify if user has update permission on selected folder', () => { + context.selection.folder = { entry: {} } as any; + context.navigation.url = '/personal-files/test'; + spyOn(context.permissions, 'check'); + app.canUpdateSelectedFolder(context); + expect(context.permissions.check).toHaveBeenCalledWith(context.selection.folder.entry, ['update']); + }); + }); + + describe('isUserWriteLockOwner', () => { + beforeEach(() => { + context.profile = {} as any; + }); + + it('should return false when there is no lock', () => { + context.selection.file = { entry: { properties: [] } } as any; + expect(app.isUserWriteLockOwner(context)).toBeFalse(); + }); + + it('should return false when user id does not match lock owner id', () => { + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as any; + context.profile.id = 'test1'; + expect(app.isUserWriteLockOwner(context)).toBeFalse(); + }); + + it('should return true when user is the owner of the lock', () => { + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test1' } } } } as any; + context.profile.id = 'test1'; + expect(app.isUserWriteLockOwner(context)).toBeTrue(); + }); + }); + + describe('canLockFile', () => { + it('should return false when file is already locked', () => { + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK' } } } as any; + expect(app.canLockFile(context)).toBeFalse(); + }); + + it('should return false when permission check fails', () => { + context.selection.file = { entry: { properties: {} } } as any; + context.permissions = { check: () => false }; + expect(app.canLockFile(context)).toBeFalse(); + }); + + it('should return true when file has no lock and permission requirements are met', () => { + context.selection.file = { entry: { properties: {} } } as any; + context.permissions = { check: () => true }; + expect(app.canLockFile(context)).toBeTrue(); + }); + }); + + describe('canUnlockFile', () => { + beforeEach(() => { + context.profile = {} as any; + }); + + it('should return false when file has no lock', () => { + context.selection.file = { entry: { properties: [] } } as any; + expect(app.canUnlockFile(context)).toBeFalse(); + }); + + it('should return false when file is locked but user is not the owner of the lock and does not have the delete permission', () => { + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as any; + context.profile.id = 'test1'; + context.permissions = { check: () => false }; + expect(app.canUnlockFile(context)).toBeFalse(); + }); + + it('should return true when file is locked and permission requirements are met', () => { + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as any; + context.profile.id = 'test1'; + context.permissions = { check: () => true }; + expect(app.canUnlockFile(context)).toBeTrue(); + }); + + it('should return true when file is locked and user is the owner of the lock', () => { + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test1' } } } } as any; + context.profile.id = 'test1'; + context.permissions = { check: () => false }; + expect(app.canUnlockFile(context)).toBeTrue(); + }); + + it('should verify if user has delete permission on current file', () => { + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as any; + context.profile.id = 'test1'; + spyOn(context.permissions, 'check'); + app.canUnlockFile(context); + expect(context.permissions.check).toHaveBeenCalledWith(context.selection.file.entry, ['delete']); + }); + }); + + describe('isTrashcanItemSelected', () => { + it('should return false when user is not in trashcan', () => { + context.navigation.url = '/personal-files/test'; + expect(app.isTrashcanItemSelected(context)).toBeFalse(); + }); + + it('should return false when nothing is selected', () => { + context.navigation.url = '/trashcan/test'; + context.selection.isEmpty = true; + expect(app.isTrashcanItemSelected(context)).toBeFalse(); + }); + + it('should return true when user is in trashcan and node is selected', () => { + context.navigation.url = '/trashcan/test'; + context.selection.isEmpty = false; + expect(app.isTrashcanItemSelected(context)).toBeTrue(); + }); + }); + + describe('canViewFile', () => { + it('should return false when user is in trashcan', () => { + context.navigation.url = '/trashcan/test'; + expect(app.canViewFile(context)).toBeFalse(); + }); + + it('should return false when nothing is selected', () => { + context.navigation.url = '/personal-files/test'; + context.selection.file = null; + expect(app.canViewFile(context)).toBeFalse(); + }); + + it('should return true when user is not in trashcan and file is selected', () => { + context.navigation.url = '/personal-files/test'; + context.selection.file = {} as any; + expect(app.canViewFile(context)).toBeTrue(); + }); + }); + + describe('canLeaveLibrary', () => { + it('should return false when no library is selected', () => { + context.selection.library = null; + expect(app.canLeaveLibrary(context)).toBeFalse(); + }); + + it('should return false when user does not have library role', () => { + context.selection.library = { entry: { role: null } } as any; + expect(app.canLeaveLibrary(context)).toBeFalse(); + }); + + it('should return true when user has a library role', () => { + context.selection.library = { entry: { role: 'test' } } as any; + expect(app.canLeaveLibrary(context)).toBeTrue(); + }); + }); + + describe('canToggleSharedLink', () => { + beforeEach(() => { + context.repository.status = new StatusInfo(); + }); + + it('should return false when no file is selected', () => { + context.selection.file = null; + expect(app.canToggleSharedLink(context)).toBeFalse(); + }); + + it('should return false when file is not shared and user cannot share it', () => { + context.selection.file = { entry: { properties: {} } } as any; + context.repository.status.isQuickShareEnabled = false; + expect(app.canToggleSharedLink(context)).toBeFalse(); + }); + + it('should return true when file is already shared', () => { + context.selection.file = { entry: { properties: { 'qshare:sharedId': 'some-id' } } } as any; + context.repository.status.isQuickShareEnabled = false; + expect(app.canToggleSharedLink(context)).toBeTrue(); + }); + + it('should return true when file can be shared', () => { + context.selection.file = { entry: { properties: {} } } as any; + context.repository.status.isQuickShareEnabled = true; + expect(app.canToggleSharedLink(context)).toBeTrue(); + }); + }); + + describe('canShowInfoDrawer', () => { + it('should return false when nothing is selected', () => { + context.selection.isEmpty = true; + expect(app.canShowInfoDrawer(context)).toBeFalse(); + }); + + it('should return false when user is in libraries or trashcan', () => { + context.selection.isEmpty = false; + context.navigation.url = '/trashcan/test'; + expect(app.canShowInfoDrawer(context)).toBeFalse(); + + context.navigation.url = '/test/libraries'; + expect(app.canShowInfoDrawer(context)).toBeFalse(); + }); + + it('should return true when selection exists and user is not in trashcan or libraries', () => { + context.navigation.url = '/personal-files/test'; + context.selection.isEmpty = false; + expect(app.canShowInfoDrawer(context)).toBeTrue(); + }); + }); + + describe('canManageFileVersions', () => { + it('should return false when no file is selected', () => { + context.selection.file = null; + expect(app.canManageFileVersions(context)).toBeFalse(); + }); + + it('should return false when user is in trashcan', () => { + context.selection.file = {} as any; + context.navigation.url = '/trashcan/test'; + expect(app.canManageFileVersions(context)).toBeFalse(); + }); + + it('should return false when locked file is selected', () => { + context.selection.file = {} as any; + context.selection.nodes = [{ entry: { isFile: true, isLocked: true } } as any]; + context.navigation.url = '/personal-files/test'; + expect(app.canManageFileVersions(context)).toBeFalse(); + }); + + it('should return true when non-locked file is selected', () => { + context.selection.file = {} as any; + context.selection.nodes = [{ entry: { isFile: true, isLocked: false } } as any]; + context.navigation.url = '/personal-files/test'; + expect(app.canManageFileVersions(context)).toBeTrue(); + }); + }); + + describe('canToggleEditOffline', () => { + beforeEach(() => { + context.profile = {} as any; + }); + + it('should return false when no file is selected', () => { + context.selection.file = null; + expect(app.canToggleEditOffline(context)).toBeFalse(); + }); + + it('should return false when user is in trashcan', () => { + context.selection.file = {} as any; + context.navigation.url = '/trashcan/test'; + expect(app.canToggleEditOffline(context)).toBeFalse(); + }); + + it('should return false when user cannot lock or unlock files', () => { + context.navigation.url = '/personal-files/test'; + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as any; + context.profile.id = 'test1'; + context.permissions = { check: () => false }; + expect(app.canToggleEditOffline(context)).toBeFalse(); + }); + + it('should return true when user can lock file', () => { + context.navigation.url = '/personal-files/test'; + context.selection.file = {} as any; + context.permissions = { check: () => true }; + expect(app.canToggleEditOffline(context)).toBeTrue(); + }); + + it('should return true when user can unlock file', () => { + context.navigation.url = '/personal-files/test'; + context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test1' } } } } as any; + context.profile.id = 'test1'; + expect(app.canToggleEditOffline(context)).toBeTrue(); + }); + }); + + describe('canInfoPreview', () => { + it('should return false when user is not is search results page', () => { + context.navigation.url = '/trashcan/test'; + expect(app.canInfoPreview(context)).toBeFalse(); + }); + + it('should return false when multiple nodes are selected', () => { + context.navigation.url = '/search/test'; + context.selection.isEmpty = false; + context.selection.count = 5; + expect(app.canInfoPreview(context)).toBeFalse(); + }); + + it('should return false when folder is selected', () => { + context.navigation.url = '/search/test'; + context.selection.isEmpty = false; + context.selection.count = 1; + context.selection.folder = {} as any; + expect(app.canInfoPreview(context)).toBeFalse(); + }); + + it('should return false when user is in preview', () => { + context.navigation.url = '/preview/test'; + context.selection.isEmpty = false; + context.selection.count = 1; + context.selection.folder = null; + expect(app.canInfoPreview(context)).toBeFalse(); + }); + + it('should return true when user is in search results page and single file is selected', () => { + context.navigation.url = '/search/test'; + context.selection.isEmpty = false; + context.selection.count = 1; + context.selection.folder = null; + context.selection.file = {} as any; + expect(app.canInfoPreview(context)).toBeTrue(); + }); + }); + + describe('showInfoSelectionButton', () => { + it('should return false when user is not in search results page', () => { + context.navigation.url = '/trashcan/test'; + expect(app.showInfoSelectionButton(context)).toBeFalse(); + }); + + it('should return false when user is in preview', () => { + context.navigation.url = '/search/preview/test'; + expect(app.showInfoSelectionButton(context)).toBeFalse(); + }); + + it('should return true when user is in search results page and not in preview', () => { + context.navigation.url = '/search/test'; + expect(app.showInfoSelectionButton(context)).toBeTrue(); + }); + }); + + describe('isSmartFolder', () => { + it('should return false when there is no selection', () => { + context.selection.isEmpty = true; + expect(app.isSmartFolder(context)).toBeFalse(); + }); + + it('should return false when selected node is not folder', () => { + context.selection.isEmpty = false; + context.selection.first = { entry: { isFolder: false } } as any; + expect(app.isSmartFolder(context)).toBeFalse(); + }); + + it('should return false when selected folder does not have smart folder aspect', () => { + context.selection.isEmpty = false; + context.selection.first = { entry: { isFolder: true, aspectNames: ['test'] } } as any; + expect(app.isSmartFolder(context)).toBeFalse(); + }); + + it('should return true when selected folder contains one of smart folder aspects', () => { + context.selection.isEmpty = false; + context.selection.first = { entry: { isFolder: true, aspectNames: ['smf:customConfigSmartFolder'] } } as any; + expect(app.isSmartFolder(context)).toBeTrue(); + + context.selection.first = { entry: { isFolder: true, aspectNames: ['smf:systemConfigSmartFolder'] } } as any; + expect(app.isSmartFolder(context)).toBeTrue(); + }); + }); }); function createTestContext(): TestRuleContext { diff --git a/projects/aca-shared/rules/src/app.rules.ts b/projects/aca-shared/rules/src/app.rules.ts index 418a0c639..8ae827273 100644 --- a/projects/aca-shared/rules/src/app.rules.ts +++ b/projects/aca-shared/rules/src/app.rules.ts @@ -93,13 +93,6 @@ export const isContentServiceEnabled = (context: AcaRuleContext): boolean => { return flag === true || flag === 'true'; }; -/** - * Checks if Search is supported for active view - * JSON ref: `app.isSearchSupported` - */ -export const isSearchSupported = (context: RuleContext): boolean => - [navigation.isNotSearchResults(context) /* , !hasSelection(context)*/].every(Boolean); - /** * Checks if upload action is supported for the given context * JSON ref: `app.isUploadSupported` @@ -122,7 +115,7 @@ export const canCopyNode = (context: RuleContext): boolean => * JSON ref: `app.selection.canAddFavorite` */ export function canAddFavorite(context: RuleContext): boolean { - if (!context.selection.isEmpty) { + if (hasSelection(context)) { if (navigation.isFavorites(context) || navigation.isLibraries(context) || navigation.isTrashcan(context)) { return false; } @@ -136,7 +129,7 @@ export function canAddFavorite(context: RuleContext): boolean { * JSON ref: `app.selection.canRemoveFavorite` */ export function canRemoveFavorite(context: RuleContext): boolean { - if (!context.selection.isEmpty && !navigation.isTrashcan(context)) { + if (hasSelection(context) && !navigation.isTrashcan(context)) { if (navigation.isFavorites(context)) { return true; } @@ -177,7 +170,7 @@ export function isShared(context: RuleContext): boolean { return true; } - if (navigation.isNotTrashcan(context) && !context.selection.isEmpty && context.selection.file) { + if (navigation.isNotTrashcan(context) && hasSelection(context) && context.selection.file) { return !!context.selection.file.entry?.properties?.['qshare:sharedId']; } @@ -189,12 +182,7 @@ export function isShared(context: RuleContext): boolean { * JSON ref: `app.selection.canDelete` */ export function canDeleteSelection(context: RuleContext): boolean { - if ( - navigation.isNotTrashcan(context) && - navigation.isNotLibraries(context) && - navigation.isNotSearchResults(context) && - !context.selection.isEmpty - ) { + if (navigation.isNotTrashcan(context) && navigation.isNotLibraries(context) && navigation.isNotSearchResults(context) && hasSelection(context)) { if (hasLockedFiles(context)) { return false; } @@ -225,7 +213,7 @@ export function canDeleteSelection(context: RuleContext): boolean { * JSON ref: `app.selection.canUnshare` */ export function canUnshareNodes(context: RuleContext): boolean { - if (!context.selection.isEmpty) { + if (hasSelection(context)) { return context.permissions.check(context.selection.nodes, ['delete'], { target: 'allowableOperationsOnTarget' }); @@ -276,7 +264,7 @@ export function canUpload(context: AcaRuleContext): boolean { * JSON ref: `app.selection.canDownload` */ export function canDownloadSelection(context: RuleContext): boolean { - if (!context.selection.isEmpty && navigation.isNotTrashcan(context)) { + if (hasSelection(context) && navigation.isNotTrashcan(context)) { return context.selection.nodes.every((node: any) => node.entry && (node.entry.isFile || node.entry.isFolder || !!node.entry.nodeId)); } return false; @@ -328,7 +316,7 @@ export const hasFileSelected = (context: RuleContext): boolean => !!context?.sel * JSON ref: `app.selection.first.canUpdate` */ export function canUpdateSelectedNode(context: RuleContext): boolean { - if (context.selection && !context.selection.isEmpty) { + if (context.selection && hasSelection(context)) { const node = context.selection.first; if (node?.entry.isFile && hasLockedFiles(context)) { @@ -342,7 +330,7 @@ export function canUpdateSelectedNode(context: RuleContext): boolean { export function isMultiselection(context: RuleContext): boolean { let isMultiNodeSelected = false; - if (context.selection && !context.selection.isEmpty) { + if (context.selection && hasSelection(context)) { isMultiNodeSelected = context.selection.count > 1; } return isMultiNodeSelected; @@ -498,14 +486,6 @@ export const canEditAspects = (context: RuleContext): boolean => repository.isMajorVersionAvailable(context, '7') ].every(Boolean); -export const editAspects = (context: RuleContext): boolean => - [ - canUpdateSelectedNode(context), - !isWriteLocked(context), - navigation.isNotTrashcan(context), - repository.isMajorVersionAvailable(context, '7') - ].every(Boolean); - export const canShowExpand = (context: RuleContext): boolean => [!navigation.isLibraries(context), !navigation.isDetails(context)].every(Boolean); /** diff --git a/projects/aca-shared/rules/src/test-rule-context.ts b/projects/aca-shared/rules/src/test-rule-context.ts index b87a0f5b3..456451b33 100644 --- a/projects/aca-shared/rules/src/test-rule-context.ts +++ b/projects/aca-shared/rules/src/test-rule-context.ts @@ -22,15 +22,19 @@ * from Hyland Software. If not, see . */ -import { NavigationState, NodePermissions, ProfileState, RuleContext, RuleEvaluator, SelectionState } from '@alfresco/adf-extensions'; +import { NavigationState, NodePermissions, ProfileState, RuleEvaluator, SelectionState } from '@alfresco/adf-extensions'; import { RepositoryInfo } from '@alfresco/js-api'; +import { AcaRuleContext } from './app.rules'; +import { AppConfigService } from '@alfresco/adf-core'; -export class TestRuleContext implements RuleContext { +export class TestRuleContext implements AcaRuleContext { auth: any; navigation: NavigationState = {}; permissions: NodePermissions; profile: ProfileState; repository: RepositoryInfo; + withCredentials: boolean; + appConfig: AppConfigService; selection: SelectionState = { count: 0,