import { Injectable } from '@angular/core'; import { GCMockModule } from '@core/mocks/gc-module.mock'; import { APIExternalAPI } from '@core/typings/api/external-api.typing'; import { User, UserTypes } from '@core/typings/client-user.typing'; import { UserService } from '@features/users/user.service'; import { BeforeEach, Spec, TestCase } from '@yourcause/test-decorators'; import { DescribeAngularService } from '@yourcause/test-decorators/angular'; import { expect, spy } from 'chai'; import { take } from 'rxjs'; import { ExternalAPIService } from './external-api.service'; import { ReadWriteTracker, ServiceType } from './outbound-api.typing'; @Injectable({ providedIn: 'root' }) @DescribeAngularService(ExternalAPIService, { imports: [ GCMockModule ] }) export class ExternalAPIServiceSpec implements Spec { constructor ( private userService: UserService ) { } user: Partial = { firstName: 'test', lastName: 'test', email: 'test@test.com' }; integrations: APIExternalAPI.ExternalAPIConfiguration[] = [ { externalApiRequestGuid: '0', authHeaderKey: '', authHeaderName: '', authenticationScheme: APIExternalAPI.ExternalAPIAuthScheme.Unauthorized, httpMethod: '', id: 0, mergeModelType: APIExternalAPI.ExternalAPIMergeModelType.Applicant, name: '', password: '', postBodyTemplate: '', responseFields: [], headers: [], url: '', description: '', username: '', oAuthClientId: '', oAuthClientSecret: '', oAuthScope: '', oAuthTokenUrl: '', createdBy: { firstName: 'Tina', lastName: 'Conway', email: 'email@email.com', userType: UserTypes.MANAGER, impersonatedBy: 'impersonator' }, createdDate: '', updatedBy: { firstName: 'Tina', lastName: 'Conway', email: 'email@email.com', userType: UserTypes.MANAGER, impersonatedBy: 'impersonator' }, updatedDate: '' } ]; mockResponse = { test: 'test' }; @BeforeEach() mockUser ( service: ExternalAPIService ) { service['set']('integrations', this.integrations); // TODO: remove after replacing mock data with api endpoint this.userService['set']('user', this.user as User); } @TestCase('should be able to prep a request') async testShouldBeAbleToPrepRequest ( service: ExternalAPIService ) { // property from the mock prop const mockProp = 'test'; const mockValue = 'test'; const mockValue2 = 'test2'; const mockSubProp = 'test'; const mockSubProp2 = 'test2'; /* mocking a response of: { test: { test: 'test', test2: 'test2' } } */ const eyeSpy = spy(( i: string, a: any ) => Promise.resolve({ response: { [mockProp]: { [mockSubProp]: mockValue, [mockSubProp2]: mockValue2 } }, responseCode: 200 }) ); // mocking the actual service execution service['externalApiResources'].executeExternalAPIIntegrationForManager = eyeSpy; // expect that there are no previously set up requests expect(service.get('requests')).to.be.undefined; // expect the mapped response to equal the mocked value using a nested selector: test.test const response = service.getIntegrationRequest( this.integrations[0].externalApiRequestGuid, '', `${mockProp}.${mockSubProp}` ) .pipe(take(1)) .toPromise(); // expect the mapped response to equal the second mocked value // and only to have been called once const response2 = service.getIntegrationRequest( this.integrations[0].externalApiRequestGuid, '', `${mockProp}.${mockSubProp2}` ) .pipe(take(1)) .toPromise(); service.setUpIntegrationRequest( this.integrations[0].externalApiRequestGuid, '', null ); expect(await response).to.equal(mockValue); expect(await response2).to.equal(mockValue2); expect(eyeSpy).to.have.been.called.once; } @TestCase('should be able to get service details') getServiceDetails (service: ExternalAPIService) { const paymentDetails = service.getServiceDetails(ServiceType.Payments); expect(paymentDetails.supportsWrite).to.be.true; const batchDetails = service.getServiceDetails(ServiceType.Batches); expect(batchDetails.supportsWrite).to.be.false; } @TestCase('should be able to get current services') getCurrentServices (service: ExternalAPIService) { const services = service.getCurrentServices(); expect(services.length).to.be.equal(service.currentlyAllowedServices.length); } @TestCase('should be able to adapt services for save') adaptServicesForSave (service: ExternalAPIService) { const servicesMap: Partial> = { [ServiceType.Payments]: { read: true, write: false }, [ServiceType.Batches]: { read: false, write: true } }; const mapped = service.adaptServicesForSave(servicesMap); expect(mapped.length).to.be.equal(2); const hasPaymentService = mapped.some((item) => { return item.clientAPIServiceTypeId === ServiceType.Payments && item.canRead && !item.canWrite; }); expect(hasPaymentService).to.be.true; const hasBatchService = mapped.some((item) => { return item.clientAPIServiceTypeId === ServiceType.Batches && !item.canRead && item.canWrite; }); expect(hasBatchService).to.be.true; } }