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' ;
3
2
import type { Context } from 'aws-lambda' ;
4
3
import { describe , expect , it } from 'vitest' ;
5
- import type { z } from 'zod' ;
4
+ import { type ZodSchema , z } from 'zod' ;
6
5
import { EventBridgeEnvelope } from '../../src/envelopes/index.js' ;
7
6
import { ParseError } from '../../src/errors.js' ;
8
7
import { parser } from '../../src/index.js' ;
9
8
import { 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 ' ;
12
11
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' ,
16
28
} ) ;
17
-
18
- type TestEvent = z . infer < typeof TestSchema > ;
19
29
20
30
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 > {
34
33
return event ;
35
34
}
36
35
37
- @parser ( { schema : TestSchema , envelope : EventBridgeEnvelope } )
36
+ @parser ( { schema, envelope : EventBridgeEnvelope } )
38
37
public async handlerWithParserCallsAnotherMethod (
39
- event : TestEvent ,
38
+ event : z . infer < typeof schema > ,
40
39
_context : Context
41
40
) : Promise < unknown > {
42
41
return this . anotherMethod ( event ) ;
43
42
}
44
43
45
- @parser ( { schema : TestSchema , envelope : EventBridgeEnvelope } )
46
- public async handlerWithSchemaAndEnvelope (
47
- event : TestEvent ,
48
- _context : Context
49
- ) : Promise < unknown > {
50
- return event ;
51
- }
52
-
53
44
@parser ( {
54
- schema : TestSchema ,
45
+ schema,
55
46
safeParse : true ,
56
47
} )
57
48
public async handlerWithSchemaAndSafeParse (
58
- event : ParsedResult < unknown , TestEvent > ,
49
+ event : ParsedResult < unknown , event > ,
59
50
_context : Context
60
- ) : Promise < ParsedResult > {
51
+ ) : Promise < ParsedResult < unknown , event > > {
61
52
return event ;
62
53
}
63
54
64
55
@parser ( {
65
- schema : TestSchema ,
56
+ schema,
66
57
envelope : EventBridgeEnvelope ,
67
58
safeParse : true ,
68
59
} )
69
60
public async harndlerWithEnvelopeAndSafeParse (
70
- event : ParsedResult < TestEvent , TestEvent > ,
61
+ event : ParsedResult < event , event > ,
71
62
_context : Context
72
63
) : Promise < ParsedResult > {
73
64
return event ;
74
65
}
75
66
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 > > {
77
70
return event ;
78
71
}
79
72
}
80
-
81
73
const lambda = new TestClass ( ) ;
82
74
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 ;
85
79
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 ) ;
87
83
88
- expect ( resp ) . toEqual ( testEvent ) ;
84
+ // Assess
85
+ expect ( result ) . toEqual ( event ) ;
89
86
} ) ;
90
87
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 ;
98
92
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 ,
101
96
{ } as Context
102
97
) ;
103
98
104
- expect ( resp ) . toEqual ( customPayload ) ;
99
+ expect ( result ) . toEqual ( event . detail ) ;
105
100
} ) ;
106
101
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
154
104
expect (
155
105
await lambda . handlerWithSchemaAndSafeParse (
156
- { foo : 'bar' } as unknown as ParsedResult < unknown , TestEvent > ,
106
+ { foo : 'bar' } as unknown as ParsedResult < unknown , event > ,
157
107
{ } as Context
158
108
)
159
109
) . toEqual ( {
@@ -163,29 +113,29 @@ describe('Parser Decorator', () => {
163
113
} ) ;
164
114
} ) ;
165
115
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 ;
173
120
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 > ,
176
124
{ } as Context
177
125
) ;
178
126
179
- expect ( resp ) . toEqual ( {
127
+ // Assess
128
+ expect ( result ) . toEqual ( {
180
129
success : true ,
181
- data : testEvent ,
130
+ data : event . detail ,
182
131
} ) ;
183
132
} ) ;
184
133
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
186
136
expect (
187
137
await lambda . harndlerWithEnvelopeAndSafeParse (
188
- { foo : 'bar' } as unknown as ParsedResult < TestEvent , TestEvent > ,
138
+ { foo : 'bar' } as unknown as ParsedResult < event , event > ,
189
139
{ } as Context
190
140
)
191
141
) . toEqual ( {
0 commit comments