From 0c5a1b9a7c64db60a8ea6adabfac5ff8c2b1ce70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Barthelet?= Date: Tue, 1 Nov 2022 14:47:19 +0100 Subject: [PATCH 1/4] Enrich put results with initial command payload --- src/Bus.ts | 15 ++++++++++----- src/Event.ts | 7 +++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Bus.ts b/src/Bus.ts index ddc85e1..00de18a 100644 --- a/src/Bus.ts +++ b/src/Bus.ts @@ -1,6 +1,5 @@ import type { EventBridgeClient, - PutEventsResponse, PutEventsRequestEntry, PutEventsResultEntry, } from '@aws-sdk/client-eventbridge'; @@ -29,7 +28,10 @@ export class Bus { this._eventBridge = EventBridge; } - async put(events: PutEventsRequestEntry[]): Promise { + async put(events: PutEventsRequestEntry[]): Promise<{ + FailedEntryCount?: number; + Entries?: (PutEventsRequestEntry & PutEventsResultEntry)[]; + }> { const entries = events.map((entry) => Object.assign({}, { ...entry }, { EventBusName: this._name }), ); @@ -43,15 +45,18 @@ export class Bus { ); return results.reduce<{ - Entries: PutEventsResultEntry[]; + Entries: (PutEventsRequestEntry & PutEventsResultEntry)[]; FailedEntryCount: number; }>( - (returnValue, result) => { + (returnValue, result, index) => { if (result.FailedEntryCount) { returnValue.FailedEntryCount += result.FailedEntryCount; } if (result.Entries) { - returnValue.Entries.push(...result.Entries); + const enrichedResult = result.Entries.map((entry) => + Object.assign({}, { ...entry }, { ...entries[index] }), + ); + returnValue.Entries.push(...enrichedResult); } return returnValue; diff --git a/src/Event.ts b/src/Event.ts index dc97228..00d72c5 100644 --- a/src/Event.ts +++ b/src/Event.ts @@ -1,7 +1,7 @@ import Ajv from 'ajv'; import type { PutEventsRequestEntry, - PutEventsResponse, + PutEventsResultEntry, } from '@aws-sdk/client-eventbridge'; import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import type { EventBridgeEvent } from 'aws-lambda'; @@ -91,7 +91,10 @@ export class Event { }; } - async publish(event: FromSchema): Promise { + async publish(event: FromSchema): Promise<{ + FailedEntryCount?: number; + Entries?: (PutEventsRequestEntry & PutEventsResultEntry)[]; + }> { return this._bus.put([this.create(event)]); } } From f8373008f0ecc95f24288144c46a35946a05fd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Barthelet?= Date: Tue, 1 Nov 2022 14:48:55 +0100 Subject: [PATCH 2/4] Add test for enriched return feature --- src/Bus.test.ts | 70 ++++++++++++++++++++++++++++++++++++++++++++++- src/Event.test.ts | 19 +++++++++---- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/src/Bus.test.ts b/src/Bus.test.ts index 9d33adb..ae79473 100644 --- a/src/Bus.test.ts +++ b/src/Bus.test.ts @@ -1,4 +1,9 @@ -import { chunkEntries, computeEventSize } from './Bus'; +import { Bus, chunkEntries, computeEventSize } from './Bus'; +import { mockClient } from 'aws-sdk-client-mock'; +import { + EventBridgeClient, + PutEventsCommand, +} from '@aws-sdk/client-eventbridge'; const smallEntry = { Detail: 'small'.repeat(Math.round(25000 / 5)), // ~ 25Kb @@ -6,6 +11,12 @@ const smallEntry = { const bigEntry = { Detail: 'big'.repeat(Math.round(100000 / 3)), // ~ 100Kb }; +const failEntry = { + Detail: 'fail', +}; +const successEntry = { + Detail: 'success', +}; const cases = [ { @@ -60,6 +71,63 @@ const cases = [ ]; describe('Bus', () => { + describe('#put', () => { + const eventBridgeClientMock = mockClient(EventBridgeClient); + const bus = new Bus({ + name: 'testBus', + // @ts-expect-error Mocking library mocked client is not type compatible with actual client + EventBridge: eventBridgeClientMock, + }); + beforeEach(() => { + eventBridgeClientMock.reset(); + }); + it('should return events command payload with results', () => { + const testCase = [ + failEntry, + successEntry, + successEntry, + failEntry, + successEntry, + failEntry, + successEntry, + ]; + eventBridgeClientMock.on(PutEventsCommand).resolves({ + FailedEntryCount: 3, + Entries: [ + { ErrorCode: '12', ErrorMessage: 'There was an error' }, + { EventId: '97a200f1-6919-4619-ac2f-e0026ebb15b7' }, + { EventId: 'e4c40e6a-1fc0-4f5a-82b3-c6c284d772ca' }, + { ErrorCode: '13', ErrorMessage: 'There was an error' }, + { EventId: '1cdf5682-6f5c-4c21-b922-f83d06447952' }, + { ErrorCode: '14', ErrorMessage: 'There was an error' }, + { EventId: '9039f372-d810-474b-9741-b369394cefef' }, + ], + }); + const failEntryResultBuilder = (code: string) => ({ + ErrorCode: code, + ErrorMessage: 'There was an error', + Detail: 'fail', + EventBusName: 'testBus', + }); + const successEntryResultBuilder = (id: string) => ({ + EventId: id, + Detail: 'success', + EventBusName: 'testBus', + }); + expect(bus.put(testCase)).resolves.toEqual({ + FailedEntryCount: 3, + Entries: [ + failEntryResultBuilder('12'), + successEntryResultBuilder('97a200f1-6919-4619-ac2f-e0026ebb15b7'), + successEntryResultBuilder('e4c40e6a-1fc0-4f5a-82b3-c6c284d772ca'), + failEntryResultBuilder('13'), + successEntryResultBuilder('1cdf5682-6f5c-4c21-b922-f83d06447952'), + failEntryResultBuilder('14'), + successEntryResultBuilder('9039f372-d810-474b-9741-b369394cefef'), + ], + }); + }); + }); describe('#computeEventSize', () => { it('should compute event size', () => { expect( diff --git a/src/Event.test.ts b/src/Event.test.ts index c75a8b9..3f35e2a 100644 --- a/src/Event.test.ts +++ b/src/Event.test.ts @@ -54,12 +54,19 @@ describe('Event', () => { }); it('should allow publishing an event', async () => { - expect( - await myEvent.publish({ - attribute: 'hello', - numberAttribute: 12, - }), - ).toHaveProperty('Entries', [{ EventId: '123456' }]); + const eventPayload = { + attribute: 'hello', + numberAttribute: 12, + }; + expect(await myEvent.publish(eventPayload)).toHaveProperty('Entries', [ + { + EventId: '123456', + DetailType: 'myEvent', + Detail: JSON.stringify(eventPayload), + EventBusName: 'test', + Source: 'source', + }, + ]); }); it('should fail with the use of validationMiddleware on wrong event', () => { From 053d1749f643b804c72ad8ef15f9e9e65824af14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Barthelet?= Date: Tue, 1 Nov 2022 14:49:10 +0100 Subject: [PATCH 3/4] Fix type in test case --- src/Bus.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bus.test.ts b/src/Bus.test.ts index ae79473..55f4e8a 100644 --- a/src/Bus.test.ts +++ b/src/Bus.test.ts @@ -133,9 +133,9 @@ describe('Bus', () => { expect( computeEventSize({ DetailType: 'myType', - Detail: JSON.stringify({ property: 'vaalue' }), + Detail: JSON.stringify({ property: 'value' }), }), - ).toBe(27); + ).toBe(26); }); }); From cb2374c541e5303512900757975bb8c8aca5dec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Barthelet?= Date: Tue, 1 Nov 2022 14:49:30 +0100 Subject: [PATCH 4/4] Update aws-sdk-client-mock to latest --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 72847bb..2b09b98 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@typescript-eslint/eslint-plugin": "^5.11.0", "@typescript-eslint/parser": "^5.11.0", "aws-lambda-mock-context": "^3.2.1", - "aws-sdk-client-mock": "^0.5.6", + "aws-sdk-client-mock": "^2.0.0", "eslint": "^8.8.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-jest": "^26.1.0",