[ACA-3081] upgrade @types/jasmine to latest (#1425)

* fix @type/jasmine update errors

* bump coverage

* fix linting
This commit is contained in:
Cilibiu Bogdan
2020-04-22 14:38:22 +03:00
committed by GitHub
parent 6147a9a295
commit b84cdcb1cc
20 changed files with 487 additions and 348 deletions

6
package-lock.json generated
View File

@@ -1295,9 +1295,9 @@
"dev": true "dev": true
}, },
"@types/jasmine": { "@types/jasmine": {
"version": "2.5.53", "version": "3.5.10",
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.53.tgz", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.10.tgz",
"integrity": "sha512-2YNL0jXYuN7w07mb1sMZQ6T6zOvGi83v8UbjhBZ8mhvI1VkQ2STU9XOrTFyvWswMyh5rW1evS+e7qltYJvTqPA==", "integrity": "sha512-3F8qpwBAiVc5+HPJeXJpbrl+XjawGmciN5LgiO7Gv1pl1RHtjoMNqZpqEksaPJW05ViKe8snYInRs6xB25Xdew==",
"dev": true "dev": true
}, },
"@types/jasminewd2": { "@types/jasminewd2": {

View File

@@ -80,7 +80,7 @@
"@angular/cli": "^7.3.9", "@angular/cli": "^7.3.9",
"@angular/compiler-cli": "7.2.15", "@angular/compiler-cli": "7.2.15",
"@angular/language-service": "7.2.15", "@angular/language-service": "7.2.15",
"@types/jasmine": "2.5.53", "@types/jasmine": "3.5.10",
"@types/jasminewd2": "^2.0.8", "@types/jasminewd2": "^2.0.8",
"@types/node": "^13.11.0", "@types/node": "^13.11.0",
"@types/selenium-webdriver": "^4.0.9", "@types/selenium-webdriver": "^4.0.9",

View File

@@ -472,7 +472,7 @@ describe('app.evaluators', () => {
withCredentials: false withCredentials: false
}; };
expect(app.canShowLanguagePicker(context)).toBe(true); expect(app.canShowLogout(context)).toBe(true);
}); });
}); });
}); });

View File

@@ -51,7 +51,7 @@ export class ContextMenuService {
}); });
} }
open(config: ContextmenuOverlayConfig) { open(config: ContextmenuOverlayConfig): ContextMenuOverlayRef {
const overlay = this.createOverlay(config); const overlay = this.createOverlay(config);
const overlayRef = new ContextMenuOverlayRef(overlay); const overlayRef = new ContextMenuOverlayRef(overlay);
@@ -60,7 +60,7 @@ export class ContextMenuService {
return overlayRef; return overlayRef;
} }
private createOverlay(config: ContextmenuOverlayConfig) { private createOverlay(config: ContextmenuOverlayConfig): OverlayRef {
const overlayConfig = this.getOverlayConfig(config); const overlayConfig = this.getOverlayConfig(config);
return this.overlay.create(overlayConfig); return this.overlay.create(overlayConfig);
} }
@@ -68,7 +68,7 @@ export class ContextMenuService {
private attachDialogContainer( private attachDialogContainer(
overlay: OverlayRef, overlay: OverlayRef,
contextmenuOverlayRef: ContextMenuOverlayRef contextmenuOverlayRef: ContextMenuOverlayRef
) { ): ContextMenuComponent {
const injector = this.createInjector(contextmenuOverlayRef); const injector = this.createInjector(contextmenuOverlayRef);
const containerPortal = new ComponentPortal( const containerPortal = new ComponentPortal(

View File

@@ -42,6 +42,7 @@ import { EffectsModule } from '@ngrx/effects';
import { RouterEffects } from '@alfresco/aca-shared/store'; import { RouterEffects } from '@alfresco/aca-shared/store';
import { of, throwError } from 'rxjs'; import { of, throwError } from 'rxjs';
import { LibraryEffects } from '../../store/effects'; import { LibraryEffects } from '../../store/effects';
import { NodeEntry } from '@alfresco/js-api';
describe('FavoriteLibrariesComponent', () => { describe('FavoriteLibrariesComponent', () => {
let fixture: ComponentFixture<FavoriteLibrariesComponent>; let fixture: ComponentFixture<FavoriteLibrariesComponent>;
@@ -90,7 +91,7 @@ describe('FavoriteLibrariesComponent', () => {
router = TestBed.get(Router); router = TestBed.get(Router);
spyOn(contentApiService, 'getNode').and.returnValue( spyOn(contentApiService, 'getNode').and.returnValue(
of({ entry: { id: 'libraryId' } }) of({ entry: { id: 'libraryId' } } as NodeEntry)
); );
}); });

View File

@@ -33,7 +33,7 @@ import { Store } from '@ngrx/store';
import { UpdateLibraryAction } from '@alfresco/aca-shared/store'; import { UpdateLibraryAction } from '@alfresco/aca-shared/store';
import { AppTestingModule } from '../../../testing/app-testing.module'; import { AppTestingModule } from '../../../testing/app-testing.module';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Site } from '@alfresco/js-api'; import { Site, SitePaging } from '@alfresco/js-api';
import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core'; import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core';
describe('LibraryMetadataFormComponent', () => { describe('LibraryMetadataFormComponent', () => {
@@ -231,7 +231,7 @@ describe('LibraryMetadataFormComponent', () => {
).and.returnValue( ).and.returnValue(
Promise.resolve({ Promise.resolve({
list: { entries: [{ entry: { title } }] } list: { entries: [{ entry: { title } }] }
}) } as SitePaging)
); );
const siteEntryModel = { const siteEntryModel = {
@@ -262,7 +262,7 @@ describe('LibraryMetadataFormComponent', () => {
).and.returnValue( ).and.returnValue(
Promise.resolve({ Promise.resolve({
list: { entries: [{ entry: { title: 'libraryTitle' } }] } list: { entries: [{ entry: { title: 'libraryTitle' } }] }
}) } as SitePaging)
); );
const siteEntryModel = { const siteEntryModel = {
@@ -293,7 +293,7 @@ describe('LibraryMetadataFormComponent', () => {
).and.returnValue( ).and.returnValue(
Promise.resolve({ Promise.resolve({
list: { entries: [] } list: { entries: [] }
}) } as SitePaging)
); );
const siteEntryModel = { const siteEntryModel = {

View File

@@ -48,6 +48,14 @@ import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '@alfresco/aca-shared'; import { ContentApiService } from '@alfresco/aca-shared';
import { ContentManagementService } from '../../services/content-management.service'; import { ContentManagementService } from '../../services/content-management.service';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import {
Node,
NodePaging,
FavoritePaging,
SharedLinkPaging,
PersonEntry,
ResultSetPaging
} from '@alfresco/js-api';
describe('PreviewComponent', () => { describe('PreviewComponent', () => {
let fixture: ComponentFixture<PreviewComponent>; let fixture: ComponentFixture<PreviewComponent>;
@@ -378,7 +386,7 @@ describe('PreviewComponent', () => {
it('should navigate to original location if node not found', async () => { it('should navigate to original location if node not found', async () => {
spyOn(router, 'navigate').and.stub(); spyOn(router, 'navigate').and.stub();
spyOn(contentApi, 'getNodeInfo').and.returnValue(Promise.reject('error')); spyOn(contentApi, 'getNodeInfo').and.returnValue(throwError('error'));
component.previewLocation = 'personal-files'; component.previewLocation = 'personal-files';
await component.displayNode('folder1'); await component.displayNode('folder1');
@@ -392,7 +400,7 @@ describe('PreviewComponent', () => {
spyOn(contentApi, 'getNodeInfo').and.returnValue( spyOn(contentApi, 'getNodeInfo').and.returnValue(
of({ of({
isFile: false isFile: false
}) } as Node)
); );
component.previewLocation = 'personal-files'; component.previewLocation = 'personal-files';
@@ -419,7 +427,7 @@ describe('PreviewComponent', () => {
spyOn(contentApi, 'getNodeInfo').and.returnValue( spyOn(contentApi, 'getNodeInfo').and.returnValue(
of({ of({
isFile: true isFile: true
}) } as Node)
); );
spyOn(component, 'getNearestNodes').and.returnValue( spyOn(component, 'getNearestNodes').and.returnValue(
Promise.reject('error') Promise.reject('error')
@@ -434,16 +442,18 @@ describe('PreviewComponent', () => {
xit('should setup node for displaying', async () => { xit('should setup node for displaying', async () => {
spyOn(router, 'navigate').and.stub(); spyOn(router, 'navigate').and.stub();
spyOn(component, 'getNearestNodes').and.returnValue({ spyOn(component, 'getNearestNodes').and.returnValue(
Promise.resolve({
left: 'node1', left: 'node1',
right: 'node3' right: 'node3'
}); })
);
spyOn(contentApi, 'getNodeInfo').and.returnValue( spyOn(contentApi, 'getNodeInfo').and.returnValue(
of({ of({
id: 'node2', id: 'node2',
parentId: 'parent1', parentId: 'parent1',
isFile: true isFile: true
}) } as Node)
); );
await component.displayNode('node2'); await component.displayNode('node2');
@@ -466,7 +476,7 @@ describe('PreviewComponent', () => {
{ entry: { id: 'node2', name: 'node 2' } } { entry: { id: 'node2', name: 'node 2' } }
] ]
} }
}) } as NodePaging)
); );
const ids = await component.getFileIds('personal-files', 'folder1'); const ids = await component.getFileIds('personal-files', 'folder1');
@@ -485,7 +495,7 @@ describe('PreviewComponent', () => {
{ entry: { id: 'node2', name: 'node 2' } } { entry: { id: 'node2', name: 'node 2' } }
] ]
} }
}) } as NodePaging)
); );
const ids = await component.getFileIds('personal-files', 'folder1'); const ids = await component.getFileIds('personal-files', 'folder1');
@@ -504,11 +514,11 @@ describe('PreviewComponent', () => {
of({ of({
list: { list: {
entries: [ entries: [
{ entry: { id: 'node1', name: 'node 1', modifiedAt: 1 } }, { entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } },
{ entry: { id: 'node2', name: 'node 2', modifiedAt: 2 } } { entry: { id: 'node2', name: 'node 2', modifiedAt: new Date(2) } }
] ]
} }
}) } as NodePaging)
); );
const ids = await component.getFileIds('personal-files', 'folder1'); const ids = await component.getFileIds('personal-files', 'folder1');
@@ -527,7 +537,7 @@ describe('PreviewComponent', () => {
{ entry: { id: 'node2', name: 'node 2' } } { entry: { id: 'node2', name: 'node 2' } }
] ]
} }
}) } as NodePaging)
); );
const ids = await component.getFileIds('libraries', 'site1'); const ids = await component.getFileIds('libraries', 'site1');
@@ -550,7 +560,7 @@ describe('PreviewComponent', () => {
{ entry: { id: 'node2', name: 'node 2', modifiedAt: new Date(2) } } { entry: { id: 'node2', name: 'node 2', modifiedAt: new Date(2) } }
] ]
} }
}) } as NodePaging)
); );
const ids = await component.getFileIds('libraries', 'folder1'); const ids = await component.getFileIds('libraries', 'folder1');
@@ -570,7 +580,7 @@ describe('PreviewComponent', () => {
{ entry: { target: { file: { id: 'file2', name: 'file 2' } } } } { entry: { target: { file: { id: 'file2', name: 'file 2' } } } }
] ]
} }
}) } as FavoritePaging)
); );
const ids = await component.getFileIds('favorites'); const ids = await component.getFileIds('favorites');
@@ -601,7 +611,7 @@ describe('PreviewComponent', () => {
} }
] ]
} }
}) } as FavoritePaging)
); );
const ids = await component.getFileIds('favorites'); const ids = await component.getFileIds('favorites');
@@ -632,7 +642,7 @@ describe('PreviewComponent', () => {
} }
] ]
} }
}) } as SharedLinkPaging)
); );
const ids = await component.getFileIds('shared'); const ids = await component.getFileIds('shared');
@@ -662,7 +672,7 @@ describe('PreviewComponent', () => {
} }
] ]
} }
}) } as SharedLinkPaging)
); );
const ids = await component.getFileIds('shared'); const ids = await component.getFileIds('shared');
@@ -676,7 +686,7 @@ describe('PreviewComponent', () => {
spyOn(contentApi, 'getPerson').and.returnValue( spyOn(contentApi, 'getPerson').and.returnValue(
of({ of({
entry: { id: 'user' } entry: { id: 'user' }
}) } as PersonEntry)
); );
spyOn(contentApi, 'search').and.returnValue( spyOn(contentApi, 'search').and.returnValue(
@@ -687,7 +697,7 @@ describe('PreviewComponent', () => {
{ entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } } { entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } }
] ]
} }
}) } as ResultSetPaging)
); );
const ids = await component.getFileIds('recent-files'); const ids = await component.getFileIds('recent-files');
@@ -700,7 +710,7 @@ describe('PreviewComponent', () => {
spyOn(contentApi, 'getPerson').and.returnValue( spyOn(contentApi, 'getPerson').and.returnValue(
of({ of({
entry: { id: 'user' } entry: { id: 'user' }
}) } as PersonEntry)
); );
spyOn(contentApi, 'search').and.returnValue( spyOn(contentApi, 'search').and.returnValue(
@@ -711,7 +721,7 @@ describe('PreviewComponent', () => {
{ entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } } { entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } }
] ]
} }
}) } as ResultSetPaging)
); );
const ids = await component.getFileIds('recent-files'); const ids = await component.getFileIds('recent-files');

