stabilise unit tests (#1878)

* cleanup async usage

* cleanup async usage

* fix library favorite tests and code
This commit is contained in:
Denys Vuika 2020-12-11 13:01:31 +00:00 committed by GitHub
parent 72cc4f705f
commit b71e1530d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 153 additions and 183 deletions

View File

@ -22,9 +22,9 @@
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { ContentActionRef } from '@alfresco/adf-extensions'; import { ContentActionRef, SidebarTabRef } from '@alfresco/adf-extensions';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { SetInfoDrawerStateAction, ToggleInfoDrawerAction } from '@alfresco/aca-shared/store'; import { SetInfoDrawerStateAction, ToggleInfoDrawerAction } from '@alfresco/aca-shared/store';
import { of, Subject } from 'rxjs'; import { of, Subject } from 'rxjs';
@ -38,7 +38,7 @@ describe('InfoDrawerComponent', () => {
let fixture: ComponentFixture<InfoDrawerComponent>; let fixture: ComponentFixture<InfoDrawerComponent>;
let component: InfoDrawerComponent; let component: InfoDrawerComponent;
let contentApiService: ContentApiService; let contentApiService: ContentApiService;
let tab; let tab: SidebarTabRef;
let appExtensionService: AppExtensionService; let appExtensionService: AppExtensionService;
const mockStream = new Subject(); const mockStream = new Subject();
const storeMock = { const storeMock = {
@ -61,7 +61,10 @@ describe('InfoDrawerComponent', () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [LibTestingModule, SharedToolbarModule], imports: [LibTestingModule, SharedToolbarModule],
declarations: [InfoDrawerComponent], declarations: [InfoDrawerComponent],
providers: [ContentApiService, { provide: AppExtensionService, useValue: extensionServiceMock }, { provide: Store, useValue: storeMock }], providers: [
{ provide: AppExtensionService, useValue: extensionServiceMock },
{ provide: Store, useValue: storeMock }
],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}); });
@ -70,7 +73,7 @@ describe('InfoDrawerComponent', () => {
appExtensionService = TestBed.inject(AppExtensionService); appExtensionService = TestBed.inject(AppExtensionService);
contentApiService = TestBed.inject(ContentApiService); contentApiService = TestBed.inject(ContentApiService);
tab = { title: 'tab1' }; tab = { title: 'tab1', id: 'tab1', component: '' };
spyOn(appExtensionService, 'getSidebarTabs').and.returnValue([tab]); spyOn(appExtensionService, 'getSidebarTabs').and.returnValue([tab]);
}); });
@ -91,7 +94,7 @@ describe('InfoDrawerComponent', () => {
expect(storeMock.dispatch).toHaveBeenCalledWith(new SetInfoDrawerStateAction(false)); expect(storeMock.dispatch).toHaveBeenCalledWith(new SetInfoDrawerStateAction(false));
}); });
it('should set displayNode when node is library', async(() => { it('should set displayNode when node is library', () => {
spyOn(contentApiService, 'getNodeInfo'); spyOn(contentApiService, 'getNodeInfo');
const nodeMock: any = { const nodeMock: any = {
entry: { id: 'nodeId' }, entry: { id: 'nodeId' },
@ -104,9 +107,9 @@ describe('InfoDrawerComponent', () => {
expect(component.displayNode).toBe(nodeMock); expect(component.displayNode).toBe(nodeMock);
expect(contentApiService.getNodeInfo).not.toHaveBeenCalled(); expect(contentApiService.getNodeInfo).not.toHaveBeenCalled();
})); });
it('should call getNodeInfo() when node is a shared file', async(() => { it('should call getNodeInfo() when node is a shared file', () => {
const response: any = { entry: { id: 'nodeId' } }; const response: any = { entry: { id: 'nodeId' } };
spyOn(contentApiService, 'getNodeInfo').and.returnValue(of(response)); spyOn(contentApiService, 'getNodeInfo').and.returnValue(of(response));
const nodeMock: any = { entry: { nodeId: 'nodeId' }, isLibrary: false }; const nodeMock: any = { entry: { nodeId: 'nodeId' }, isLibrary: false };
@ -117,9 +120,9 @@ describe('InfoDrawerComponent', () => {
expect(component.displayNode).toBe(response); expect(component.displayNode).toBe(response);
expect(contentApiService.getNodeInfo).toHaveBeenCalled(); expect(contentApiService.getNodeInfo).toHaveBeenCalled();
})); });
it('should call getNodeInfo() when node is a favorite file', async(() => { it('should call getNodeInfo() when node is a favorite file', () => {
const response: any = { entry: { id: 'nodeId' } }; const response: any = { entry: { id: 'nodeId' } };
spyOn(contentApiService, 'getNodeInfo').and.returnValue(of(response)); spyOn(contentApiService, 'getNodeInfo').and.returnValue(of(response));
const nodeMock: any = { const nodeMock: any = {
@ -133,9 +136,9 @@ describe('InfoDrawerComponent', () => {
expect(component.displayNode).toBe(response); expect(component.displayNode).toBe(response);
expect(contentApiService.getNodeInfo).toHaveBeenCalled(); expect(contentApiService.getNodeInfo).toHaveBeenCalled();
})); });
it('should call getNodeInfo() when node is a recent file', async(() => { it('should call getNodeInfo() when node is a recent file', () => {
const response: any = { entry: { id: 'nodeId' } }; const response: any = { entry: { id: 'nodeId' } };
spyOn(contentApiService, 'getNodeInfo').and.returnValue(of(response)); spyOn(contentApiService, 'getNodeInfo').and.returnValue(of(response));
const nodeMock: any = { const nodeMock: any = {
@ -152,7 +155,7 @@ describe('InfoDrawerComponent', () => {
expect(component.displayNode).toBe(response); expect(component.displayNode).toBe(response);
expect(contentApiService.getNodeInfo).toHaveBeenCalled(); expect(contentApiService.getNodeInfo).toHaveBeenCalled();
})); });
it('should dispatch close panel on Esc keyboard event', () => { it('should dispatch close panel on Esc keyboard event', () => {
const event = new KeyboardEvent('keydown', { const event = new KeyboardEvent('keydown', {

View File

@ -38,13 +38,13 @@ describe('ContextActionsDirective', () => {
directive = new ContextActionsDirective(storeMock); directive = new ContextActionsDirective(storeMock);
}); });
it('should not render context menu when `enabled` property is false', fakeAsync(() => { it('should not render context menu when `enabled` property is false', () => {
spyOn(directive, 'execute').and.stub(); spyOn(directive, 'execute').and.stub();
directive.enabled = false; directive.enabled = false;
directive.onContextMenuEvent(new MouseEvent('contextmenu')); directive.onContextMenuEvent(new MouseEvent('contextmenu'));
expect(directive.execute).not.toHaveBeenCalled(); expect(directive.execute).not.toHaveBeenCalled();
})); });
it('should call service to render context menu', fakeAsync(() => { it('should call service to render context menu', fakeAsync(() => {
const el = document.createElement('div'); const el = document.createElement('div');

View File

@ -28,7 +28,6 @@ import { AppTestingModule } from '../../testing/app-testing.module';
import { ContextMenuComponent } from './context-menu.component'; import { ContextMenuComponent } from './context-menu.component';
import { ContextMenuModule } from './context-menu.module'; import { ContextMenuModule } from './context-menu.module';
import { ContextMenuOverlayRef } from './context-menu-overlay'; import { ContextMenuOverlayRef } from './context-menu-overlay';
import { TranslateModule, TranslateLoader, TranslateFakeLoader } from '@ngx-translate/core';
import { ContentActionType } from '@alfresco/adf-extensions'; import { ContentActionType } from '@alfresco/adf-extensions';
import { of } from 'rxjs'; import { of } from 'rxjs';
@ -52,15 +51,8 @@ describe('ContextMenuComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [ContextMenuModule, AppTestingModule],
AppTestingModule,
ContextMenuModule,
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: TranslateFakeLoader }
})
],
providers: [ providers: [
AppExtensionService,
{ {
provide: ContextMenuOverlayRef, provide: ContextMenuOverlayRef,
useValue: { useValue: {
@ -103,11 +95,11 @@ describe('ContextMenuComponent', () => {
expect(contextMenuElements[0].querySelector('span').innerText).toBe(contextItem.title); expect(contextMenuElements[0].querySelector('span').innerText).toBe(contextItem.title);
})); }));
it('should run action with provided action id', fakeAsync(() => { it('should run action with provided action id', () => {
spyOn(extensionsService, 'runActionById'); spyOn(extensionsService, 'runActionById');
component.runAction(contextItem.actions.click); component.runAction(contextItem.actions.click);
expect(extensionsService.runActionById).toHaveBeenCalledWith(contextItem.actions.click); expect(extensionsService.runActionById).toHaveBeenCalledWith(contextItem.actions.click);
})); });
}); });

View File

@ -24,7 +24,7 @@
*/ */
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
import { TestBed, ComponentFixture, async, fakeAsync, tick } from '@angular/core/testing'; import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing';
import { UserPreferencesService, UploadService, AlfrescoApiService } from '@alfresco/adf-core'; import { UserPreferencesService, UploadService, AlfrescoApiService } from '@alfresco/adf-core';
import { ClosePreviewAction } from '@alfresco/aca-shared/store'; import { ClosePreviewAction } from '@alfresco/aca-shared/store';
import { PreviewComponent } from './preview.component'; import { PreviewComponent } from './preview.component';
@ -615,21 +615,23 @@ describe('PreviewComponent', () => {
expect(ids).toEqual(['node2', 'node1']); expect(ids).toEqual(['node2', 'node1']);
}); });
it('should return to parent folder on nodesDeleted event', async(() => { it('should return to parent folder on nodesDeleted event', async () => {
spyOn(component, 'navigateToFileLocation'); spyOn(component, 'navigateToFileLocation');
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
contentManagementService.nodesDeleted.next(); contentManagementService.nodesDeleted.next();
expect(component.navigateToFileLocation).toHaveBeenCalled(); expect(component.navigateToFileLocation).toHaveBeenCalled();
})); });
it('should return to parent folder on fileUploadDeleted event', async(() => { it('should return to parent folder on fileUploadDeleted event', async () => {
spyOn(component, 'navigateToFileLocation'); spyOn(component, 'navigateToFileLocation');
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
uploadService.fileUploadDeleted.next(); uploadService.fileUploadDeleted.next();
expect(component.navigateToFileLocation).toHaveBeenCalled(); expect(component.navigateToFileLocation).toHaveBeenCalled();
})); });
it('should emit nodeUpdated event on fileUploadComplete event', fakeAsync(() => { it('should emit nodeUpdated event on fileUploadComplete event', fakeAsync(() => {
spyOn(alfrescoApiService.nodeUpdated, 'next'); spyOn(alfrescoApiService.nodeUpdated, 'next');
@ -640,12 +642,13 @@ describe('PreviewComponent', () => {
expect(alfrescoApiService.nodeUpdated.next).toHaveBeenCalled(); expect(alfrescoApiService.nodeUpdated.next).toHaveBeenCalled();
})); }));
it('should return to parent folder when event emitted from extension', async(() => { it('should return to parent folder when event emitted from extension', async () => {
spyOn(component, 'navigateToFileLocation'); spyOn(component, 'navigateToFileLocation');
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
store.dispatch(new ClosePreviewAction()); store.dispatch(new ClosePreviewAction());
expect(component.navigateToFileLocation).toHaveBeenCalled(); expect(component.navigateToFileLocation).toHaveBeenCalled();
})); });
describe('Keyboard navigation', () => { describe('Keyboard navigation', () => {
beforeEach(() => { beforeEach(() => {

View File

@ -24,7 +24,7 @@
*/ */
import { SearchInputControlComponent } from './search-input-control.component'; import { SearchInputControlComponent } from './search-input-control.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
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';
@ -32,19 +32,17 @@ describe('SearchInputControlComponent', () => {
let fixture: ComponentFixture<SearchInputControlComponent>; let fixture: ComponentFixture<SearchInputControlComponent>;
let component: SearchInputControlComponent; let component: SearchInputControlComponent;
beforeEach(async(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [AppTestingModule], imports: [AppTestingModule],
declarations: [SearchInputControlComponent], declarations: [SearchInputControlComponent],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}) });
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(SearchInputControlComponent); fixture = TestBed.createComponent(SearchInputControlComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
}));
it('should emit submit event on searchSubmit', async () => { it('should emit submit event on searchSubmit', async () => {
const keyboardEvent = { target: { value: 'a' } }; const keyboardEvent = { target: { value: 'a' } };

View File

@ -24,15 +24,14 @@
*/ */
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed, async, ComponentFixture, fakeAsync, tick } from '@angular/core/testing'; import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing';
import { SearchInputComponent } from './search-input.component'; import { SearchInputComponent } from './search-input.component';
import { AppTestingModule } from '../../../testing/app-testing.module'; import { AppTestingModule } from '../../../testing/app-testing.module';
import { Actions, ofType } from '@ngrx/effects'; import { Actions, ofType } from '@ngrx/effects';
import { SearchByTermAction, SearchActionTypes } from '@alfresco/aca-shared/store'; import { SearchByTermAction, SearchActionTypes } from '@alfresco/aca-shared/store';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
import { SearchLibrariesQueryBuilderService } from '../search-libraries-results/search-libraries-query-builder.service';
import { ContentManagementService } from '../../../services/content-management.service'; import { ContentManagementService } from '../../../services/content-management.service';
import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
describe('SearchInputComponent', () => { describe('SearchInputComponent', () => {
let fixture: ComponentFixture<SearchInputComponent>; let fixture: ComponentFixture<SearchInputComponent>;
@ -40,22 +39,20 @@ describe('SearchInputComponent', () => {
let actions$: Actions; let actions$: Actions;
let content: ContentManagementService; let content: ContentManagementService;
beforeEach(async(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [AppTestingModule], imports: [AppTestingModule],
declarations: [SearchInputComponent], declarations: [SearchInputComponent],
schemas: [NO_ERRORS_SCHEMA], providers: [SearchQueryBuilderService],
providers: [SearchQueryBuilderService, SearchLibrariesQueryBuilderService] schemas: [NO_ERRORS_SCHEMA]
}) });
.compileComponents()
.then(() => {
actions$ = TestBed.inject(Actions); actions$ = TestBed.inject(Actions);
fixture = TestBed.createComponent(SearchInputComponent); fixture = TestBed.createComponent(SearchInputComponent);
content = TestBed.inject(ContentManagementService); content = TestBed.inject(ContentManagementService);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });
}));
it('should change flag on library400Error event', () => { it('should change flag on library400Error event', () => {
expect(component.has400LibraryError).toBe(false); expect(component.has400LibraryError).toBe(false);

View File

@ -24,7 +24,7 @@
*/ */
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed, async, ComponentFixture } from '@angular/core/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { SidenavComponent } from './sidenav.component'; import { SidenavComponent } from './sidenav.component';
import { AppTestingModule } from '../../testing/app-testing.module'; import { AppTestingModule } from '../../testing/app-testing.module';
import { AppExtensionService } from '@alfresco/aca-shared'; import { AppExtensionService } from '@alfresco/aca-shared';
@ -33,46 +33,44 @@ describe('SidenavComponent', () => {
let fixture: ComponentFixture<SidenavComponent>; let fixture: ComponentFixture<SidenavComponent>;
let component: SidenavComponent; let component: SidenavComponent;
let extensionService: AppExtensionService; let extensionService: AppExtensionService;
const navbarMock: any = [
beforeEach(() => {
TestBed.configureTestingModule({
imports: [AppTestingModule],
declarations: [SidenavComponent],
schemas: [NO_ERRORS_SCHEMA]
});
fixture = TestBed.createComponent(SidenavComponent);
component = fixture.componentInstance;
extensionService = TestBed.inject(AppExtensionService);
extensionService.navbar = [
{ {
id: 'route',
items: [ items: [
{ {
route: 'route' id: 'item-1',
icon: 'item',
route: 'route',
title: 'item-1'
} }
] ]
} }
]; ];
});
beforeEach(async(() => { it('should set the sidenav data', async () => {
TestBed.configureTestingModule({
imports: [AppTestingModule],
providers: [AppExtensionService],
declarations: [SidenavComponent],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(SidenavComponent);
component = fixture.componentInstance;
extensionService = TestBed.inject(AppExtensionService);
extensionService.navbar = navbarMock;
fixture.detectChanges(); fixture.detectChanges();
}); await fixture.whenStable();
}));
// TODO: fix with ADF 4.1 expect(component.groups.length).toBe(1);
it('should set the sidenav data', async(() => { expect(component.groups[0].items.length).toBe(1);
expect(component.groups).toEqual([ expect(component.groups[0].items[0]).toEqual({
{ id: 'item-1',
items: [ icon: 'item',
{ url: '/route',
route: 'route', route: 'route',
url: '/route' title: 'item-1'
} });
] });
} as any
]);
}));
}); });

View File

@ -24,9 +24,9 @@
*/ */
import { Component, ViewChild } from '@angular/core'; import { Component, ViewChild } from '@angular/core';
import { LibraryFavoriteDirective } from './library-favorite.directive'; import { LibraryEntity, LibraryFavoriteDirective } from './library-favorite.directive';
import { AlfrescoApiService, CoreModule } from '@alfresco/adf-core'; import { AlfrescoApiService, CoreModule } from '@alfresco/adf-core';
import { TestBed, async, ComponentFixture } from '@angular/core/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { AppTestingModule } from '../testing/app-testing.module'; import { AppTestingModule } from '../testing/app-testing.module';
@ -35,17 +35,17 @@ import { AppTestingModule } from '../testing/app-testing.module';
template: ` <button #favoriteLibrary="favoriteLibrary" [acaFavoriteLibrary]="selection">Favorite</button> ` template: ` <button #favoriteLibrary="favoriteLibrary" [acaFavoriteLibrary]="selection">Favorite</button> `
}) })
class TestComponent { class TestComponent {
@ViewChild('favoriteLibrary') @ViewChild('favoriteLibrary', { static: true })
directive: LibraryFavoriteDirective; directive: LibraryFavoriteDirective;
selection = null; selection: LibraryEntity = null;
} }
describe('LibraryFavoriteDirective', () => { describe('LibraryFavoriteDirective', () => {
let fixture: ComponentFixture<TestComponent>; let fixture: ComponentFixture<TestComponent>;
let api: AlfrescoApiService; let api: AlfrescoApiService;
let component: TestComponent; let component: TestComponent;
let selection: { entry: { guid: string; id: string } }; let selection: LibraryEntity;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -55,7 +55,8 @@ describe('LibraryFavoriteDirective', () => {
fixture = TestBed.createComponent(TestComponent); fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
api = TestBed.inject(AlfrescoApiService); api = TestBed.inject(AlfrescoApiService);
selection = { entry: { guid: 'guid', id: 'id' } }; selection = { entry: { guid: 'guid', id: 'id', title: 'Site', visibility: 'PUBLIC' }, isLibrary: true, isFavorite: false };
component.selection = selection;
}); });
it('should not check for favorite if no selection exists', () => { it('should not check for favorite if no selection exists', () => {
@ -65,59 +66,60 @@ describe('LibraryFavoriteDirective', () => {
expect(api.peopleApi.getFavoriteSite).not.toHaveBeenCalled(); expect(api.peopleApi.getFavoriteSite).not.toHaveBeenCalled();
}); });
it('should mark selection as favorite when getFavoriteSite returns successfully', async(() => { it('should mark selection as favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.resolve(null)); spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.resolve(null));
component.selection = selection;
fixture.detectChanges();
fixture.whenStable().then(() => { delete selection.isFavorite;
fixture.detectChanges();
await fixture.whenStable();
expect(api.peopleApi.getFavoriteSite).toHaveBeenCalled(); expect(api.peopleApi.getFavoriteSite).toHaveBeenCalled();
expect(component.directive.isFavorite()).toBe(true); expect(component.directive.isFavorite()).toBe(true);
}); });
}));
it('should mark selection not favorite when getFavoriteSite errors', async(() => { it('should mark selection not favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.reject()); spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.reject());
component.selection = selection;
fixture.detectChanges();
fixture.whenStable().then(() => { delete selection.isFavorite;
fixture.detectChanges();
await fixture.whenStable();
expect(api.peopleApi.getFavoriteSite).toHaveBeenCalled(); expect(api.peopleApi.getFavoriteSite).toHaveBeenCalled();
expect(component.directive.isFavorite()).toBe(false); expect(component.directive.isFavorite()).toBe(false);
}); });
}));
it('should call addFavorite() on click event when selection is not a favorite', async(() => { it('should call addFavorite() on click event when selection is not a favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.reject()); spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.reject());
spyOn(api.peopleApi, 'addFavorite').and.returnValue(Promise.resolve(null)); spyOn(api.peopleApi, 'addFavorite').and.returnValue(Promise.resolve(null));
component.selection = selection;
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
expect(component.directive.isFavorite()).toBeFalsy(); expect(component.directive.isFavorite()).toBeFalsy();
fixture.whenStable().then(() => {
fixture.nativeElement.querySelector('button').dispatchEvent(new MouseEvent('click')); fixture.nativeElement.querySelector('button').dispatchEvent(new MouseEvent('click'));
fixture.detectChanges(); fixture.detectChanges();
expect(api.peopleApi.addFavorite).toHaveBeenCalled(); expect(api.peopleApi.addFavorite).toHaveBeenCalled();
}); });
}));
it('should call removeFavoriteSite() on click event when selection is not a favorite', async(() => { it('should call removeFavoriteSite() on click event when selection is favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.resolve(null)); spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.resolve(null));
spyOn(api.favoritesApi, 'removeFavoriteSite').and.returnValue(Promise.resolve()); spyOn(api.favoritesApi, 'removeFavoriteSite').and.returnValue(Promise.resolve());
component.selection = selection;
selection.isFavorite = true;
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
expect(component.directive.isFavorite()).toBeFalsy(); expect(component.directive.isFavorite()).toBeTruthy();
fixture.whenStable().then(() => {
fixture.nativeElement.querySelector('button').dispatchEvent(new MouseEvent('click')); fixture.nativeElement.querySelector('button').dispatchEvent(new MouseEvent('click'));
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
expect(api.favoritesApi.removeFavoriteSite).toHaveBeenCalled(); expect(api.favoritesApi.removeFavoriteSite).toHaveBeenCalled();
}); });
}));
}); });

View File

@ -39,7 +39,7 @@ export interface LibraryEntity {
}) })
export class LibraryFavoriteDirective implements OnChanges { export class LibraryFavoriteDirective implements OnChanges {
@Input('acaFavoriteLibrary') @Input('acaFavoriteLibrary')
library: any = null; library: LibraryEntity = null;
@Output() toggle = new EventEmitter<any>(); @Output() toggle = new EventEmitter<any>();
// tslint:disable-next-line: no-output-native // tslint:disable-next-line: no-output-native
@ -49,7 +49,19 @@ export class LibraryFavoriteDirective implements OnChanges {
@HostListener('click') @HostListener('click')
onClick() { onClick() {
this.toggleFavorite(); const guid = this.targetLibrary.entry.guid;
if (this.targetLibrary.isFavorite) {
this.removeFavorite(guid);
} else {
this.addFavorite({
target: {
site: {
guid
}
}
});
}
} }
constructor(private alfrescoApiService: AlfrescoApiService) {} constructor(private alfrescoApiService: AlfrescoApiService) {}
@ -64,44 +76,23 @@ export class LibraryFavoriteDirective implements OnChanges {
this.markFavoriteLibrary(changes.library.currentValue); this.markFavoriteLibrary(changes.library.currentValue);
} }
isFavorite() { isFavorite(): boolean {
return this.targetLibrary && this.targetLibrary.isFavorite; return this.targetLibrary && this.targetLibrary.isFavorite;
} }
toggleFavorite() {
if (this.targetLibrary.isFavorite) {
this.removeFavorite(this.targetLibrary.entry.guid);
} else {
const favoriteBody = this.createFavoriteBody(this.targetLibrary);
this.addFavorite(favoriteBody);
}
}
private async markFavoriteLibrary(library: LibraryEntity) { private async markFavoriteLibrary(library: LibraryEntity) {
if (this.targetLibrary.isFavorite === undefined) { if (this.targetLibrary.isFavorite === undefined) {
await this.getFavoriteSite(library); try {
await this.alfrescoApiService.peopleApi.getFavoriteSite('-me-', library.entry.id);
this.targetLibrary.isFavorite = true;
} catch {
this.targetLibrary.isFavorite = false;
}
} else { } else {
this.targetLibrary = library; this.targetLibrary = library;
} }
} }
private getFavoriteSite(library: LibraryEntity) {
this.alfrescoApiService.peopleApi
.getFavoriteSite('-me-', library.entry.id)
.then(() => (this.targetLibrary.isFavorite = true))
.catch(() => (this.targetLibrary.isFavorite = false));
}
private createFavoriteBody(library: LibraryEntity): FavoriteBody {
return {
target: {
site: {
guid: library.entry.guid
}
}
};
}
private addFavorite(favoriteBody: FavoriteBody) { private addFavorite(favoriteBody: FavoriteBody) {
this.alfrescoApiService.peopleApi this.alfrescoApiService.peopleApi
.addFavorite('-me-', favoriteBody) .addFavorite('-me-', favoriteBody)

View File

@ -116,13 +116,10 @@ describe('NodeActionsService', () => {
}); });
describe('ContentNodeSelector configuration', () => { describe('ContentNodeSelector configuration', () => {
it('should validate selection when allowableOperation has `create`', async(() => { it('should validate selection when allowableOperation has `create`', () => {
spyOn(dialog, 'open'); spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }]; const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]); service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({ const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
name: 'some-folder-template', name: 'some-folder-template',
@ -133,15 +130,12 @@ describe('NodeActionsService', () => {
}); });
expect(isSelectionValid).toBe(true); expect(isSelectionValid).toBe(true);
})); });
it('should invalidate selection when allowableOperation does not have `create`', async(() => { it('should invalidate selection when allowableOperation does not have `create`', () => {
spyOn(dialog, 'open'); spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }]; const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]); service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({ const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
name: 'some-folder-template', name: 'some-folder-template',
@ -152,15 +146,12 @@ describe('NodeActionsService', () => {
}); });
expect(isSelectionValid).toBe(false); expect(isSelectionValid).toBe(false);
})); });
it('should invalidate selection if isSite', async(() => { it('should invalidate selection if isSite', () => {
spyOn(dialog, 'open'); spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }]; const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]); service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({ const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
name: 'some-folder-template', name: 'some-folder-template',
@ -172,15 +163,12 @@ describe('NodeActionsService', () => {
}); });
expect(isSelectionValid).toBe(false); expect(isSelectionValid).toBe(false);
})); });
it('should validate selection if not a Site', async(() => { it('should validate selection if not a Site', () => {
spyOn(dialog, 'open'); spyOn(dialog, 'open');
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }]; const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>();
service.getContentNodeSelection('', contentEntities as NodeEntry[]); service.getContentNodeSelection('', contentEntities as NodeEntry[]);
subject.next([new TestNode().entry]);
const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({ const isSelectionValid = dialog.open['calls'].argsFor(0)[1].data.isSelectionValid({
name: 'some-folder-template', name: 'some-folder-template',
@ -192,7 +180,7 @@ describe('NodeActionsService', () => {
}); });
expect(isSelectionValid).toBe(true); expect(isSelectionValid).toBe(true);
})); });
}); });
describe('doBatchOperation', () => { describe('doBatchOperation', () => {
@ -244,7 +232,7 @@ 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", () => {
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }]; const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>(); const subject = new Subject<MinimalNodeEntryEntity[]>();
@ -256,7 +244,7 @@ describe('NodeActionsService', () => {
expect(spyOnSuccess).toHaveBeenCalled(); expect(spyOnSuccess).toHaveBeenCalled();
expect(spyOnError).not.toHaveBeenCalledWith(badRequestError); expect(spyOnError).not.toHaveBeenCalledWith(badRequestError);
})); });
}); });
describe('getEntryParentId', () => { describe('getEntryParentId', () => {
@ -580,8 +568,6 @@ describe('NodeActionsService', () => {
copyObservable = service.copyNodeAction(folderToCopy.entry, folderParentAndDestination.entry.id); copyObservable = service.copyNodeAction(folderToCopy.entry, folderParentAndDestination.entry.id);
}); });
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 = [
{ {