/*! * @license * Copyright 2019 Alfresco Software, Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { AlfrescoApiService, SitesService } from '../services'; import { LibraryMembershipDirective } from './library-membership.directive'; import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core'; import { of, throwError, Subject } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; import { DirectiveModule } from './directive.module'; import { CoreModule } from '../core.module'; import { CoreTestingModule } from '../testing/core.testing.module'; describe('LibraryMembershipDirective', () => { let alfrescoApiService: AlfrescoApiService; let directive: LibraryMembershipDirective; let sitesService: SitesService; let addMembershipSpy: jasmine.Spy; let getMembershipSpy: jasmine.Spy; let deleteMembershipSpy: jasmine.Spy; let mockSupportedVersion = false; let testSiteEntry: any; let requestedMembershipResponse: any; beforeEach(() => { TestBed.configureTestingModule({ imports: [ TranslateModule.forRoot(), DirectiveModule, CoreModule.forRoot(), CoreTestingModule ], schemas: [NO_ERRORS_SCHEMA] }); testSiteEntry = { id: 'id-1', guid: 'site-1', title: 'aa t m', visibility: 'MODERATED' }; requestedMembershipResponse = { id: testSiteEntry.id, createdAt: '2018-11-14', site: testSiteEntry }; alfrescoApiService = TestBed.inject(AlfrescoApiService); sitesService = TestBed.inject(SitesService); directive = new LibraryMembershipDirective(alfrescoApiService, sitesService, { ecmProductInfo$: new Subject(), isVersionSupported: () => mockSupportedVersion } as any); }); describe('markMembershipRequest', () => { beforeEach(() => { getMembershipSpy = spyOn(directive['sitesApi'], 'getSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse })); }); it('should not check membership requests if no entry is selected', fakeAsync(() => { const selection = {}; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); expect(getMembershipSpy).not.toHaveBeenCalled(); })); it('should check if a membership request exists for the selected library', fakeAsync(() => { const selection = { entry: {} }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); expect(getMembershipSpy.calls.count()).toBe(1); })); it('should remember when a membership request exists for selected library', fakeAsync(() => { const selection = { entry: testSiteEntry }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); expect(directive.targetSite.joinRequested).toBe(true); })); it('should remember when a membership request is not found for selected library', fakeAsync(() => { getMembershipSpy.and.returnValue(Promise.reject()); const selection = { entry: testSiteEntry }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); expect(directive.targetSite.joinRequested).toBe(false); })); }); describe('toggleMembershipRequest', () => { beforeEach(() => { mockSupportedVersion = false; getMembershipSpy = spyOn(directive['sitesApi'], 'getSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse })); addMembershipSpy = spyOn(directive['sitesApi'], 'createSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse })); deleteMembershipSpy = spyOn(directive['sitesApi'], 'deleteSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({})); }); it('should do nothing if there is no selected library ', fakeAsync(() => { const selection = {}; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); directive.toggleMembershipRequest(); tick(); expect(addMembershipSpy).not.toHaveBeenCalled(); expect(deleteMembershipSpy).not.toHaveBeenCalled(); })); it('should delete membership request if there is one', fakeAsync(() => { const selection = { entry: testSiteEntry }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); directive.toggleMembershipRequest(); tick(); expect(deleteMembershipSpy).toHaveBeenCalled(); })); it('should call API to make a membership request if there is none', fakeAsync(() => { const selection = { entry: { id: 'no-membership-requested' } }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); directive.toggleMembershipRequest(); tick(); expect(addMembershipSpy).toHaveBeenCalledWith('-me-', { id: 'no-membership-requested' }); expect(deleteMembershipSpy).not.toHaveBeenCalled(); })); it("should add 'workspace' to send appropriate email", fakeAsync(() => { mockSupportedVersion = true; const selection = { entry: { id: 'no-membership-requested' } }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); directive.toggleMembershipRequest(); tick(); expect(addMembershipSpy).toHaveBeenCalledWith('-me-', { id: 'no-membership-requested', client: 'workspace' }); expect(deleteMembershipSpy).not.toHaveBeenCalled(); })); it('should call API to add user to library if admin user', fakeAsync(() => { const createSiteMembershipSpy = spyOn(sitesService, 'createSiteMembership').and.returnValue(of({} as any)); const selection = { entry: { id: 'no-membership-requested' } }; const selectionChange = new SimpleChange(null, selection, true); directive.isAdmin = true; directive.ngOnChanges({ selection: selectionChange }); tick(); directive.toggleMembershipRequest(); tick(); expect(createSiteMembershipSpy).toHaveBeenCalled(); expect(addMembershipSpy).not.toHaveBeenCalled(); })); it('should emit error when the request to join a library fails', fakeAsync(() => { spyOn(directive.error, 'emit'); addMembershipSpy.and.returnValue(throwError('err')); const selection = { entry: { id: 'no-membership-requested' } }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); directive.toggleMembershipRequest(); tick(); expect(directive.error.emit).toHaveBeenCalled(); })); it('should emit specific error message on invalid email address server error', fakeAsync(() => { const emitErrorSpy = spyOn(directive.error, 'emit'); const selection = { entry: { id: 'no-membership-requested' } }; const change = new SimpleChange(null, selection, true); directive.ngOnChanges({ selection: change }); tick(); const testData = [ { fixture: 'Failed to resolve sender mail address', expected: 'APP.MESSAGES.ERRORS.INVALID_SENDER_EMAIL' }, { fixture: 'All recipients for the mail action were invalid', expected: 'APP.MESSAGES.ERRORS.INVALID_RECEIVER_EMAIL' } ]; testData.forEach((data) => { addMembershipSpy.and.returnValue(throwError({ message: data.fixture })); emitErrorSpy.calls.reset(); directive.toggleMembershipRequest(); tick(); expect(emitErrorSpy).toHaveBeenCalledWith({ error: { message: data.fixture }, i18nKey: data.expected }); }); })); }); });