1- import { generateMock } from '@anatine/zod-mock' ;
2- import type { LambdaInterface } from '@aws-lambda-powertools/commons/lib/esm/types' ;
1+ import type { LambdaInterface } from '@aws-lambda-powertools/commons/types' ;
32import type { Context } from 'aws-lambda' ;
43import { describe , expect , it } from 'vitest' ;
5- import type { z } from 'zod' ;
4+ import { type ZodSchema , z } from 'zod' ;
65import { EventBridgeEnvelope } from '../../src/envelopes/index.js' ;
76import { ParseError } from '../../src/errors.js' ;
87import { parser } from '../../src/index.js' ;
98import { EventBridgeSchema } from '../../src/schemas/index.js' ;
10- import type { EventBridgeEvent , ParsedResult } from '../../src/types' ;
11- import { TestSchema , getTestEvent } from './schema/utils' ;
9+ import type { EventBridgeEvent , ParsedResult } from '../../src/types/index.js ' ;
10+ import { getTestEvent } from './schema/utils.js ' ;
1211
13- describe ( 'Parser Decorator' , ( ) => {
14- const customEventBridgeSchema = EventBridgeSchema . extend ( {
15- detail : TestSchema ,
12+ describe ( 'Decorator: parser' , ( ) => {
13+ const schema = z . object ( {
14+ name : z . string ( ) ,
15+ age : z . number ( ) ,
16+ } ) ;
17+ const payload = {
18+ name : 'John Doe' ,
19+ age : 30 ,
20+ } ;
21+ const extendedSchema = EventBridgeSchema . extend ( {
22+ detail : schema ,
23+ } ) ;
24+ type event = z . infer < typeof extendedSchema > ;
25+ const baseEvent = getTestEvent < EventBridgeEvent > ( {
26+ eventsPath : 'eventbridge' ,
27+ filename : 'base' ,
1628 } ) ;
17-
18- type TestEvent = z . infer < typeof TestSchema > ;
1929
2030 class TestClass implements LambdaInterface {
21- @parser ( { schema : TestSchema } )
22- public async handler (
23- event : TestEvent ,
24- _context : Context
25- ) : Promise < TestEvent > {
26- return event ;
27- }
28-
29- @parser ( { schema : customEventBridgeSchema } )
30- public async handlerWithCustomSchema (
31- event : unknown ,
32- _context : Context
33- ) : Promise < unknown > {
31+ @parser ( { schema : extendedSchema } )
32+ public async handler ( event : event , _context : Context ) : Promise < event > {
3433 return event ;
3534 }
3635
37- @parser ( { schema : TestSchema , envelope : EventBridgeEnvelope } )
36+ @parser ( { schema, envelope : EventBridgeEnvelope } )
3837 public async handlerWithParserCallsAnotherMethod (
39- event : TestEvent ,
38+ event : z . infer < typeof schema > ,
4039 _context : Context
4140 ) : Promise < unknown > {
4241 return this . anotherMethod ( event ) ;
4342 }
4443
45- @parser ( { schema : TestSchema , envelope : EventBridgeEnvelope } )
46- public async handlerWithSchemaAndEnvelope (
47- event : TestEvent ,
48- _context : Context
49- ) : Promise < unknown > {
50- return event ;
51- }
52-
5344 @parser ( {
54- schema : TestSchema ,
45+ schema,
5546 safeParse : true ,
5647 } )
5748 public async handlerWithSchemaAndSafeParse (
58- event : ParsedResult < unknown , TestEvent > ,
49+ event : ParsedResult < unknown , event > ,
5950 _context : Context
60- ) : Promise < ParsedResult > {
51+ ) : Promise < ParsedResult < unknown , event > > {
6152 return event ;
6253 }
6354
6455 @parser ( {
65- schema : TestSchema ,
56+ schema,
6657 envelope : EventBridgeEnvelope ,
6758 safeParse : true ,
6859 } )
6960 public async harndlerWithEnvelopeAndSafeParse (
70- event : ParsedResult < TestEvent , TestEvent > ,
61+ event : ParsedResult < event , event > ,
7162 _context : Context
7263 ) : Promise < ParsedResult > {
7364 return event ;
7465 }
7566
76- private async anotherMethod ( event : TestEvent ) : Promise < TestEvent > {
67+ private async anotherMethod < T extends ZodSchema > (
68+ event : z . infer < T >
69+ ) : Promise < z . infer < T > > {
7770 return event ;
7871 }
7972 }
80-
8173 const lambda = new TestClass ( ) ;
8274
83- it ( 'should parse custom schema event' , async ( ) => {
84- const testEvent = generateMock ( TestSchema ) ;
75+ it ( 'parses the event using the schema provided' , async ( ) => {
76+ // Prepare
77+ const event = structuredClone ( baseEvent ) ;
78+ event . detail = payload ;
8579
86- const resp = await lambda . handler ( testEvent , { } as Context ) ;
80+ // Act
81+ // @ts -expect-error - extended schema
82+ const result = await lambda . handler ( event , { } as Context ) ;
8783
88- expect ( resp ) . toEqual ( testEvent ) ;
84+ // Assess
85+ expect ( result ) . toEqual ( event ) ;
8986 } ) ;
9087
91- it ( 'should parse custom schema with envelope event' , async ( ) => {
92- const customPayload = generateMock ( TestSchema ) ;
93- const testEvent = getTestEvent < EventBridgeEvent > ( {
94- eventsPath : 'eventbridge' ,
95- filename : 'base' ,
96- } ) ;
97- testEvent . detail = customPayload ;
88+ it ( 'preserves the class method scope when decorated' , async ( ) => {
89+ // Prepare
90+ const event = structuredClone ( baseEvent ) ;
91+ event . detail = payload ;
9892
99- const resp = await lambda . handlerWithSchemaAndEnvelope (
100- testEvent as unknown as TestEvent ,
93+ const result = await lambda . handlerWithParserCallsAnotherMethod (
94+ // @ts -expect-error - extended schema
95+ event ,
10196 { } as Context
10297 ) ;
10398
104- expect ( resp ) . toEqual ( customPayload ) ;
99+ expect ( result ) . toEqual ( event . detail ) ;
105100 } ) ;
106101
107- it ( 'should parse extended envelope event' , async ( ) => {
108- const customPayload = generateMock ( TestSchema ) ;
109-
110- const testEvent = generateMock ( customEventBridgeSchema ) ;
111- testEvent . detail = customPayload ;
112-
113- const resp : z . infer < typeof customEventBridgeSchema > =
114- ( await lambda . handlerWithCustomSchema (
115- testEvent ,
116- { } as Context
117- ) ) as z . infer < typeof customEventBridgeSchema > ;
118-
119- expect ( customEventBridgeSchema . parse ( resp ) ) . toEqual ( testEvent ) ;
120- expect ( resp . detail ) . toEqual ( customPayload ) ;
121- } ) ;
122-
123- it ( 'should parse and call private async method' , async ( ) => {
124- const customPayload = generateMock ( TestSchema ) ;
125- const testEvent = getTestEvent < EventBridgeEvent > ( {
126- eventsPath : 'eventbridge' ,
127- filename : 'base' ,
128- } ) ;
129- testEvent . detail = customPayload ;
130-
131- const resp = await lambda . handlerWithParserCallsAnotherMethod (
132- testEvent as unknown as TestEvent ,
133- { } as Context
134- ) ;
135-
136- expect ( resp ) . toEqual ( customPayload ) ;
137- } ) ;
138-
139- it ( 'should parse event with schema and safeParse' , async ( ) => {
140- const testEvent = generateMock ( TestSchema ) ;
141-
142- const resp = await lambda . handlerWithSchemaAndSafeParse (
143- testEvent as unknown as ParsedResult < unknown , TestEvent > ,
144- { } as Context
145- ) ;
146-
147- expect ( resp ) . toEqual ( {
148- success : true ,
149- data : testEvent ,
150- } ) ;
151- } ) ;
152-
153- it ( 'should parse event with schema and safeParse and return error' , async ( ) => {
102+ it ( 'returns a parse error when schema validation fails with safeParse enabled' , async ( ) => {
103+ // Act & Assess
154104 expect (
155105 await lambda . handlerWithSchemaAndSafeParse (
156- { foo : 'bar' } as unknown as ParsedResult < unknown , TestEvent > ,
106+ { foo : 'bar' } as unknown as ParsedResult < unknown , event > ,
157107 { } as Context
158108 )
159109 ) . toEqual ( {
@@ -163,29 +113,29 @@ describe('Parser Decorator', () => {
163113 } ) ;
164114 } ) ;
165115
166- it ( 'should parse event with envelope and safeParse' , async ( ) => {
167- const testEvent = generateMock ( TestSchema ) ;
168- const event = getTestEvent < EventBridgeEvent > ( {
169- eventsPath : 'eventbridge' ,
170- filename : 'base' ,
171- } ) ;
172- event . detail = testEvent ;
116+ it ( 'parses the event with envelope and safeParse' , async ( ) => {
117+ // Prepare
118+ const event = structuredClone ( baseEvent ) ;
119+ event . detail = payload ;
173120
174- const resp = await lambda . harndlerWithEnvelopeAndSafeParse (
175- event as unknown as ParsedResult < TestEvent , TestEvent > ,
121+ // Act
122+ const result = await lambda . harndlerWithEnvelopeAndSafeParse (
123+ event as unknown as ParsedResult < event , event > ,
176124 { } as Context
177125 ) ;
178126
179- expect ( resp ) . toEqual ( {
127+ // Assess
128+ expect ( result ) . toEqual ( {
180129 success : true ,
181- data : testEvent ,
130+ data : event . detail ,
182131 } ) ;
183132 } ) ;
184133
185- it ( 'should parse event with envelope and safeParse and return error' , async ( ) => {
134+ it ( 'returns a parse error when schema/envelope validation fails with safeParse enabled' , async ( ) => {
135+ // Act & Assess
186136 expect (
187137 await lambda . harndlerWithEnvelopeAndSafeParse (
188- { foo : 'bar' } as unknown as ParsedResult < TestEvent , TestEvent > ,
138+ { foo : 'bar' } as unknown as ParsedResult < event , event > ,
189139 { } as Context
190140 )
191141 ) . toEqual ( {
0 commit comments