/*! * @license * Copyright Squiz Australia Pty Ltd. All Rights Reserved. */ import { DynamoDBClient, DynamoDBClientConfig, GetItemCommandOutput, PutItemCommandOutput, ScanCommandOutput, } from '@aws-sdk/client-dynamodb'; import { initIocContainer, iocContainer } from '../../../../mocks/mockIoc'; import { ENTITY_TYPES } from '../../constants/Repository.constants'; import { createMockClientGetResponse, createMockClientPutResponse, createMockClientScanResponse, } from '../../core/dynamoClient.mock'; import { createMockCreateJobManifestRequest, createMockJobManifest, createMockJobManifestDto, createMockJobManifestDtos, createMockJobManifestRecord, JobManifest, } from '../../manifest'; import { JobManifestService } from './JobManifestService'; initIocContainer(); // Mock DynamoDB Client const mockOptions = {} as DynamoDBClientConfig; const mockClient = new DynamoDBClient(mockOptions); const mockSend = jest.fn(); mockClient.send = mockSend; // Inject the JobManifestRepository property (of JobManifestService) with a mocked client iocContainer.rebind(DynamoDBClient).toConstantValue(mockClient); let jobManifestService: JobManifestService; describe('JobManifestService', (): void => { beforeAll((): void => { jobManifestService = iocContainer.get(JobManifestService); }); describe(`createJobManifest`, (): void => { it(`should return a response for createJob`, async (): Promise => { const newJobManifestToCreate = createMockCreateJobManifestRequest(); const mockReponse = createMockClientPutResponse({ Attributes: createMockJobManifestDto({ pk: ENTITY_TYPES.manifest, sk: newJobManifestToCreate.name, }), }); mockSend.mockImplementationOnce((): PutItemCommandOutput => mockReponse); const response = await jobManifestService.createJobManifest(newJobManifestToCreate); expect(mockSend).toBeCalledTimes(1); expect(response).toStrictEqual({ ...newJobManifestToCreate, type: ENTITY_TYPES.manifest, }); }); }); describe(`findJobManifest`, (): void => { it(`should return job manifest`, async (): Promise => { const mockJobManifestItem = createMockJobManifestDto(); mockSend.mockImplementationOnce( (): GetItemCommandOutput => createMockClientGetResponse({ Item: mockJobManifestItem, }), ); const response = await jobManifestService.findJobManifest( mockJobManifestItem.name.S as string, mockJobManifestItem.version.S as string, ); expect(response).toStrictEqual({ concurrency: parseInt(mockJobManifestItem.concurrency.N as string), entryFile: mockJobManifestItem.entryFile.S as string, entryFunction: JSON.parse(mockJobManifestItem.entryFunction.S as string), name: mockJobManifestItem.name.S as string, version: mockJobManifestItem.version.S as string, timeoutSeconds: parseInt(mockJobManifestItem.timeoutSeconds.N as string), image: mockJobManifestItem.image.S as string, autoRetry: false, type: `manifest`, } as JobManifest); expect(mockSend).toBeCalledTimes(1); }); it(`should return null if job manifest does not exist`, async (): Promise => { mockSend.mockImplementationOnce( (): ScanCommandOutput => createMockClientScanResponse({ Items: [], }), ); const response = await jobManifestService.findJobManifest(`null`, `null`); expect(mockSend).toBeCalledTimes(1); expect(response).toBe(null); }); }); describe(`listAllJobManifests`, (): void => { it(`should return an empty list`, async (): Promise => { mockSend.mockImplementationOnce((): ScanCommandOutput => createMockClientScanResponse()); const response = await jobManifestService.listAllJobManifests(); expect(mockSend).toBeCalled(); expect(response).toStrictEqual([]); }); it(`should return a list of existing job manifests`, async (): Promise => { const mockManifestItems = createMockJobManifestDtos(); mockSend.mockImplementationOnce( (): ScanCommandOutput => createMockClientScanResponse({ Items: mockManifestItems, LastEvaluatedKey: undefined, }), ); const response = await jobManifestService.listAllJobManifests(); expect(mockSend).toBeCalledTimes(1); expect(response).toHaveLength(mockManifestItems.length); }); it(`should paginate results to return a list of existing job manifests`, async (): Promise => { const mockManifestItemsPage1 = createMockJobManifestDtos(); const mockManifestItemsPage2 = createMockJobManifestDtos(); mockSend .mockImplementationOnce( (): ScanCommandOutput => createMockClientScanResponse({ Items: mockManifestItemsPage1, LastEvaluatedKey: mockManifestItemsPage1.slice(-1)[0], }), ) .mockImplementationOnce( (): ScanCommandOutput => createMockClientScanResponse({ Items: mockManifestItemsPage2, LastEvaluatedKey: undefined, }), ); const response = await jobManifestService.listAllJobManifests(); expect(mockSend).toBeCalledTimes(2); expect(response).toHaveLength(mockManifestItemsPage1.length + mockManifestItemsPage2.length); }); }); describe(`updateJobManifest`, (): void => { it(`should update a job manifest record`, async (): Promise => { const jobManifestToUpdate = createMockJobManifest({ name: `name`, }); const updatedJobManifest: JobManifest = { ...jobManifestToUpdate, concurrency: 10, timeoutSeconds: 100, }; const updatedJobManifestRecord = createMockJobManifestRecord({ sk: `${updatedJobManifest.name}-${updatedJobManifest.version}`, name: updatedJobManifest.name, version: updatedJobManifest.version, entryFile: updatedJobManifest.entryFile, entryFunction: updatedJobManifest.entryFunction, concurrency: updatedJobManifest.concurrency, timeoutSeconds: updatedJobManifest.timeoutSeconds, }); const updatedJobManifestRecordDto = createMockJobManifestDto({ ...updatedJobManifestRecord, }); const putResponse = createMockClientPutResponse({ Attributes: { ...updatedJobManifestRecordDto }, }); mockSend.mockImplementation((): PutItemCommandOutput => putResponse); const response = await jobManifestService.updateJobManifest( jobManifestToUpdate.name, jobManifestToUpdate.version, updatedJobManifestRecord, ); expect(response).toStrictEqual(updatedJobManifest); expect(mockSend).toBeCalledTimes(1); }); }); });