View File

@@ -41,6 +41,7 @@ import { DocumentListComponent } from '@alfresco/adf-content-services';
import { RecentFilesComponent } from './recent-files.component'; import { RecentFilesComponent } from './recent-files.component';
import { AppTestingModule } from '../../testing/app-testing.module'; import { AppTestingModule } from '../../testing/app-testing.module';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { PersonEntry } from '@alfresco/js-api';
describe('RecentFilesComponent', () => { describe('RecentFilesComponent', () => {
let fixture: ComponentFixture<RecentFilesComponent>; let fixture: ComponentFixture<RecentFilesComponent>;
@@ -90,7 +91,7 @@ describe('RecentFilesComponent', () => {
spyOn(alfrescoApi.peopleApi, 'getPerson').and.returnValue( spyOn(alfrescoApi.peopleApi, 'getPerson').and.returnValue(
Promise.resolve({ Promise.resolve({
entry: { id: 'personId' } entry: { id: 'personId' }
}) } as PersonEntry)
); );
spyOn(alfrescoApi.searchApi, 'search').and.returnValue( spyOn(alfrescoApi.searchApi, 'search').and.returnValue(

View File

@@ -26,12 +26,16 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { AppTestingModule } from '../../../testing/app-testing.module'; import { AppTestingModule } from '../../../testing/app-testing.module';
import { AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApiService } from '@alfresco/adf-core';
import { SearchLibrariesQueryBuilderService } from './search-libraries-query-builder.service'; import {
SearchLibrariesQueryBuilderService,
LibrarySearchQuery
} from './search-libraries-query-builder.service';
describe('SearchLibrariesQueryBuilderService', () => { describe('SearchLibrariesQueryBuilderService', () => {
let apiService: AlfrescoApiService; let apiService: AlfrescoApiService;
let builder: SearchLibrariesQueryBuilderService; let builder: SearchLibrariesQueryBuilderService;
let queriesApi; let queriesApi;
const query = {} as LibrarySearchQuery;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@@ -54,7 +58,6 @@ describe('SearchLibrariesQueryBuilderService', () => {
}); });
it('should build query and raise an event on update', async () => { it('should build query and raise an event on update', async () => {
const query = {};
spyOn(builder, 'buildQuery').and.returnValue(query); spyOn(builder, 'buildQuery').and.returnValue(query);
let eventArgs = null; let eventArgs = null;
@@ -68,7 +71,6 @@ describe('SearchLibrariesQueryBuilderService', () => {
const data = {}; const data = {};
spyOn(queriesApi, 'findSites').and.returnValue(Promise.resolve(data)); spyOn(queriesApi, 'findSites').and.returnValue(Promise.resolve(data));
const query = {};
spyOn(builder, 'buildQuery').and.returnValue(query); spyOn(builder, 'buildQuery').and.returnValue(query);
let eventArgs = null; let eventArgs = null;
@@ -106,7 +108,6 @@ describe('SearchLibrariesQueryBuilderService', () => {
const err = '{"error": {"statusCode": 400}}'; const err = '{"error": {"statusCode": 400}}';
spyOn(queriesApi, 'findSites').and.returnValue(Promise.reject(err)); spyOn(queriesApi, 'findSites').and.returnValue(Promise.reject(err));
const query = {};
spyOn(builder, 'buildQuery').and.returnValue(query); spyOn(builder, 'buildQuery').and.returnValue(query);
let eventArgs = null; let eventArgs = null;

View File

@@ -45,7 +45,7 @@ import {
NavigateToFolder, NavigateToFolder,
SnackbarErrorAction SnackbarErrorAction
} from '@alfresco/aca-shared/store'; } from '@alfresco/aca-shared/store';
import { Pagination } from '@alfresco/js-api'; import { Pagination, SearchRequest } from '@alfresco/js-api';
import { SearchQueryBuilderService } from '@alfresco/adf-content-services'; import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
@@ -58,6 +58,7 @@ describe('SearchComponent', () => {
let alfrescoApi: AlfrescoApiService; let alfrescoApi: AlfrescoApiService;
let translate: TranslationService; let translate: TranslationService;
let router: Router; let router: Router;
const searchRequest = {} as SearchRequest;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@@ -108,7 +109,7 @@ describe('SearchComponent', () => {
}) })
); );
spyOn(queryBuilder, 'buildQuery').and.returnValue({}); spyOn(queryBuilder, 'buildQuery').and.returnValue(searchRequest);
spyOn(store, 'dispatch').and.stub(); spyOn(store, 'dispatch').and.stub();
queryBuilder.execute(); queryBuilder.execute();
@@ -133,7 +134,7 @@ describe('SearchComponent', () => {
}) })
); );
spyOn(queryBuilder, 'buildQuery').and.returnValue({}); spyOn(queryBuilder, 'buildQuery').and.returnValue(searchRequest);
spyOn(store, 'dispatch').and.stub(); spyOn(store, 'dispatch').and.stub();
queryBuilder.execute(); queryBuilder.execute();
@@ -158,7 +159,7 @@ describe('SearchComponent', () => {
}) })
); );
spyOn(queryBuilder, 'buildQuery').and.returnValue({}); spyOn(queryBuilder, 'buildQuery').and.returnValue(searchRequest);
spyOn(store, 'dispatch').and.stub(); spyOn(store, 'dispatch').and.stub();
queryBuilder.execute(); queryBuilder.execute();

View File

@@ -26,7 +26,7 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { AppTestingModule } from '../testing/app-testing.module'; import { AppTestingModule } from '../testing/app-testing.module';
import { AppExtensionService } from './extension.service'; import { AppExtensionService } from './extension.service';
import { Store } from '@ngrx/store'; import { Store, Action } from '@ngrx/store';
import { AppStore } from '@alfresco/aca-shared/store'; import { AppStore } from '@alfresco/aca-shared/store';
import { import {
ContentActionType, ContentActionType,
@@ -37,7 +37,8 @@ import {
reduceEmptyMenus, reduceEmptyMenus,
ExtensionService, ExtensionService,
ExtensionConfig, ExtensionConfig,
ComponentRegisterService ComponentRegisterService,
NavBarGroupRef
} from '@alfresco/adf-extensions'; } from '@alfresco/adf-extensions';
import { AppConfigService } from '@alfresco/adf-core'; import { AppConfigService } from '@alfresco/adf-core';
@@ -155,7 +156,7 @@ describe('AppExtensionService', () => {
expect(store.dispatch).toHaveBeenCalledWith({ expect(store.dispatch).toHaveBeenCalledWith({
type: 'CREATE_FOLDER', type: 'CREATE_FOLDER',
payload: 'folder-name' payload: 'folder-name'
}); } as Action);
}); });
it('should still invoke store if action is missing', () => { it('should still invoke store if action is missing', () => {
@@ -667,6 +668,13 @@ describe('AppExtensionService', () => {
}); });
describe('getApplicationNavigation', () => { describe('getApplicationNavigation', () => {
beforeEach(() => {
extensions.setEvaluators({
notVisible: () => false,
isVisible: () => true
});
});
it('should create navigation data', () => { it('should create navigation data', () => {
const navigation = service.getApplicationNavigation([ const navigation = service.getApplicationNavigation([
{ items: [{ route: 'route1' }, { route: 'route2' }] }, { items: [{ route: 'route1' }, { route: 'route2' }] },
@@ -683,7 +691,7 @@ describe('AppExtensionService', () => {
{ {
items: [{ children: [{ route: 'route3', url: '/route3' }] }] items: [{ children: [{ route: 'route3', url: '/route3' }] }]
} }
]); ] as NavBarGroupRef[]);
}); });
it('should filter out disabled items', () => { it('should filter out disabled items', () => {
@@ -695,18 +703,10 @@ describe('AppExtensionService', () => {
expect(navigation).toEqual([ expect(navigation).toEqual([
{ items: [{ route: 'route1', url: '/route1' }] }, { items: [{ route: 'route1', url: '/route1' }] },
{ items: [{ children: [] }] } { items: [{ children: [] }] }
]); ] as NavBarGroupRef[]);
}); });
it('should filter out items based on rule', () => { it('should filter out items based on rule', () => {
spyOn(service, 'filterVisible').and.callFake(item => {
if (item.rules) {
return item.rules.visible;
} else {
return true;
}
});
const navigation = service.getApplicationNavigation([ const navigation = service.getApplicationNavigation([
{ {
id: 'groupId', id: 'groupId',
@@ -714,7 +714,7 @@ describe('AppExtensionService', () => {
{ {
id: 'itemId', id: 'itemId',
route: 'route1', route: 'route1',
rules: { visible: false } rules: { visible: 'notVisible' }
} }
] ]
} }
@@ -724,19 +724,11 @@ describe('AppExtensionService', () => {
}); });
it('should filter out group based on rule', () => { it('should filter out group based on rule', () => {
spyOn(service, 'filterVisible').and.callFake(item => {
if (item.rules) {
return item.rules.visible;
} else {
return true;
}
});
const navigation = service.getApplicationNavigation([ const navigation = service.getApplicationNavigation([
{ {
id: 'group1', id: 'group1',
rules: { rules: {
visible: false visible: 'notVisible'
}, },
items: [ items: [
{ {

View File

@@ -267,7 +267,7 @@ export class AppExtensionService implements RuleContext {
.filter(entry => !entry.disabled); .filter(entry => !entry.disabled);
} }
getApplicationNavigation(elements) { getApplicationNavigation(elements): Array<NavBarGroupRef> {
return elements return elements
.filter(group => this.filterVisible(group)) .filter(group => this.filterVisible(group))
.map(group => { .map(group => {

View File

@@ -52,8 +52,13 @@ import { Store } from '@ngrx/store';
import { ContentManagementService } from './content-management.service'; import { ContentManagementService } from './content-management.service';
import { NodeActionsService } from './node-actions.service'; import { NodeActionsService } from './node-actions.service';
import { TranslationService, AlfrescoApiService } from '@alfresco/adf-core'; import { TranslationService, AlfrescoApiService } from '@alfresco/adf-core';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar'; import {
MatSnackBar,
MatSnackBarRef,
SimpleSnackBar
} from '@angular/material/snack-bar';
import { NodeEntry, Node } from '@alfresco/js-api';
describe('ContentManagementService', () => { describe('ContentManagementService', () => {
let dialog: MatDialog; let dialog: MatDialog;
@@ -84,14 +89,17 @@ describe('ContentManagementService', () => {
}); });
describe('Copy node action', () => { describe('Copy node action', () => {
let subject: Subject<string>;
beforeEach(() => { beforeEach(() => {
subject = new Subject<string>();
spyOn(snackBar, 'open').and.callThrough(); spyOn(snackBar, 'open').and.callThrough();
}); });
afterEach(() => subject.complete());
it('notifies successful copy of a node', () => { it('notifies successful copy of a node', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.COPY')
);
const selection: any[] = [ const selection: any[] = [
{ entry: { id: 'node-to-copy-id', name: 'name' } } { entry: { id: 'node-to-copy-id', name: 'name' } }
@@ -100,6 +108,7 @@ describe('ContentManagementService', () => {
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
subject.next('OPERATION.SUCCES.CONTENT.COPY');
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -108,9 +117,7 @@ describe('ContentManagementService', () => {
}); });
it('notifies successful copy of multiple nodes', () => { it('notifies successful copy of multiple nodes', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.COPY')
);
const selection: any[] = [ const selection: any[] = [
{ entry: { id: 'node-to-copy-1', name: 'name1' } }, { entry: { id: 'node-to-copy-1', name: 'name1' } },
@@ -123,6 +130,7 @@ describe('ContentManagementService', () => {
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
subject.next('OPERATION.SUCCES.CONTENT.COPY');
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -131,9 +139,7 @@ describe('ContentManagementService', () => {
}); });
it('notifies partially copy of one node out of a multiple selection of nodes', () => { it('notifies partially copy of one node out of a multiple selection of nodes', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.COPY')
);
const selection: any[] = [ const selection: any[] = [
{ entry: { id: 'node-to-copy-1', name: 'name1' } }, { entry: { id: 'node-to-copy-1', name: 'name1' } },
@@ -145,6 +151,7 @@ describe('ContentManagementService', () => {
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
subject.next('OPERATION.SUCCES.CONTENT.COPY');
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -153,9 +160,7 @@ describe('ContentManagementService', () => {
}); });
it('notifies partially copy of more nodes out of a multiple selection of nodes', () => { it('notifies partially copy of more nodes out of a multiple selection of nodes', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.COPY')
);
const selection: any[] = [ const selection: any[] = [
{ entry: { id: 'node-to-copy-0', name: 'name0' } }, { entry: { id: 'node-to-copy-0', name: 'name0' } },
@@ -169,6 +174,7 @@ describe('ContentManagementService', () => {
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
subject.next('OPERATION.SUCCES.CONTENT.COPY');
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -177,9 +183,7 @@ describe('ContentManagementService', () => {
}); });
it('notifies of failed copy of multiple nodes', () => { it('notifies of failed copy of multiple nodes', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.COPY')
);
const selection: any[] = [ const selection: any[] = [
{ entry: { id: 'node-to-copy-0', name: 'name0' } }, { entry: { id: 'node-to-copy-0', name: 'name0' } },
@@ -190,6 +194,7 @@ describe('ContentManagementService', () => {
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
subject.next('OPERATION.SUCCES.CONTENT.COPY');
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -198,9 +203,7 @@ describe('ContentManagementService', () => {
}); });
it('notifies of failed copy of one node', () => { it('notifies of failed copy of one node', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.COPY')
);
const selection: any[] = [ const selection: any[] = [
{ entry: { id: 'node-to-copy', name: 'name' } } { entry: { id: 'node-to-copy', name: 'name' } }
@@ -209,6 +212,7 @@ describe('ContentManagementService', () => {
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
subject.next('OPERATION.SUCCES.CONTENT.COPY');
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -217,7 +221,7 @@ describe('ContentManagementService', () => {
}); });
it('notifies error if success message was not emitted', () => { it('notifies error if success message was not emitted', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue(of('')); spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
const selection: any[] = [ const selection: any[] = [
{ entry: { id: 'node-to-copy-id', name: 'name' } } { entry: { id: 'node-to-copy-id', name: 'name' } }
@@ -225,6 +229,7 @@ describe('ContentManagementService', () => {
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.contentCopied.next(); nodeActions.contentCopied.next();
subject.next('');
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -233,12 +238,11 @@ describe('ContentManagementService', () => {
}); });
it('notifies permission error on copy of node', () => { it('notifies permission error on copy of node', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
throwError(new Error(JSON.stringify({ error: { statusCode: 403 } })))
);
const selection: any[] = [{ entry: { id: '1', name: 'name' } }]; const selection: any[] = [{ entry: { id: '1', name: 'name' } }];
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
subject.error(new Error(JSON.stringify({ error: { statusCode: 403 } })));
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -247,13 +251,12 @@ describe('ContentManagementService', () => {
}); });
it('notifies generic error message on all errors, but 403', () => { it('notifies generic error message on all errors, but 403', () => {
spyOn(nodeActions, 'copyNodes').and.returnValue( spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
throwError(new Error(JSON.stringify({ error: { statusCode: 404 } })))
);
const selection: any[] = [{ entry: { id: '1', name: 'name' } }]; const selection: any[] = [{ entry: { id: '1', name: 'name' } }];
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
subject.error(new Error(JSON.stringify({ error: { statusCode: 404 } })));
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -263,14 +266,15 @@ describe('ContentManagementService', () => {
}); });
describe('Undo Copy action', () => { describe('Undo Copy action', () => {
beforeEach(() => { let subject: Subject<string>;
spyOn(nodeActions, 'copyNodes').and.returnValue(
of('OPERATION.SUCCES.CONTENT.COPY')
);
beforeEach(() => {
subject = new Subject<string>();
spyOn(nodeActions, 'copyNodes').and.returnValue(subject);
spyOn(snackBar, 'open').and.returnValue({ spyOn(snackBar, 'open').and.returnValue({
onAction: () => of({}) onAction: () => of(null)
}); } as MatSnackBarRef<SimpleSnackBar>);
}); });
it('should delete the newly created node on Undo action', () => { it('should delete the newly created node on Undo action', () => {
@@ -282,6 +286,7 @@ describe('ContentManagementService', () => {
const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }]; const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }];
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.copyNodes(null).next('OPERATION.SUCCES.CONTENT.COPY');
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
@@ -325,6 +330,7 @@ describe('ContentManagementService', () => {
]; ];
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.copyNodes(null).next('OPERATION.SUCCES.CONTENT.COPY');
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
@@ -348,6 +354,7 @@ describe('ContentManagementService', () => {
const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }]; const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }];
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.copyNodes(null).next('OPERATION.SUCCES.CONTENT.COPY');
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
@@ -368,6 +375,7 @@ describe('ContentManagementService', () => {
const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }]; const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }];
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.copyNodes(null).next('OPERATION.SUCCES.CONTENT.COPY');
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
@@ -388,6 +396,7 @@ describe('ContentManagementService', () => {
const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }]; const createdItems: any[] = [{ entry: { id: 'copy-id', name: 'name' } }];
store.dispatch(new CopyNodesAction(selection)); store.dispatch(new CopyNodesAction(selection));
nodeActions.copyNodes(null).next('OPERATION.SUCCES.CONTENT.COPY');
nodeActions.contentCopied.next(createdItems); nodeActions.contentCopied.next(createdItems);
expect(nodeActions.copyNodes).toHaveBeenCalled(); expect(nodeActions.copyNodes).toHaveBeenCalled();
@@ -399,6 +408,8 @@ describe('ContentManagementService', () => {
}); });
describe('Move node action', () => { describe('Move node action', () => {
let subject: Subject<string>;
beforeEach(() => { beforeEach(() => {
spyOn(translationService, 'instant').and.callFake(keysArray => { spyOn(translationService, 'instant').and.callFake(keysArray => {
if (Array.isArray(keysArray)) { if (Array.isArray(keysArray)) {
@@ -414,9 +425,12 @@ describe('ContentManagementService', () => {
}); });
beforeEach(() => { beforeEach(() => {
subject = new Subject<string>();
spyOn(snackBar, 'open').and.callThrough(); spyOn(snackBar, 'open').and.callThrough();
}); });
afterEach(() => subject.complete());
it('notifies successful move of a node', () => { it('notifies successful move of a node', () => {
const node = [{ entry: { id: 'node-to-move-id', name: 'name' } }]; const node = [{ entry: { id: 'node-to-move-id', name: 'name' } }];
const moveResponse = { const moveResponse = {
@@ -425,14 +439,12 @@ describe('ContentManagementService', () => {
partiallySucceeded: [] partiallySucceeded: []
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.MOVE')
);
spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse); spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse);
const selection: any = node; const selection: any = node;
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -452,14 +464,13 @@ describe('ContentManagementService', () => {
partiallySucceeded: [] partiallySucceeded: []
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.MOVE')
);
spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse); spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse);
const selection: any = nodes; const selection: any = nodes;
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -476,14 +487,13 @@ describe('ContentManagementService', () => {
partiallySucceeded: nodes partiallySucceeded: nodes
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.MOVE')
);
spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse); spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse);
const selection = nodes; const selection = nodes;
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -503,14 +513,13 @@ describe('ContentManagementService', () => {
partiallySucceeded: nodes partiallySucceeded: nodes
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.MOVE')
);
spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse); spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse);
const selection = nodes; const selection = nodes;
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -530,13 +539,11 @@ describe('ContentManagementService', () => {
partiallySucceeded: [] partiallySucceeded: []
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.MOVE')
);
spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse); spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse);
store.dispatch(new MoveNodesAction(nodes)); store.dispatch(new MoveNodesAction(nodes));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -556,12 +563,11 @@ describe('ContentManagementService', () => {
partiallySucceeded: [nodes[1]] partiallySucceeded: [nodes[1]]
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.MOVE')
);
spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse); spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse);
store.dispatch(new MoveNodesAction(nodes)); store.dispatch(new MoveNodesAction(nodes));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -578,9 +584,10 @@ describe('ContentManagementService', () => {
partiallySucceeded: [] partiallySucceeded: []
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue(of('')); spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
store.dispatch(new MoveNodesAction(nodes)); store.dispatch(new MoveNodesAction(nodes));
nodeActions.moveNodes(null).next('');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -590,12 +597,13 @@ describe('ContentManagementService', () => {
}); });
it('notifies permission error on move of node', () => { it('notifies permission error on move of node', () => {
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
throwError(new Error(JSON.stringify({ error: { statusCode: 403 } })))
);
const selection: any[] = [{ entry: { id: '1', name: 'name' } }]; const selection: any[] = [{ entry: { id: '1', name: 'name' } }];
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions
.moveNodes(null)
.error(new Error(JSON.stringify({ error: { statusCode: 403 } })));
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -604,12 +612,13 @@ describe('ContentManagementService', () => {
}); });
it('notifies generic error message on all errors, but 403', () => { it('notifies generic error message on all errors, but 403', () => {
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
throwError(new Error(JSON.stringify({ error: { statusCode: 404 } })))
);
const selection: any[] = [{ entry: { id: '1', name: 'name' } }]; const selection: any[] = [{ entry: { id: '1', name: 'name' } }];
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions
.moveNodes(null)
.error(new Error(JSON.stringify({ error: { statusCode: 404 } })));
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -618,12 +627,13 @@ describe('ContentManagementService', () => {
}); });
it('notifies conflict error message on 409', () => { it('notifies conflict error message on 409', () => {
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
throwError(new Error(JSON.stringify({ error: { statusCode: 409 } })))
);
const selection: any[] = [{ entry: { id: '1', name: 'name' } }]; const selection: any[] = [{ entry: { id: '1', name: 'name' } }];
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions
.moveNodes(null)
.error(new Error(JSON.stringify({ error: { statusCode: 409 } })));
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
expect(snackBar.open['calls'].argsFor(0)[0]).toBe( expect(snackBar.open['calls'].argsFor(0)[0]).toBe(
@@ -639,12 +649,11 @@ describe('ContentManagementService', () => {
partiallySucceeded: [] partiallySucceeded: []
}; };
spyOn(nodeActions, 'moveNodes').and.returnValue( spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
of('OPERATION.SUCCES.CONTENT.MOVE')
);
spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse); spyOn(nodeActions, 'processResponse').and.returnValue(moveResponse);
store.dispatch(new MoveNodesAction(nodes)); store.dispatch(new MoveNodesAction(nodes));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(moveResponse); nodeActions.contentMoved.next(moveResponse);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -655,6 +664,8 @@ describe('ContentManagementService', () => {
}); });
describe('Undo Move action', () => { describe('Undo Move action', () => {
let subject: Subject<string>;
beforeEach(() => { beforeEach(() => {
spyOn(translationService, 'instant').and.callFake(keysArray => { spyOn(translationService, 'instant').and.callFake(keysArray => {
if (Array.isArray(keysArray)) { if (Array.isArray(keysArray)) {
@@ -670,15 +681,16 @@ describe('ContentManagementService', () => {
}); });
beforeEach(() => { beforeEach(() => {
spyOn(nodeActions, 'moveNodes').and.returnValue( subject = new Subject<string>();
of('OPERATION.SUCCES.CONTENT.MOVE') spyOn(nodeActions, 'moveNodes').and.returnValue(subject);
);
spyOn(snackBar, 'open').and.returnValue({ spyOn(snackBar, 'open').and.returnValue({
onAction: () => of({}) onAction: () => of(null)
}); } as MatSnackBarRef<SimpleSnackBar>);
}); });
afterEach(() => subject.next());
it('should move node back to initial parent, after succeeded move', () => { it('should move node back to initial parent, after succeeded move', () => {
const initialParent = 'parent-id-0'; const initialParent = 'parent-id-0';
const node = { const node = {
@@ -689,6 +701,7 @@ describe('ContentManagementService', () => {
spyOn(nodeActions, 'moveNodeAction').and.returnValue(of({})); spyOn(nodeActions, 'moveNodeAction').and.returnValue(of({}));
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
const movedItems = { const movedItems = {
failed: [], failed: [],
partiallySucceeded: [], partiallySucceeded: [],
@@ -726,6 +739,7 @@ describe('ContentManagementService', () => {
}; };
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(movedItems); nodeActions.contentMoved.next(movedItems);
expect(nodeActions.moveNodeAction).toHaveBeenCalledWith( expect(nodeActions.moveNodeAction).toHaveBeenCalledWith(
@@ -762,6 +776,7 @@ describe('ContentManagementService', () => {
}; };
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(movedItems); nodeActions.contentMoved.next(movedItems);
expect(contentApi.restoreNode).toHaveBeenCalled(); expect(contentApi.restoreNode).toHaveBeenCalled();
@@ -805,6 +820,7 @@ describe('ContentManagementService', () => {
}; };
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(movedItems); nodeActions.contentMoved.next(movedItems);
expect(contentApi.restoreNode).toHaveBeenCalled(); expect(contentApi.restoreNode).toHaveBeenCalled();
@@ -838,6 +854,7 @@ describe('ContentManagementService', () => {
}; };
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(movedItems); nodeActions.contentMoved.next(movedItems);
expect(contentApi.restoreNode).toHaveBeenCalled(); expect(contentApi.restoreNode).toHaveBeenCalled();
@@ -871,6 +888,7 @@ describe('ContentManagementService', () => {
}; };
store.dispatch(new MoveNodesAction(selection)); store.dispatch(new MoveNodesAction(selection));
nodeActions.moveNodes(null).next('OPERATION.SUCCES.CONTENT.MOVE');
nodeActions.contentMoved.next(movedItems); nodeActions.contentMoved.next(movedItems);
expect(nodeActions.moveNodes).toHaveBeenCalled(); expect(nodeActions.moveNodes).toHaveBeenCalled();
@@ -999,7 +1017,7 @@ describe('ContentManagementService', () => {
afterClosed() { afterClosed() {
return of(true); return of(true);
} }
}); } as MatDialogRef<MatDialog>);
}); });
it('does not purge nodes if no selection', () => { it('does not purge nodes if no selection', () => {
@@ -1185,7 +1203,7 @@ describe('ContentManagementService', () => {
}); });
it('call restore nodes if selection has nodes with path', fakeAsync(() => { it('call restore nodes if selection has nodes with path', fakeAsync(() => {
spyOn(contentApi, 'restoreNode').and.returnValue(of({})); spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
spyOn(contentApi, 'getDeletedNodes').and.returnValue( spyOn(contentApi, 'getDeletedNodes').and.returnValue(
of({ of({
list: { entries: [] } list: { entries: [] }
@@ -1217,7 +1235,7 @@ describe('ContentManagementService', () => {
it('should navigate to library folder when node is a library content', fakeAsync(() => { it('should navigate to library folder when node is a library content', fakeAsync(() => {
spyOn(store, 'dispatch').and.callThrough(); spyOn(store, 'dispatch').and.callThrough();
spyOn(contentApi, 'restoreNode').and.returnValue(of({})); spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
spyOn(contentApi, 'getDeletedNodes').and.returnValue( spyOn(contentApi, 'getDeletedNodes').and.returnValue(
of({ of({
list: { entries: [] } list: { entries: [] }
@@ -1273,7 +1291,7 @@ describe('ContentManagementService', () => {
spyOn(contentApi, 'restoreNode').and.callFake(id => { spyOn(contentApi, 'restoreNode').and.callFake(id => {
if (id === '1') { if (id === '1') {
return of({}); return of({} as NodeEntry);
} }
if (id === '2') { if (id === '2') {
@@ -1284,7 +1302,7 @@ describe('ContentManagementService', () => {
return throwError(error); return throwError(error);
} }
return of({}); return of({} as NodeEntry);
}); });
const path = { const path = {
@@ -1378,15 +1396,16 @@ describe('ContentManagementService', () => {
it('should raise info message when restore multiple nodes', fakeAsync(done => { it('should raise info message when restore multiple nodes', fakeAsync(done => {
spyOn(contentApi, 'restoreNode').and.callFake(id => { spyOn(contentApi, 'restoreNode').and.callFake(id => {
const entry = {} as NodeEntry;
if (id === '1') { if (id === '1') {
return of({}); return of(entry);
} }
if (id === '2') { if (id === '2') {
return of({}); return of(entry);
} }
return of({}); return of(entry);
}); });
actions$.pipe( actions$.pipe(
@@ -1411,8 +1430,8 @@ describe('ContentManagementService', () => {
store.dispatch(new RestoreDeletedNodesAction(selection)); store.dispatch(new RestoreDeletedNodesAction(selection));
})); }));
xit('should raise info message when restore selected node', fakeAsync(done => { it('should raise info message when restore selected node', fakeAsync(done => {
spyOn(contentApi, 'restoreNode').and.returnValue(of({})); spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
actions$.pipe( actions$.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info), ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
@@ -1434,7 +1453,7 @@ describe('ContentManagementService', () => {
})); }));
it('navigate to restore selected node location onAction', fakeAsync(done => { it('navigate to restore selected node location onAction', fakeAsync(done => {
spyOn(contentApi, 'restoreNode').and.returnValue(of({})); spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
actions$.pipe( actions$.pipe(
ofType<NavigateRouteAction>(RouterActionTypes.NavigateRoute), ofType<NavigateRouteAction>(RouterActionTypes.NavigateRoute),
@@ -1467,13 +1486,13 @@ describe('ContentManagementService', () => {
describe('Share Node', () => { describe('Share Node', () => {
it('should open dialog for nodes without requesting getNodeInfo', fakeAsync(() => { it('should open dialog for nodes without requesting getNodeInfo', fakeAsync(() => {
const node: any = { entry: { id: '1', name: 'name1' } }; const node = { entry: { id: '1', name: 'name1' } } as any;
spyOn(contentApi, 'getNodeInfo').and.returnValue(of({})); spyOn(contentApi, 'getNodeInfo').and.returnValue(of({} as Node));
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed() { afterClosed() {
return of(null); return of(null);
} }
}); } as MatDialogRef<MatDialog>);
store.dispatch(new ShareNodeAction(node)); store.dispatch(new ShareNodeAction(node));
@@ -1482,13 +1501,15 @@ describe('ContentManagementService', () => {
})); }));
it('should open dialog with getNodeInfo data when `id` property is missing', fakeAsync(() => { it('should open dialog with getNodeInfo data when `id` property is missing', fakeAsync(() => {
const node: any = { entry: { nodeId: '1', name: 'name1' } }; const node = {
spyOn(contentApi, 'getNodeInfo').and.returnValue(of({})); entry: { nodeId: '1', name: 'name1' }
} as any;
spyOn(contentApi, 'getNodeInfo').and.returnValue(of({} as Node));
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed() { afterClosed() {
return of(null); return of(null);
} }
}); } as MatDialogRef<MatDialog>);
store.dispatch(new ShareNodeAction(node)); store.dispatch(new ShareNodeAction(node));
@@ -1497,13 +1518,13 @@ describe('ContentManagementService', () => {
})); }));
it('should update node selection after dialog is closed', fakeAsync(() => { it('should update node selection after dialog is closed', fakeAsync(() => {
const node: any = { entry: { id: '1', name: 'name1' } }; const node = { entry: { id: '1', name: 'name1' } } as NodeEntry;
spyOn(store, 'dispatch').and.callThrough(); spyOn(store, 'dispatch').and.callThrough();
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed() { afterClosed() {
return of(null); return of(null);
} }
}); } as MatDialogRef<MatDialog>);
store.dispatch(new ShareNodeAction(node)); store.dispatch(new ShareNodeAction(node));
@@ -1513,11 +1534,11 @@ describe('ContentManagementService', () => {
})); }));
it('should emit event when node is un-shared', fakeAsync(() => { it('should emit event when node is un-shared', fakeAsync(() => {
const node: any = { entry: { id: '1', name: 'name1' } }; const node = { entry: { id: '1', name: 'name1' } } as NodeEntry;
spyOn(contentManagementService.linksUnshared, 'next').and.callThrough(); spyOn(contentManagementService.linksUnshared, 'next').and.callThrough();
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed: () => of(node) afterClosed: () => of(node)
}); } as MatDialogRef<MatDialog>);
store.dispatch(new ShareNodeAction(node)); store.dispatch(new ShareNodeAction(node));
tick(); tick();
@@ -1531,7 +1552,9 @@ describe('ContentManagementService', () => {
describe('Unlock Node', () => { describe('Unlock Node', () => {
it('should unlock node', fakeAsync(() => { it('should unlock node', fakeAsync(() => {
spyOn(contentApi, 'unlockNode').and.returnValue(Promise.resolve({})); spyOn(contentApi, 'unlockNode').and.returnValue(
Promise.resolve({} as NodeEntry)
);
store.dispatch(new UnlockWriteAction({ entry: { id: 'node-id' } })); store.dispatch(new UnlockWriteAction({ entry: { id: 'node-id' } }));
tick(); tick();

View File

@@ -1164,7 +1164,7 @@ export class ContentManagementService {
return i18nMessageString; return i18nMessageString;
} }
getNodeInfo() { getNodeInfo(): Observable<MinimalNodeEntryEntity> {
return this.store.select(getAppSelection).pipe( return this.store.select(getAppSelection).pipe(
take(1), take(1),
flatMap(({ file }) => { flatMap(({ file }) => {
@@ -1178,8 +1178,8 @@ export class ContentManagementService {
); );
} }
unlockNode(node: NodeEntry) { unlockNode(node: NodeEntry): Promise<void | NodeEntry> {
this.contentApi.unlockNode(node.entry.id).catch(() => { return this.contentApi.unlockNode(node.entry.id).catch(() => {
this.store.dispatch( this.store.dispatch(
new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', { new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', {
fileName: node.entry.name fileName: node.entry.name

View File

@@ -24,12 +24,16 @@
*/ */
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async } from '@angular/core/testing';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { of, throwError } from 'rxjs'; import { of, throwError, Subject } from 'rxjs';
import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core'; import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
import { DocumentListService } from '@alfresco/adf-content-services'; import { DocumentListService } from '@alfresco/adf-content-services';
import { NodeActionsService } from './node-actions.service'; import { NodeActionsService, BatchOperationType } from './node-actions.service';
import { MinimalNodeEntryEntity } from '@alfresco/js-api'; import {
MinimalNodeEntryEntity,
NodeChildAssociationEntry,
NodeEntry
} from '@alfresco/js-api';
import { AppTestingModule } from '../testing/app-testing.module'; import { AppTestingModule } from '../testing/app-testing.module';
import { ContentApiService } from '@alfresco/aca-shared'; import { ContentApiService } from '@alfresco/aca-shared';
@@ -80,6 +84,7 @@ describe('NodeActionsService', () => {
const spyOnSuccess = jasmine.createSpy('spyOnSuccess'); const spyOnSuccess = jasmine.createSpy('spyOnSuccess');
const spyOnError = jasmine.createSpy('spyOnError'); const spyOnError = jasmine.createSpy('spyOnError');
let contentApi: ContentApiService; let contentApi: ContentApiService;
let dialog: MatDialog;
const helper = { const helper = {
fakeCopyNode: ( fakeCopyNode: (
@@ -132,11 +137,100 @@ describe('NodeActionsService', () => {
service = TestBed.get(NodeActionsService); service = TestBed.get(NodeActionsService);
apiService = TestBed.get(AlfrescoApiService); apiService = TestBed.get(AlfrescoApiService);
dialog = TestBed.get(MatDialog);
apiService.reset(); apiService.reset();
nodesApi = apiService.getInstance().nodes; nodesApi = apiService.getInstance().nodes;
}); });
describe('ContentNodeSelector configuration', () => {
it('should validate selection when allowableOperation has `create`', async(() => {
spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
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`', async(() => {
spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
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', async(() => {
spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
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', async(() => {
spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
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', () => { describe('doBatchOperation', () => {
beforeEach(() => { beforeEach(() => {
spyOnSuccess.calls.reset(); spyOnSuccess.calls.reset();
@@ -211,30 +305,16 @@ describe('NodeActionsService', () => {
it("should not throw error if entry in 'contentEntities' does not have id, but has nodeId property", async(() => { it("should not throw error if entry in 'contentEntities' does not have id, but has nodeId property", async(() => {
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }]; const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
spyOn(service, 'getContentNodeSelection').and.returnValue( spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
of([new TestNode().entry])
);
spyOn(service, 'copyNodeAction').and.returnValue(of({})); spyOn(service, 'copyNodeAction').and.returnValue(of({}));
const doCopyBatchOperation = service service.copyNodes(contentEntities).subscribe(spyOnSuccess, spyOnError);
.copyNodes(contentEntities) subject.next([new TestNode().entry]);
.asObservable();
doCopyBatchOperation
.toPromise()
.then(
() => {
spyOnSuccess();
},
error => {
spyOnError(error);
}
)
.then(() => {
expect(spyOnSuccess).toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalled();
expect(spyOnError).not.toHaveBeenCalledWith(badRequestError); expect(spyOnError).not.toHaveBeenCalledWith(badRequestError);
});
})); }));
}); });
@@ -268,11 +348,10 @@ describe('NodeActionsService', () => {
spyOn(service, 'getEntryParentId').and.returnValue('parent-id'); spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
const dialog = TestBed.get(MatDialog);
spyOn(dialog, 'open').and.callFake( spyOn(dialog, 'open').and.callFake(
(_contentNodeSelectorComponent: any, data: any) => { (_contentNodeSelectorComponent: any, data: any) => {
testContentNodeSelectorComponentData = data; testContentNodeSelectorComponentData = data;
return { componentInstance: {} }; return { componentInstance: {} } as MatDialogRef<any>;
} }
); );
@@ -329,19 +408,20 @@ describe('NodeActionsService', () => {
}); });
it('should be called', () => { it('should be called', () => {
const subject = new Subject<MinimalNodeEntryEntity[]>();
const spyOnBatchOperation = spyOn( const spyOnBatchOperation = spyOn(
service, service,
'doBatchOperation' 'doBatchOperation'
).and.callThrough(); ).and.callThrough();
spyOn(service, 'getContentNodeSelection').and.returnValue( spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
of([destinationFolder.entry])
);
spyOn(service, 'copyNodeAction').and.returnValue(of({})); spyOn(service, 'copyNodeAction').and.returnValue(of({}));
service.copyNodes([fileToCopy, folderToCopy]); service.copyNodes([fileToCopy, folderToCopy]);
subject.next([destinationFolder.entry]);
expect(spyOnBatchOperation.calls.count()).toEqual(1); expect(spyOnBatchOperation.calls.count()).toEqual(1);
expect(spyOnBatchOperation).toHaveBeenCalledWith( expect(spyOnBatchOperation).toHaveBeenCalledWith(
'copy', BatchOperationType.copy,
[fileToCopy, folderToCopy], [fileToCopy, folderToCopy],
undefined undefined
); );
@@ -359,18 +439,17 @@ describe('NodeActionsService', () => {
spyOn(service, 'getEntryParentId').and.returnValue('parent-id'); spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
let testContentNodeSelectorComponentData; let testContentNodeSelectorComponentData;
const dialog = TestBed.get(MatDialog);
const spyOnDialog = spyOn(dialog, 'open').and.callFake( const spyOnDialog = spyOn(dialog, 'open').and.callFake(
(_contentNodeSelectorComponent: any, data: any) => { (_contentNodeSelectorComponent: any, data: any) => {
testContentNodeSelectorComponentData = data; testContentNodeSelectorComponentData = data;
return { componentInstance: {} }; return { componentInstance: {} } as MatDialogRef<any>;
} }
); );
service.copyNodes([fileToCopy, folderToCopy]); service.copyNodes([fileToCopy, folderToCopy]);
expect(spyOnBatchOperation).toHaveBeenCalledWith( expect(spyOnBatchOperation).toHaveBeenCalledWith(
'copy', BatchOperationType.copy,
[fileToCopy, folderToCopy], [fileToCopy, folderToCopy],
undefined undefined
); );
@@ -413,11 +492,10 @@ describe('NodeActionsService', () => {
spyOn(service, 'getEntryParentId').and.returnValue('parent-id'); spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
let testContentNodeSelectorComponentData; let testContentNodeSelectorComponentData;
const dialog = TestBed.get(MatDialog);
spyOn(dialog, 'open').and.callFake( spyOn(dialog, 'open').and.callFake(
(_contentNodeSelectorComponent: any, data: any) => { (_contentNodeSelectorComponent: any, data: any) => {
testContentNodeSelectorComponentData = data; testContentNodeSelectorComponentData = data;
return { componentInstance: {} }; return { componentInstance: {} } as MatDialogRef<any>;
} }
); );
@@ -443,11 +521,10 @@ describe('NodeActionsService', () => {
spyOn(service, 'getEntryParentId').and.returnValue('parent-id'); spyOn(service, 'getEntryParentId').and.returnValue('parent-id');
let testContentNodeSelectorComponentData; let testContentNodeSelectorComponentData;
const dialog = TestBed.get(MatDialog);
spyOn(dialog, 'open').and.callFake( spyOn(dialog, 'open').and.callFake(
(_contentNodeSelectorComponent: any, data: any) => { (_contentNodeSelectorComponent: any, data: any) => {
testContentNodeSelectorComponentData = data; testContentNodeSelectorComponentData = data;
return { componentInstance: {} }; return { componentInstance: {} } as MatDialogRef<any>;
} }
); );
@@ -636,8 +713,10 @@ describe('NodeActionsService', () => {
let spyOnContentAction; let spyOnContentAction;
let spyOnFolderAction; let spyOnFolderAction;
let copyObservable; let copyObservable;
let subject: Subject<NodeChildAssociationEntry>;
beforeEach(() => { beforeEach(() => {
subject = new Subject<NodeChildAssociationEntry>();
folderToCopy = new TestNode( folderToCopy = new TestNode(
'folder-to-copy-id', 'folder-to-copy-id',
!isFile, !isFile,
@@ -673,6 +752,8 @@ describe('NodeActionsService', () => {
spyOnError.calls.reset(); spyOnError.calls.reset();
}); });
afterEach(() => subject.complete());
it('when folder to copy has a file as content', async(() => { it('when folder to copy has a file as content', async(() => {
const testFamilyNodes = [ const testFamilyNodes = [
{ {
@@ -687,7 +768,9 @@ describe('NodeActionsService', () => {
spyOn(nodesApi, 'getNodeChildren').and.callFake( spyOn(nodesApi, 'getNodeChildren').and.callFake(
helper.fakeGetNodeChildren(testFamilyNodes) helper.fakeGetNodeChildren(testFamilyNodes)
); );
spyOn(service, 'getChildByName').and.returnValue(of(existingFolder)); spyOn(service, 'getChildByName').and.returnValue(of(
existingFolder
) as any);
copyObservable copyObservable
.toPromise() .toPromise()
@@ -738,7 +821,7 @@ describe('NodeActionsService', () => {
spyOn(nodesApi, 'getNodeChildren').and.callFake( spyOn(nodesApi, 'getNodeChildren').and.callFake(
helper.fakeGetNodeChildren(testFamilyNodes) helper.fakeGetNodeChildren(testFamilyNodes)
); );
spyOn(service, 'getChildByName').and.returnValue(of(existingFolder)); spyOn(service, 'getChildByName').and.returnValue(subject);
copyObservable copyObservable
.toPromise() .toPromise()
@@ -766,6 +849,8 @@ describe('NodeActionsService', () => {
] ]
]); ]);
}); });
subject.next(existingFolder);
})); }));
it('when folder to copy has another folder as child', async(() => { it('when folder to copy has another folder as child', async(() => {
@@ -783,7 +868,9 @@ describe('NodeActionsService', () => {
spyOn(nodesApi, 'getNodeChildren').and.callFake( spyOn(nodesApi, 'getNodeChildren').and.callFake(
helper.fakeGetNodeChildren(testFamilyNodes) helper.fakeGetNodeChildren(testFamilyNodes)
); );
spyOn(service, 'getChildByName').and.returnValue(of(existingFolder)); spyOn(service, 'getChildByName').and.returnValue(of(
existingFolder
) as any);
copyObservable copyObservable
.toPromise() .toPromise()
@@ -830,8 +917,10 @@ describe('NodeActionsService', () => {
let spyOnBatchOperation; let spyOnBatchOperation;
let spyOnDocumentListServiceAction; let spyOnDocumentListServiceAction;
let documentListService; let documentListService;
let subject: Subject<MinimalNodeEntryEntity[]>;
beforeEach(() => { beforeEach(() => {
subject = new Subject<MinimalNodeEntryEntity[]>();
fileToMove = new TestNode('file-to-be-moved', isFile, 'file-name'); fileToMove = new TestNode('file-to-be-moved', isFile, 'file-name');
folderToMove = new TestNode('fid', !isFile, 'folder-name'); folderToMove = new TestNode('fid', !isFile, 'folder-name');
destinationFolder = new TestNode(folderDestinationId); destinationFolder = new TestNode(folderDestinationId);
@@ -843,11 +932,13 @@ describe('NodeActionsService', () => {
).and.callThrough(); ).and.callThrough();
}); });
afterEach(() => subject.complete());
it('should allow to select destination for nodes that have permission to be moved', () => { it('should allow to select destination for nodes that have permission to be moved', () => {
const spyOnDestinationPicker = spyOn( const spyOnDestinationPicker = spyOn(
service, service,
'getContentNodeSelection' 'getContentNodeSelection'
).and.returnValue(of([destinationFolder.entry])); ).and.returnValue(subject);
spyOn(service, 'moveContentAction').and.returnValue(of({})); spyOn(service, 'moveContentAction').and.returnValue(of({}));
spyOn(service, 'moveFolderAction').and.returnValue(of({})); spyOn(service, 'moveFolderAction').and.returnValue(of({}));
@@ -855,8 +946,10 @@ describe('NodeActionsService', () => {
folderToMove.entry['allowableOperations'] = [permissionToMove]; folderToMove.entry['allowableOperations'] = [permissionToMove];
service.moveNodes([fileToMove, folderToMove], permissionToMove); service.moveNodes([fileToMove, folderToMove], permissionToMove);
subject.next([destinationFolder.entry]);
expect(spyOnBatchOperation).toHaveBeenCalledWith( expect(spyOnBatchOperation).toHaveBeenCalledWith(
'move', BatchOperationType.move,
[fileToMove, folderToMove], [fileToMove, folderToMove],
permissionToMove permissionToMove
); );
@@ -867,14 +960,16 @@ describe('NodeActionsService', () => {
const spyOnDestinationPicker = spyOn( const spyOnDestinationPicker = spyOn(
service, service,
'getContentNodeSelection' 'getContentNodeSelection'
).and.returnValue(of([destinationFolder.entry])); ).and.returnValue(subject);
fileToMove.entry['allowableOperations'] = []; fileToMove.entry['allowableOperations'] = [];
folderToMove.entry['allowableOperations'] = []; folderToMove.entry['allowableOperations'] = [];
service.moveNodes([fileToMove, folderToMove], permissionToMove); service.moveNodes([fileToMove, folderToMove], permissionToMove);
subject.next([destinationFolder.entry]);
expect(spyOnBatchOperation).toHaveBeenCalledWith( expect(spyOnBatchOperation).toHaveBeenCalledWith(
'move', BatchOperationType.move,
[fileToMove, folderToMove], [fileToMove, folderToMove],
permissionToMove permissionToMove
); );
@@ -882,9 +977,7 @@ describe('NodeActionsService', () => {
}); });
it('should call the documentListService moveNode directly for moving a file that has permission to be moved', () => { it('should call the documentListService moveNode directly for moving a file that has permission to be moved', () => {
spyOn(service, 'getContentNodeSelection').and.returnValue( spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
of([destinationFolder.entry])
);
fileToMove.entry['allowableOperations'] = [permissionToMove]; fileToMove.entry['allowableOperations'] = [permissionToMove];
spyOnDocumentListServiceAction = spyOn( spyOnDocumentListServiceAction = spyOn(
documentListService, documentListService,
@@ -893,6 +986,8 @@ describe('NodeActionsService', () => {
spyOn(service, 'moveNodeAction'); spyOn(service, 'moveNodeAction');
service.moveNodes([fileToMove], permissionToMove); service.moveNodes([fileToMove], permissionToMove);
subject.next([destinationFolder.entry]);
expect(service.moveNodeAction).not.toHaveBeenCalled(); expect(service.moveNodeAction).not.toHaveBeenCalled();
expect(spyOnDocumentListServiceAction).toHaveBeenCalled(); expect(spyOnDocumentListServiceAction).toHaveBeenCalled();
}); });
@@ -995,11 +1090,15 @@ describe('NodeActionsService', () => {
}); });
describe('moveFolderAction', () => { describe('moveFolderAction', () => {
let subject$: Subject<NodeChildAssociationEntry>;
beforeEach(() => { beforeEach(() => {
subject$ = new Subject<NodeChildAssociationEntry>();
spyOnSuccess.calls.reset(); spyOnSuccess.calls.reset();
spyOnError.calls.reset(); spyOnError.calls.reset();
}); });
afterEach(() => subject$.complete());
it('should not throw permission error in case it occurs on folder move', async(() => { it('should not throw permission error in case it occurs on folder move', async(() => {
spyOnDocumentListServiceAction = spyOn( spyOnDocumentListServiceAction = spyOn(
documentListService, documentListService,
@@ -1029,41 +1128,29 @@ describe('NodeActionsService', () => {
})); }));
it('should not throw error on conflict in case it occurs on folder move', async(() => { it('should not throw error on conflict in case it occurs on folder move', async(() => {
spyOnDocumentListServiceAction = spyOn(
documentListService,
'moveNode'
).and.returnValue(throwError(conflictError));
const newDestination = new TestNode( const newDestination = new TestNode(
'new-destination', 'new-destination',
!isFile, !isFile,
folderToMove.entry.name folderToMove.entry.name
); ) as NodeChildAssociationEntry;
spyOn(service, 'getChildByName').and.returnValue(of(newDestination));
spyOnDocumentListServiceAction = spyOn(
documentListService,
'moveNode'
).and.returnValue(throwError(conflictError));
spyOn(service, 'getChildByName').and.returnValue(subject$);
spyOn(service, 'getNodeChildren').and.returnValue( spyOn(service, 'getNodeChildren').and.returnValue(
of(emptyChildrenList) of(emptyChildrenList)
); );
const moveFolderActionObservable = service.moveFolderAction( service
folderToMove.entry, .moveFolderAction(folderToMove.entry, folderDestinationId)
folderDestinationId .subscribe(spyOnSuccess, spyOnError);
);
moveFolderActionObservable subject$.next(newDestination);
.toPromise()
.then(
() => {
spyOnSuccess();
},
error => {
spyOnError(error);
}
)
.then(() => {
expect(spyOnDocumentListServiceAction).toHaveBeenCalled();
expect(spyOnSuccess).toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalled();
expect(spyOnError).not.toHaveBeenCalledWith(conflictError); expect(spyOnError).not.toHaveBeenCalledWith(conflictError);
});
})); }));
it('should try to move children nodes of a folder to already existing folder with same name', async(() => { it('should try to move children nodes of a folder to already existing folder with same name', async(() => {
@@ -1087,33 +1174,21 @@ describe('NodeActionsService', () => {
'new-destination', 'new-destination',
!isFile, !isFile,
'conflicting-name' 'conflicting-name'
); ) as NodeChildAssociationEntry;
spyOn(service, 'getChildByName').and.returnValue(of(newDestination)); spyOn(service, 'getChildByName').and.returnValue(subject$);
const childrenNodes = [fileToMove, folderToMove]; const childrenNodes = [fileToMove, folderToMove];
spyOn(service, 'getNodeChildren').and.returnValue( spyOn(service, 'getNodeChildren').and.returnValue(
of({ list: { entries: childrenNodes } }) of({ list: { entries: childrenNodes } })
); );
const moveFolderActionObservable = service.moveFolderAction( service
parentFolderToMove.entry, .moveFolderAction(parentFolderToMove.entry, folderDestinationId)
folderDestinationId .subscribe(spyOnSuccess, spyOnError);
); subject$.next(newDestination);
moveFolderActionObservable
.toPromise()
.then(
() => {
spyOnSuccess();
},
error => {
spyOnError(error);
}
)
.then(() => {
expect(spyOnDocumentListServiceAction).toHaveBeenCalled();
expect(spyOnDocumentListServiceAction).toHaveBeenCalled();
expect(spyOnSuccess).toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalled();
expect(spyOnError).not.toHaveBeenCalledWith(conflictError); expect(spyOnError).not.toHaveBeenCalledWith(conflictError);
});
})); }));
}); });
@@ -1122,8 +1197,10 @@ describe('NodeActionsService', () => {
let parentFolderToMove; let parentFolderToMove;
let moveNodeActionPromise; let moveNodeActionPromise;
let spyOnDelete; let spyOnDelete;
let subject$: Subject<NodeChildAssociationEntry>;
beforeEach(() => { beforeEach(() => {
subject$ = new Subject<NodeChildAssociationEntry>();
parentFolderToMove = new TestNode( parentFolderToMove = new TestNode(
'parent-folder', 'parent-folder',
!isFile, !isFile,
@@ -1138,6 +1215,7 @@ describe('NodeActionsService', () => {
spyOnDelete.calls.reset(); spyOnDelete.calls.reset();
spyOnSuccess.calls.reset(); spyOnSuccess.calls.reset();
spyOnError.calls.reset(); spyOnError.calls.reset();
subject$.complete();
}); });
it('should take no extra delete action, if folder was moved to the same location', async(() => { it('should take no extra delete action, if folder was moved to the same location', async(() => {
@@ -1207,29 +1285,18 @@ describe('NodeActionsService', () => {
partiallySucceeded: [] partiallySucceeded: []
}); });
const folderOnLocation = parentFolderToMove; const folderOnLocation = parentFolderToMove;
spyOn(service, 'getChildByName').and.returnValue( spyOn(service, 'getChildByName').and.returnValue(subject$);
of(folderOnLocation)
);
parentFolderToMove.entry.parentId = `not-${folderDestinationId}`; parentFolderToMove.entry.parentId = `not-${folderDestinationId}`;
moveNodeActionPromise = service moveNodeActionPromise = service
.moveNodeAction(parentFolderToMove.entry, folderDestinationId) .moveNodeAction(parentFolderToMove.entry, folderDestinationId)
.toPromise(); .subscribe(spyOnSuccess, spyOnError);
moveNodeActionPromise subject$.next(folderOnLocation);
.then(
() => {
spyOnSuccess();
},
error => {
spyOnError(error);
}
)
.then(() => {
expect(spyOnDelete).toHaveBeenCalled(); expect(spyOnDelete).toHaveBeenCalled();
expect(spyOnSuccess).toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalled();
expect(spyOnError).not.toHaveBeenCalled(); expect(spyOnError).not.toHaveBeenCalled();
});
})); }));
it('should take no extra delete action, if folder is no longer on location', async(() => { it('should take no extra delete action, if folder is no longer on location', async(() => {
@@ -1242,27 +1309,17 @@ describe('NodeActionsService', () => {
failed: [], failed: [],
partiallySucceeded: [] partiallySucceeded: []
}); });
spyOn(service, 'getChildByName').and.returnValue(of(null)); spyOn(service, 'getChildByName').and.returnValue(subject$);
parentFolderToMove.entry.parentId = `not-${folderDestinationId}`; parentFolderToMove.entry.parentId = `not-${folderDestinationId}`;
moveNodeActionPromise = service moveNodeActionPromise = service
.moveNodeAction(parentFolderToMove.entry, folderDestinationId) .moveNodeAction(parentFolderToMove.entry, folderDestinationId)
.toPromise(); .subscribe(spyOnSuccess, spyOnError);
moveNodeActionPromise subject$.next(null);
.then(
() => {
spyOnSuccess();
},
error => {
spyOnError(error);
}
)
.then(() => {
expect(spyOnDelete).not.toHaveBeenCalled();
expect(spyOnDelete).not.toHaveBeenCalled();
expect(spyOnSuccess).toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalled();
expect(spyOnError).not.toHaveBeenCalled(); expect(spyOnError).not.toHaveBeenCalled();
});
})); }));
}); });
}); });

View File

@@ -45,7 +45,8 @@ import {
MinimalNodeEntity, MinimalNodeEntity,
MinimalNodeEntryEntity, MinimalNodeEntryEntity,
SitePaging, SitePaging,
NodeChildAssociationPaging NodeChildAssociationPaging,
NodeChildAssociationEntry
} from '@alfresco/js-api'; } from '@alfresco/js-api';
import { ContentApiService } from '@alfresco/aca-shared'; import { ContentApiService } from '@alfresco/aca-shared';
import { catchError, map, mergeMap } from 'rxjs/operators'; import { catchError, map, mergeMap } from 'rxjs/operators';
@@ -624,11 +625,14 @@ export class NodeActionsService {
); );
} }
getChildByName(parentId: string, name: string) { getChildByName(
parentId: string,
name: string
): Subject<NodeChildAssociationEntry> {
const matchedNodes = new Subject<any>(); const matchedNodes = new Subject<any>();
this.getNodeChildren(parentId).subscribe( this.getNodeChildren(parentId).subscribe(
(childrenNodes: any) => { (childrenNodes: NodeChildAssociationPaging) => {
const result = childrenNodes.list.entries.find( const result = childrenNodes.list.entries.find(
node => node.entry.name === name node => node.entry.name === name
); );

View File

@@ -32,7 +32,7 @@ import { Store } from '@ngrx/store';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core'; import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core';
import { NodeTemplateService } from './node-template.service'; import { NodeTemplateService } from './node-template.service';
import { of } from 'rxjs'; import { ResultSetPaging } from '@alfresco/js-api';
describe('NodeTemplateService', () => { describe('NodeTemplateService', () => {
let dialog: MatDialog; let dialog: MatDialog;
@@ -65,7 +65,9 @@ describe('NodeTemplateService', () => {
it('should open dialog with parent node `id` as data property', fakeAsync(() => { it('should open dialog with parent node `id` as data property', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ list: { entries: [{ entry: { id: 'parent-node-id' } }] } }) Promise.resolve({
list: { entries: [{ entry: { id: 'parent-node-id' } }] }
} as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
@@ -79,7 +81,7 @@ describe('NodeTemplateService', () => {
it('should remove parents path for templates breadcrumb', fakeAsync(() => { it('should remove parents path for templates breadcrumb', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ Promise.resolve({
list: { list: {
entries: [ entries: [
{ {
@@ -96,11 +98,12 @@ describe('NodeTemplateService', () => {
} }
] ]
} }
}) } as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
const breadcrumb = dialog.open['calls'] const breadcrumb = dialog.open['calls']
.argsFor(0)[1] .argsFor(0)[1]
@@ -120,7 +123,7 @@ describe('NodeTemplateService', () => {
it('should set template folder path as root for breadcrumb', fakeAsync(() => { it('should set template folder path as root for breadcrumb', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ Promise.resolve({
list: { list: {
entries: [ entries: [
{ {
@@ -137,11 +140,12 @@ describe('NodeTemplateService', () => {
} }
] ]
} }
}) } as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
const breadcrumb = dialog.open['calls'] const breadcrumb = dialog.open['calls']
.argsFor(0)[1] .argsFor(0)[1]
@@ -178,9 +182,9 @@ describe('NodeTemplateService', () => {
); );
})); }));
it('should return true if row is not a `link` nodeType', () => { it('should return true if row is not a `link` nodeType', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ Promise.resolve({
list: { list: {
entries: [ entries: [
{ {
@@ -194,22 +198,23 @@ describe('NodeTemplateService', () => {
} }
] ]
} }
}) } as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
expect( expect(
dialog.open['calls'].argsFor(0)[1].data.rowFilter({ dialog.open['calls'].argsFor(0)[1].data.rowFilter({
node: { entry: { nodeType: 'text' } } node: { entry: { nodeType: 'text' } }
}) })
).toBe(true); ).toBe(true);
}); }));
it('should return false if row is a `filelink` nodeType', () => { it('should return false if row is a `filelink` nodeType', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ Promise.resolve({
list: { list: {
entries: [ entries: [
{ {
@@ -223,22 +228,23 @@ describe('NodeTemplateService', () => {
} }
] ]
} }
}) } as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
expect( expect(
dialog.open['calls'].argsFor(0)[1].data.rowFilter({ dialog.open['calls'].argsFor(0)[1].data.rowFilter({
node: { entry: { nodeType: 'app:filelink' } } node: { entry: { nodeType: 'app:filelink' } }
}) })
).toBe(false); ).toBe(false);
}); }));
it('should return false if row is a `folderlink` nodeType', () => { it('should return false if row is a `folderlink` nodeType', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ Promise.resolve({
list: { list: {
entries: [ entries: [
{ {
@@ -252,27 +258,31 @@ describe('NodeTemplateService', () => {
} }
] ]
} }
}) } as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
expect( expect(
dialog.open['calls'].argsFor(0)[1].data.rowFilter({ dialog.open['calls'].argsFor(0)[1].data.rowFilter({
node: { entry: { nodeType: 'app:folderlink' } } node: { entry: { nodeType: 'app:folderlink' } }
}) })
).toBe(false); ).toBe(false);
}); }));
describe('File templates', () => { describe('File templates', () => {
it('should return false if selected node is not a file', () => { it('should return false if selected node is not a file', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ list: { entries: [{ entry: { id: 'templates-folder-id' } }] } }) Promise.resolve({
list: { entries: [{ entry: { id: 'templates-folder-id' } }] }
} as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
const isSelectionValid = dialog.open['calls'] const isSelectionValid = dialog.open['calls']
.argsFor(0)[1] .argsFor(0)[1]
@@ -284,15 +294,18 @@ describe('NodeTemplateService', () => {
}); });
expect(isSelectionValid).toBe(false); expect(isSelectionValid).toBe(false);
}); }));
it('should return true if selected node is a template file', () => { it('should return true if selected node is a template file', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ list: { entries: [{ entry: { id: 'templates-folder-id' } }] } }) Promise.resolve({
list: { entries: [{ entry: { id: 'templates-folder-id' } }] }
} as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
const isSelectionValid = dialog.open['calls'] const isSelectionValid = dialog.open['calls']
.argsFor(0)[1] .argsFor(0)[1]
@@ -304,30 +317,36 @@ describe('NodeTemplateService', () => {
}); });
expect(isSelectionValid).toBe(true); expect(isSelectionValid).toBe(true);
}); }));
it('should set dialog title for file templates', () => { it('should set dialog title for file templates', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ list: { entries: [{ entry: { id: 'templates-folder-id' } }] } }) Promise.resolve({
list: { entries: [{ entry: { id: 'templates-folder-id' } }] }
} as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(fileTemplateConfig); nodeTemplateService.selectTemplateDialog(fileTemplateConfig);
tick();
const title = dialog.open['calls'].argsFor(0)[1].data.title; const title = dialog.open['calls'].argsFor(0)[1].data.title;
expect(title).toBe('NODE_SELECTOR.SELECT_FILE_TEMPLATE_TITLE'); expect(title).toBe('NODE_SELECTOR.SELECT_FILE_TEMPLATE_TITLE');
}); }));
}); });
describe('Folder templates', () => { describe('Folder templates', () => {
it('should return false if selected node is not a folder', () => { it('should return false if selected node is not a folder', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ list: { entries: [{ entry: { id: 'templates-folder-id' } }] } }) Promise.resolve({
list: { entries: [{ entry: { id: 'templates-folder-id' } }] }
} as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(folderTemplateConfig); nodeTemplateService.selectTemplateDialog(folderTemplateConfig);
tick();
const isSelectionValid = dialog.open['calls'] const isSelectionValid = dialog.open['calls']
.argsFor(0)[1] .argsFor(0)[1]
@@ -339,15 +358,18 @@ describe('NodeTemplateService', () => {
}); });
expect(isSelectionValid).toBe(false); expect(isSelectionValid).toBe(false);
}); }));
it('should return false if current node is the parent folder', fakeAsync(() => { it('should return false if current node is the parent folder', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ list: { entries: [{ entry: { id: 'templates-folder-id' } }] } }) Promise.resolve({
list: { entries: [{ entry: { id: 'templates-folder-id' } }] }
} as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(folderTemplateConfig); nodeTemplateService.selectTemplateDialog(folderTemplateConfig);
tick();
const isSelectionValid = dialog.open['calls'] const isSelectionValid = dialog.open['calls']
.argsFor(0)[1] .argsFor(0)[1]
@@ -363,13 +385,13 @@ describe('NodeTemplateService', () => {
it('should return true if selected node is a folder template', fakeAsync(() => { it('should return true if selected node is a folder template', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ Promise.resolve({
list: { list: {
entries: [ entries: [
{ entry: { id: 'templates-folder-id', path: { elements: [] } } } { entry: { id: 'templates-folder-id', path: { elements: [] } } }
] ]
} }
}) } as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
@@ -388,17 +410,20 @@ describe('NodeTemplateService', () => {
expect(isSelectionValid).toBe(true); expect(isSelectionValid).toBe(true);
})); }));
it('should set dialog title for folder templates', () => { it('should set dialog title for folder templates', fakeAsync(() => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue( spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(
of({ list: { entries: [{ entry: { id: 'templates-folder-id' } }] } }) Promise.resolve({
list: { entries: [{ entry: { id: 'templates-folder-id' } }] }
} as ResultSetPaging)
); );
spyOn(dialog, 'open'); spyOn(dialog, 'open');
nodeTemplateService.selectTemplateDialog(folderTemplateConfig); nodeTemplateService.selectTemplateDialog(folderTemplateConfig);
tick();
const title = dialog.open['calls'].argsFor(0)[1].data.title; const title = dialog.open['calls'].argsFor(0)[1].data.title;
expect(title).toBe('NODE_SELECTOR.SELECT_FOLDER_TEMPLATE_TITLE'); expect(title).toBe('NODE_SELECTOR.SELECT_FOLDER_TEMPLATE_TITLE');
}); }));
}); });
}); });

View File

@@ -30,13 +30,13 @@ import { EffectsModule } from '@ngrx/effects';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { ContextMenu } from '@alfresco/aca-shared/store'; import { ContextMenu } from '@alfresco/aca-shared/store';
import { ContextMenuService } from '../../components/context-menu/context-menu.service'; import { ContextMenuService } from '../../components/context-menu/context-menu.service';
import { OverlayRef } from '@angular/cdk/overlay';
import { ContextMenuOverlayRef } from '../../components/context-menu/context-menu-overlay';
describe('ContextMenuEffects', () => { describe('ContextMenuEffects', () => {
let store: Store<any>; let store: Store<any>;
let contextMenuService: ContextMenuService; let contextMenuService: ContextMenuService;
const overlayRefMock = { const overlayRefMock = new ContextMenuOverlayRef({} as OverlayRef);
close: jasmine.createSpy('close')
};
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@@ -47,6 +47,7 @@ describe('ContextMenuEffects', () => {
store = TestBed.get(Store); store = TestBed.get(Store);
contextMenuService = TestBed.get(ContextMenuService); contextMenuService = TestBed.get(ContextMenuService);
spyOn(overlayRefMock, 'close').and.callFake(() => {});
spyOn(contextMenuService, 'open').and.returnValue(overlayRefMock); spyOn(contextMenuService, 'open').and.returnValue(overlayRefMock);
}); });

View File

@@ -36,11 +36,12 @@ import {
SnackbarErrorAction SnackbarErrorAction
} from '@alfresco/aca-shared/store'; } from '@alfresco/aca-shared/store';
import { NodeTemplateService } from '../../services/node-template.service'; import { NodeTemplateService } from '../../services/node-template.service';
import { of } from 'rxjs'; import { of, Subject } from 'rxjs';
import { AlfrescoApiServiceMock, AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, AlfrescoApiService } from '@alfresco/adf-core';
import { ContentManagementService } from '../../services/content-management.service'; import { ContentManagementService } from '../../services/content-management.service';
import { Node, NodeEntry } from '@alfresco/js-api'; import { Node, NodeEntry } from '@alfresco/js-api';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { CreateFromTemplateDialogComponent } from '../../dialogs/node-template/create-from-template.dialog';
describe('TemplateEffects', () => { describe('TemplateEffects', () => {
let store: Store<any>; let store: Store<any>;
@@ -75,6 +76,8 @@ describe('TemplateEffects', () => {
selectionType: 'folder' selectionType: 'folder'
}; };
let subject: Subject<Node[]>;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [AppTestingModule, EffectsModule.forRoot([TemplateEffects])], imports: [AppTestingModule, EffectsModule.forRoot([TemplateEffects])],
@@ -95,13 +98,12 @@ describe('TemplateEffects', () => {
alfrescoApiService = TestBed.get(AlfrescoApiService); alfrescoApiService = TestBed.get(AlfrescoApiService);
contentManagementService = TestBed.get(ContentManagementService); contentManagementService = TestBed.get(ContentManagementService);
matDialog = TestBed.get(MatDialog); matDialog = TestBed.get(MatDialog);
subject = new Subject<Node[]>();
spyOn(store, 'dispatch').and.callThrough(); spyOn(store, 'dispatch').and.callThrough();
spyOn(contentManagementService.reload, 'next'); spyOn(contentManagementService.reload, 'next');
spyOn(store, 'select').and.returnValue(of({ id: 'parent-id' })); spyOn(store, 'select').and.returnValue(of({ id: 'parent-id' }));
spyOn(nodeTemplateService, 'selectTemplateDialog').and.returnValue( spyOn(nodeTemplateService, 'selectTemplateDialog').and.returnValue(subject);
of([{ id: 'template-id' }])
);
copyNodeSpy = spyOn(alfrescoApiService.getInstance().nodes, 'copyNode'); copyNodeSpy = spyOn(alfrescoApiService.getInstance().nodes, 'copyNode');
updateNodeSpy = spyOn(alfrescoApiService.getInstance().nodes, 'updateNode'); updateNodeSpy = spyOn(alfrescoApiService.getInstance().nodes, 'updateNode');
@@ -112,10 +114,28 @@ describe('TemplateEffects', () => {
updateNodeSpy.calls.reset(); updateNodeSpy.calls.reset();
}); });
it('should call createTemplateDialog on FileFromTemplate action', fakeAsync(() => {
spyOn(nodeTemplateService, 'createTemplateDialog');
store.dispatch(new FileFromTemplate());
subject.next([node]);
tick(300);
expect(nodeTemplateService.createTemplateDialog).toHaveBeenCalledWith(node);
}));
it('should call createTemplateDialog on FolderFromTemplate action', fakeAsync(() => {
spyOn(nodeTemplateService, 'createTemplateDialog');
store.dispatch(new FolderFromTemplate());
subject.next([node]);
tick(300);
expect(nodeTemplateService.createTemplateDialog).toHaveBeenCalledWith(node);
}));
it('should open dialog to select template files', fakeAsync(() => { it('should open dialog to select template files', fakeAsync(() => {
spyOn(nodeTemplateService, 'createTemplateDialog').and.returnValue({ spyOn(nodeTemplateService, 'createTemplateDialog').and.returnValue({
afterClosed: () => of(node) afterClosed: () => of(node)
}); } as MatDialogRef<CreateFromTemplateDialogComponent>);
store.dispatch(new FileFromTemplate()); store.dispatch(new FileFromTemplate());
tick(); tick();
@@ -128,7 +148,7 @@ describe('TemplateEffects', () => {
it('should open dialog to select template folders', fakeAsync(() => { it('should open dialog to select template folders', fakeAsync(() => {
spyOn(nodeTemplateService, 'createTemplateDialog').and.returnValue({ spyOn(nodeTemplateService, 'createTemplateDialog').and.returnValue({
afterClosed: () => of(node) afterClosed: () => of(node)
}); } as MatDialogRef<CreateFromTemplateDialogComponent>);
store.dispatch(new FolderFromTemplate()); store.dispatch(new FolderFromTemplate());
tick(); tick();

View File

@@ -34,12 +34,15 @@ import {
FileUploadCompleteEvent, FileUploadCompleteEvent,
FileModel FileModel
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
import { import {
UnlockWriteAction, UnlockWriteAction,
SnackbarErrorAction SnackbarErrorAction
} from '@alfresco/aca-shared/store'; } from '@alfresco/aca-shared/store';
import { ContentManagementService } from '../../services/content-management.service'; import { ContentManagementService } from '../../services/content-management.service';
import { of, throwError } from 'rxjs'; import { of, throwError } from 'rxjs';
import { MatDialogRef } from '@angular/material';
import { NodeVersionUploadDialogComponent } from '../../dialogs/node-version-upload/node-version-upload.dialog';
function createFileList(fileName, type = 'text/plain') { function createFileList(fileName, type = 'text/plain') {
const data = new Blob([''], { type }); const data = new Blob([''], { type });
@@ -198,7 +201,9 @@ describe('UploadEffects', () => {
describe('upload file version', () => { describe('upload file version', () => {
beforeEach(() => { beforeEach(() => {
const dialog = { afterClosed: () => of({}) }; const dialog = { afterClosed: () => of({}) } as MatDialogRef<
NodeVersionUploadDialogComponent
>;
spyOn(contentManagementService, 'versionUploadDialog').and.returnValue( spyOn(contentManagementService, 'versionUploadDialog').and.returnValue(
dialog dialog
); );
@@ -208,11 +213,9 @@ describe('UploadEffects', () => {
it('should upload file', () => { it('should upload file', () => {
spyOn(contentManagementService, 'getNodeInfo').and.returnValue( spyOn(contentManagementService, 'getNodeInfo').and.returnValue(
of({ of({
entry: {
id: 'file1', id: 'file1',
properties: {} properties: {}
} } as MinimalNodeEntryEntity)
})
); );
uploadVersionInput.files = createFileList('bogus.txt'); uploadVersionInput.files = createFileList('bogus.txt');