From b2e6de71dbfdcc82e26e49c7a383221cdf8ae789 Mon Sep 17 00:00:00 2001 From: Swopnil Dangol Date: Mon, 11 Aug 2025 13:49:00 +0100 Subject: [PATCH] Exported the parse function from the parser --- packages/parser/src/index.ts | 1 + packages/parser/tests/unit/parser.test.ts | 136 ++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 packages/parser/tests/unit/parser.test.ts diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts index d932877eba..8697513118 100644 --- a/packages/parser/src/index.ts +++ b/packages/parser/src/index.ts @@ -1,2 +1,3 @@ export { ParseError } from './errors.js'; +export { parse } from './parser.js'; export { parser } from './parserDecorator.js'; diff --git a/packages/parser/tests/unit/parser.test.ts b/packages/parser/tests/unit/parser.test.ts new file mode 100644 index 0000000000..374e41c245 --- /dev/null +++ b/packages/parser/tests/unit/parser.test.ts @@ -0,0 +1,136 @@ +import { describe, expect, it } from 'vitest'; +import { z } from 'zod'; +import { EventBridgeEnvelope } from '../../src/envelopes/eventbridge.js'; +import { SqsEnvelope } from '../../src/envelopes/sqs.js'; +import { ParseError } from '../../src/errors.js'; +import { parse } from '../../src/parser.js'; +import type { EventBridgeEvent, SqsEvent } from '../../src/types/index.js'; +import { getTestEvent } from './helpers/utils.js'; + +describe('Parser', () => { + const schema = z + .object({ + name: z.string(), + age: z.number(), + }) + .strict(); + const baseSqsEvent = getTestEvent({ + eventsPath: 'sqs', + filename: 'base', + }); + const baseEventBridgeEvent = getTestEvent({ + eventsPath: 'eventbridge', + filename: 'base', + }); + const JSONPayload = { name: 'John', age: 18 }; + + it('parses an event with schema and envelope', async () => { + // Prepare + const event = structuredClone(baseSqsEvent); + event.Records[1].body = 'bar'; + + // Act + + const result = parse(event, SqsEnvelope, z.string()); + + // Assess + expect(result).toStrictEqual(['Test message.', 'bar']); + }); + + it('throws when envelope does not match', async () => { + // Prepare + const event = structuredClone(baseEventBridgeEvent); + + // Act & Assess + expect(() => parse(event, SqsEnvelope, z.string())).toThrow(); + }); + + it('throws when schema does not match', async () => { + // Prepare + const event = structuredClone(baseSqsEvent); + // @ts-expect-error - setting an invalid body + event.Records[1].body = undefined; + + // Act & Assess + expect(() => parse(event, SqsEnvelope, z.string())).toThrow(); + }); + + it('parses the event successfully', async () => { + // Prepare + const event = 42; + + // Act + const result = parse(event, undefined, z.number()); + + // Assess + expect(result).toEqual(event); + }); + + it('throws when the event does not match the schema', async () => { + // Prepare + const event = structuredClone(JSONPayload); + + // Act & Assess + expect(() => parse(event, undefined, z.number())).toThrow(); + }); + + it('returns the payload when using safeParse', async () => { + // Prepare + const event = structuredClone(JSONPayload); + + // Act + const result = parse(event, undefined, schema, true); + + // Assess + expect(result).toEqual({ + success: true, + data: event, + }); + }); + + it('returns the error when using safeParse and the payload is invalid', async () => { + // Prepare + const event = structuredClone(JSONPayload); + + // Act + const result = parse(event, undefined, z.string(), true); + + // Assess + expect(result).toEqual({ + success: false, + error: expect.any(ParseError), + originalEvent: event, + }); + }); + + it('returns the payload when using safeParse with envelope', async () => { + // Prepare + const detail = structuredClone(JSONPayload); + const event = structuredClone(baseEventBridgeEvent); + event.detail = detail; + + // Act + const result = parse(event, EventBridgeEnvelope, schema, true); + + // Assess + expect(result).toStrictEqual({ + success: true, + data: detail, + }); + }); + + it('returns an error when using safeParse with envelope and the payload is invalid', async () => { + // Prepare + const event = structuredClone(baseEventBridgeEvent); + + // Act + const result = parse(event, EventBridgeEnvelope, z.string(), true); + + // Assess + expect(result).toStrictEqual({ + success: false, + error: expect.any(ParseError), + originalEvent: event, + }); + }); +});