@hazeljs/serverless 0.2.0-beta.55 → 0.2.0-beta.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters.test.d.ts +2 -0
- package/dist/adapters.test.d.ts.map +1 -0
- package/dist/adapters.test.js +416 -0
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.test.d.ts","sourceRoot":"","sources":["../src/adapters.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
jest.mock('@hazeljs/core', () => ({
|
|
10
|
+
__esModule: true,
|
|
11
|
+
HazelApp: jest.fn(),
|
|
12
|
+
Container: { getInstance: jest.fn().mockReturnValue({}) },
|
|
13
|
+
Injectable: () => () => undefined,
|
|
14
|
+
HazelModule: () => () => undefined,
|
|
15
|
+
Type: null,
|
|
16
|
+
default: { info: jest.fn(), debug: jest.fn(), warn: jest.fn(), error: jest.fn() },
|
|
17
|
+
}));
|
|
18
|
+
const core_1 = require("@hazeljs/core");
|
|
19
|
+
const lambda_adapter_1 = require("./lambda.adapter");
|
|
20
|
+
const cloud_function_adapter_1 = require("./cloud-function.adapter");
|
|
21
|
+
const cold_start_optimizer_1 = require("./cold-start.optimizer");
|
|
22
|
+
const serverless_decorator_1 = require("./serverless.decorator");
|
|
23
|
+
class MockModule {
|
|
24
|
+
}
|
|
25
|
+
function makeEvent(overrides = {}) {
|
|
26
|
+
return {
|
|
27
|
+
httpMethod: 'GET',
|
|
28
|
+
path: '/test',
|
|
29
|
+
headers: {},
|
|
30
|
+
queryStringParameters: null,
|
|
31
|
+
body: null,
|
|
32
|
+
isBase64Encoded: false,
|
|
33
|
+
...overrides,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function makeContext(overrides = {}) {
|
|
37
|
+
return {
|
|
38
|
+
awsRequestId: 'req-123',
|
|
39
|
+
invokedFunctionArn: 'arn:aws:lambda:us-east-1:000:function:test',
|
|
40
|
+
functionName: 'test-fn',
|
|
41
|
+
functionVersion: '$LATEST',
|
|
42
|
+
logGroupName: '/aws/lambda/test',
|
|
43
|
+
logStreamName: '2024/01/01/test',
|
|
44
|
+
memoryLimitInMB: '512',
|
|
45
|
+
getRemainingTimeInMillis: () => 30000,
|
|
46
|
+
done: jest.fn(),
|
|
47
|
+
fail: jest.fn(),
|
|
48
|
+
succeed: jest.fn(),
|
|
49
|
+
callbackWaitsForEmptyEventLoop: true,
|
|
50
|
+
...overrides,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
describe('LambdaAdapter', () => {
|
|
54
|
+
let mockMatch;
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
jest.clearAllMocks();
|
|
57
|
+
mockMatch = jest.fn().mockResolvedValue(null);
|
|
58
|
+
core_1.HazelApp.mockImplementation(() => ({
|
|
59
|
+
getRouter: jest.fn().mockReturnValue({ match: mockMatch }),
|
|
60
|
+
}));
|
|
61
|
+
cold_start_optimizer_1.ColdStartOptimizer.getInstance().reset();
|
|
62
|
+
});
|
|
63
|
+
describe('createHandler() – cold start tracking', () => {
|
|
64
|
+
it('isCold() is true before first call', () => {
|
|
65
|
+
const adapter = new lambda_adapter_1.LambdaAdapter(MockModule);
|
|
66
|
+
expect(adapter.isCold()).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
it('isCold() becomes false after first handler call', async () => {
|
|
69
|
+
const adapter = new lambda_adapter_1.LambdaAdapter(MockModule);
|
|
70
|
+
await adapter.createHandler()(makeEvent(), makeContext());
|
|
71
|
+
expect(adapter.isCold()).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
it('getApp() is undefined before handler is called', () => {
|
|
74
|
+
expect(new lambda_adapter_1.LambdaAdapter(MockModule).getApp()).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
it('getApp() returns HazelApp after first call', async () => {
|
|
77
|
+
const adapter = new lambda_adapter_1.LambdaAdapter(MockModule);
|
|
78
|
+
await adapter.createHandler()(makeEvent(), makeContext());
|
|
79
|
+
expect(adapter.getApp()).toBeDefined();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('createHandler() – routing', () => {
|
|
83
|
+
it('returns 404 when route is not found', async () => {
|
|
84
|
+
const adapter = new lambda_adapter_1.LambdaAdapter(MockModule);
|
|
85
|
+
const result = await adapter.createHandler()(makeEvent({ path: '/missing' }), makeContext());
|
|
86
|
+
expect(result.statusCode).toBe(404);
|
|
87
|
+
expect(JSON.parse(result.body)).toMatchObject({ message: 'Route not found' });
|
|
88
|
+
});
|
|
89
|
+
it('calls matched route handler and returns json response', async () => {
|
|
90
|
+
mockMatch.mockResolvedValue({
|
|
91
|
+
handler: async (_req, res) => res.json({ ok: true }),
|
|
92
|
+
});
|
|
93
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent(), makeContext());
|
|
94
|
+
expect(result.statusCode).toBe(200);
|
|
95
|
+
expect(JSON.parse(result.body)).toEqual({ ok: true });
|
|
96
|
+
});
|
|
97
|
+
it('uses returned value from handler when res methods are not called', async () => {
|
|
98
|
+
mockMatch.mockResolvedValue({ handler: async () => ({ direct: 'return' }) });
|
|
99
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent(), makeContext());
|
|
100
|
+
expect(JSON.parse(result.body)).toEqual({ direct: 'return' });
|
|
101
|
+
});
|
|
102
|
+
it('respects res.status() code', async () => {
|
|
103
|
+
mockMatch.mockResolvedValue({
|
|
104
|
+
handler: async (_req, res) => res.status(201).json({ created: true }),
|
|
105
|
+
});
|
|
106
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent({ httpMethod: 'POST' }), makeContext());
|
|
107
|
+
expect(result.statusCode).toBe(201);
|
|
108
|
+
});
|
|
109
|
+
it('returns string body from res.send()', async () => {
|
|
110
|
+
mockMatch.mockResolvedValue({
|
|
111
|
+
handler: async (_req, res) => res.send('plain text'),
|
|
112
|
+
});
|
|
113
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent(), makeContext());
|
|
114
|
+
expect(result.body).toBe('plain text');
|
|
115
|
+
});
|
|
116
|
+
it('supports res.setHeader()', async () => {
|
|
117
|
+
mockMatch.mockResolvedValue({
|
|
118
|
+
handler: async (_req, res) => {
|
|
119
|
+
res.setHeader('X-Custom', 'value');
|
|
120
|
+
res.json({});
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent(), makeContext());
|
|
124
|
+
expect(result.headers?.['X-Custom']).toBe('value');
|
|
125
|
+
});
|
|
126
|
+
it('returns error statusCode from thrown error with statusCode property', async () => {
|
|
127
|
+
const err = Object.assign(new Error('Forbidden'), { statusCode: 403 });
|
|
128
|
+
mockMatch.mockRejectedValue(err);
|
|
129
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent(), makeContext());
|
|
130
|
+
expect(result.statusCode).toBe(403);
|
|
131
|
+
});
|
|
132
|
+
it('returns 500 when route handler throws without statusCode', async () => {
|
|
133
|
+
mockMatch.mockRejectedValue(new Error('Unexpected'));
|
|
134
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent(), makeContext());
|
|
135
|
+
expect(result.statusCode).toBe(500);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
describe('createHandler() – request conversion', () => {
|
|
139
|
+
it('parses JSON body', async () => {
|
|
140
|
+
let capturedBody;
|
|
141
|
+
mockMatch.mockResolvedValue({
|
|
142
|
+
handler: async (req, res) => {
|
|
143
|
+
capturedBody = req.body;
|
|
144
|
+
res.json({});
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent({ httpMethod: 'POST', body: '{"key":"val"}' }), makeContext());
|
|
148
|
+
expect(capturedBody).toEqual({ key: 'val' });
|
|
149
|
+
});
|
|
150
|
+
it('parses base64-encoded JSON body', async () => {
|
|
151
|
+
let capturedBody;
|
|
152
|
+
mockMatch.mockResolvedValue({
|
|
153
|
+
handler: async (req, res) => {
|
|
154
|
+
capturedBody = req.body;
|
|
155
|
+
res.json({});
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
const b64 = Buffer.from(JSON.stringify({ encoded: true })).toString('base64');
|
|
159
|
+
await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent({ httpMethod: 'POST', body: b64, isBase64Encoded: true }), makeContext());
|
|
160
|
+
expect(capturedBody).toEqual({ encoded: true });
|
|
161
|
+
});
|
|
162
|
+
it('returns raw string body when JSON parse fails', async () => {
|
|
163
|
+
let capturedBody;
|
|
164
|
+
mockMatch.mockResolvedValue({
|
|
165
|
+
handler: async (req, res) => {
|
|
166
|
+
capturedBody = req.body;
|
|
167
|
+
res.json({});
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent({ httpMethod: 'POST', body: 'not-valid-json' }), makeContext());
|
|
171
|
+
expect(capturedBody).toBe('not-valid-json');
|
|
172
|
+
});
|
|
173
|
+
it('passes query string parameters to handler', async () => {
|
|
174
|
+
let capturedQuery;
|
|
175
|
+
mockMatch.mockResolvedValue({
|
|
176
|
+
handler: async (req, res) => {
|
|
177
|
+
capturedQuery = req.query;
|
|
178
|
+
res.json({});
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent({ queryStringParameters: { page: '2', size: '10' } }), makeContext());
|
|
182
|
+
expect(capturedQuery).toEqual({ page: '2', size: '10' });
|
|
183
|
+
});
|
|
184
|
+
it('passes pathParameters to handler', async () => {
|
|
185
|
+
let capturedParams;
|
|
186
|
+
mockMatch.mockResolvedValue({
|
|
187
|
+
handler: async (req, res) => {
|
|
188
|
+
capturedParams = req.params;
|
|
189
|
+
res.json({});
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent({ pathParameters: { id: '42' } }), makeContext());
|
|
193
|
+
expect(capturedParams).toEqual({ id: '42' });
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
describe('createHandler() – initialization errors', () => {
|
|
197
|
+
it('returns 500 when HazelApp constructor throws', async () => {
|
|
198
|
+
core_1.HazelApp.mockImplementationOnce(() => {
|
|
199
|
+
throw new Error('Module init failed');
|
|
200
|
+
});
|
|
201
|
+
const result = await new lambda_adapter_1.LambdaAdapter(MockModule).createHandler()(makeEvent(), makeContext());
|
|
202
|
+
expect(result.statusCode).toBe(500);
|
|
203
|
+
expect(JSON.parse(result.body).message).toBe('Module init failed');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
describe('createHandler() – app reuse', () => {
|
|
207
|
+
it('creates HazelApp only once across multiple calls', async () => {
|
|
208
|
+
mockMatch.mockResolvedValue({
|
|
209
|
+
handler: async (_r, res) => res.json({}),
|
|
210
|
+
});
|
|
211
|
+
const adapter = new lambda_adapter_1.LambdaAdapter(MockModule);
|
|
212
|
+
const handler = adapter.createHandler();
|
|
213
|
+
await handler(makeEvent(), makeContext());
|
|
214
|
+
await handler(makeEvent(), makeContext());
|
|
215
|
+
expect(core_1.HazelApp).toHaveBeenCalledTimes(1);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe('cold start optimization', () => {
|
|
219
|
+
it('calls warmUp when module has @Serverless coldStartOptimization:true', async () => {
|
|
220
|
+
let OptimizedModule = class OptimizedModule {
|
|
221
|
+
};
|
|
222
|
+
OptimizedModule = __decorate([
|
|
223
|
+
(0, serverless_decorator_1.Serverless)({ coldStartOptimization: true })
|
|
224
|
+
], OptimizedModule);
|
|
225
|
+
mockMatch.mockResolvedValue({
|
|
226
|
+
handler: async (_r, res) => res.json({}),
|
|
227
|
+
});
|
|
228
|
+
const adapter = new lambda_adapter_1.LambdaAdapter(OptimizedModule);
|
|
229
|
+
await adapter.createHandler()(makeEvent(), makeContext());
|
|
230
|
+
expect(core_1.HazelApp).toHaveBeenCalledTimes(1);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
describe('createLambdaHandler()', () => {
|
|
235
|
+
beforeEach(() => {
|
|
236
|
+
jest.clearAllMocks();
|
|
237
|
+
core_1.HazelApp.mockImplementation(() => ({
|
|
238
|
+
getRouter: jest.fn().mockReturnValue({ match: jest.fn().mockResolvedValue(null) }),
|
|
239
|
+
}));
|
|
240
|
+
cold_start_optimizer_1.ColdStartOptimizer.getInstance().reset();
|
|
241
|
+
});
|
|
242
|
+
it('returns a callable handler that produces a ServerlessResponse', async () => {
|
|
243
|
+
const handler = (0, lambda_adapter_1.createLambdaHandler)(MockModule);
|
|
244
|
+
const result = await handler(makeEvent(), makeContext());
|
|
245
|
+
expect(result).toHaveProperty('statusCode');
|
|
246
|
+
expect(result).toHaveProperty('body');
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
// ─── CloudFunctionAdapter ────────────────────────────────────────────────────
|
|
250
|
+
function makeCloudReq(overrides = {}) {
|
|
251
|
+
return {
|
|
252
|
+
method: 'GET',
|
|
253
|
+
url: '/test',
|
|
254
|
+
path: '/test',
|
|
255
|
+
headers: { 'content-type': 'application/json' },
|
|
256
|
+
query: {},
|
|
257
|
+
...overrides,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function makeCloudRes() {
|
|
261
|
+
const captures = {
|
|
262
|
+
headers: {},
|
|
263
|
+
};
|
|
264
|
+
const res = {
|
|
265
|
+
_captures: captures,
|
|
266
|
+
status: jest.fn().mockReturnThis(),
|
|
267
|
+
set: jest.fn().mockReturnThis(),
|
|
268
|
+
send: jest.fn().mockImplementation((b) => {
|
|
269
|
+
captures.body = b;
|
|
270
|
+
}),
|
|
271
|
+
json: jest.fn().mockImplementation((b) => {
|
|
272
|
+
captures.body = b;
|
|
273
|
+
}),
|
|
274
|
+
end: jest.fn(),
|
|
275
|
+
};
|
|
276
|
+
return res;
|
|
277
|
+
}
|
|
278
|
+
describe('CloudFunctionAdapter', () => {
|
|
279
|
+
let mockMatch;
|
|
280
|
+
beforeEach(() => {
|
|
281
|
+
jest.clearAllMocks();
|
|
282
|
+
mockMatch = jest.fn().mockResolvedValue(null);
|
|
283
|
+
core_1.HazelApp.mockImplementation(() => ({
|
|
284
|
+
getRouter: jest.fn().mockReturnValue({ match: mockMatch }),
|
|
285
|
+
}));
|
|
286
|
+
cold_start_optimizer_1.ColdStartOptimizer.getInstance().reset();
|
|
287
|
+
});
|
|
288
|
+
describe('createHttpHandler()', () => {
|
|
289
|
+
it('calls res.status(404) when route not found', async () => {
|
|
290
|
+
const res = makeCloudRes();
|
|
291
|
+
await new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createHttpHandler()(makeCloudReq(), res);
|
|
292
|
+
expect(res.status).toHaveBeenCalledWith(404);
|
|
293
|
+
expect(res.send).toHaveBeenCalled();
|
|
294
|
+
});
|
|
295
|
+
it('calls matched route and sends response', async () => {
|
|
296
|
+
mockMatch.mockResolvedValue({
|
|
297
|
+
handler: async (_r, synRes) => synRes.json({ ok: true }),
|
|
298
|
+
});
|
|
299
|
+
const res = makeCloudRes();
|
|
300
|
+
await new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createHttpHandler()(makeCloudReq(), res);
|
|
301
|
+
expect(res.send).toHaveBeenCalled();
|
|
302
|
+
});
|
|
303
|
+
it('calls res.status(500).json() on handler init error', async () => {
|
|
304
|
+
core_1.HazelApp.mockImplementationOnce(() => {
|
|
305
|
+
throw new Error('crash');
|
|
306
|
+
});
|
|
307
|
+
const res = makeCloudRes();
|
|
308
|
+
await new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createHttpHandler()(makeCloudReq(), res);
|
|
309
|
+
expect(res.status).toHaveBeenCalledWith(500);
|
|
310
|
+
expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ error: 'Internal Server Error' }));
|
|
311
|
+
});
|
|
312
|
+
it('normalizes string[] headers to first value', async () => {
|
|
313
|
+
let capturedHeaders;
|
|
314
|
+
mockMatch.mockResolvedValue({
|
|
315
|
+
handler: async (req, res) => {
|
|
316
|
+
capturedHeaders = req.headers;
|
|
317
|
+
res.json({});
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
const res = makeCloudRes();
|
|
321
|
+
await new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createHttpHandler()(makeCloudReq({ headers: { 'x-multi': ['alpha', 'beta'] } }), res);
|
|
322
|
+
expect(capturedHeaders?.['x-multi']).toBe('alpha');
|
|
323
|
+
});
|
|
324
|
+
it('normalizes string[] query params to first value', async () => {
|
|
325
|
+
let capturedQuery;
|
|
326
|
+
mockMatch.mockResolvedValue({
|
|
327
|
+
handler: async (req, res) => {
|
|
328
|
+
capturedQuery = req.query;
|
|
329
|
+
res.json({});
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
const res = makeCloudRes();
|
|
333
|
+
await new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createHttpHandler()(makeCloudReq({ query: { tag: ['first', 'second'] } }), res);
|
|
334
|
+
expect(capturedQuery?.tag).toBe('first');
|
|
335
|
+
});
|
|
336
|
+
it('sets headers on response from internal ServerlessResponse headers', async () => {
|
|
337
|
+
mockMatch.mockResolvedValue({
|
|
338
|
+
handler: async (_r, synRes) => {
|
|
339
|
+
synRes.setHeader('X-Trace', 'abc');
|
|
340
|
+
synRes.json({});
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
const res = makeCloudRes();
|
|
344
|
+
await new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createHttpHandler()(makeCloudReq(), res);
|
|
345
|
+
expect(res.set).toHaveBeenCalledWith('X-Trace', 'abc');
|
|
346
|
+
});
|
|
347
|
+
it('isCold() becomes false after first call', async () => {
|
|
348
|
+
const adapter = new cloud_function_adapter_1.CloudFunctionAdapter(MockModule);
|
|
349
|
+
expect(adapter.isCold()).toBe(true);
|
|
350
|
+
const res = makeCloudRes();
|
|
351
|
+
await adapter.createHttpHandler()(makeCloudReq(), res);
|
|
352
|
+
expect(adapter.isCold()).toBe(false);
|
|
353
|
+
});
|
|
354
|
+
it('getApp() returns undefined before first call', () => {
|
|
355
|
+
expect(new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).getApp()).toBeUndefined();
|
|
356
|
+
});
|
|
357
|
+
it('creates HazelApp only once across multiple calls', async () => {
|
|
358
|
+
mockMatch.mockResolvedValue({
|
|
359
|
+
handler: async (_r, res) => res.json({}),
|
|
360
|
+
});
|
|
361
|
+
const adapter = new cloud_function_adapter_1.CloudFunctionAdapter(MockModule);
|
|
362
|
+
const handler = adapter.createHttpHandler();
|
|
363
|
+
const res1 = makeCloudRes();
|
|
364
|
+
const res2 = makeCloudRes();
|
|
365
|
+
await handler(makeCloudReq(), res1);
|
|
366
|
+
await handler(makeCloudReq(), res2);
|
|
367
|
+
expect(core_1.HazelApp).toHaveBeenCalledTimes(1);
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
describe('createEventHandler()', () => {
|
|
371
|
+
it('resolves without error for a valid event', async () => {
|
|
372
|
+
const handler = new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createEventHandler();
|
|
373
|
+
await expect(handler({ data: 'payload' }, { eventType: 'pubsub', resource: 'projects/test' })).resolves.toBeUndefined();
|
|
374
|
+
});
|
|
375
|
+
it('rethrows errors from initialization', async () => {
|
|
376
|
+
core_1.HazelApp.mockImplementationOnce(() => {
|
|
377
|
+
throw new Error('init failed');
|
|
378
|
+
});
|
|
379
|
+
const handler = new cloud_function_adapter_1.CloudFunctionAdapter(MockModule).createEventHandler();
|
|
380
|
+
await expect(handler({}, {})).rejects.toThrow('init failed');
|
|
381
|
+
});
|
|
382
|
+
it('isCold() becomes false after first event call', async () => {
|
|
383
|
+
const adapter = new cloud_function_adapter_1.CloudFunctionAdapter(MockModule);
|
|
384
|
+
await adapter.createEventHandler()({}, {});
|
|
385
|
+
expect(adapter.isCold()).toBe(false);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
describe('createCloudFunctionHandler()', () => {
|
|
390
|
+
beforeEach(() => {
|
|
391
|
+
jest.clearAllMocks();
|
|
392
|
+
core_1.HazelApp.mockImplementation(() => ({
|
|
393
|
+
getRouter: jest.fn().mockReturnValue({ match: jest.fn().mockResolvedValue(null) }),
|
|
394
|
+
}));
|
|
395
|
+
cold_start_optimizer_1.ColdStartOptimizer.getInstance().reset();
|
|
396
|
+
});
|
|
397
|
+
it('returns a callable HTTP handler', async () => {
|
|
398
|
+
const handler = (0, cloud_function_adapter_1.createCloudFunctionHandler)(MockModule);
|
|
399
|
+
const res = makeCloudRes();
|
|
400
|
+
await handler(makeCloudReq(), res);
|
|
401
|
+
expect(res.send).toHaveBeenCalled();
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
describe('createCloudFunctionEventHandler()', () => {
|
|
405
|
+
beforeEach(() => {
|
|
406
|
+
jest.clearAllMocks();
|
|
407
|
+
core_1.HazelApp.mockImplementation(() => ({
|
|
408
|
+
getRouter: jest.fn().mockReturnValue({ match: jest.fn() }),
|
|
409
|
+
}));
|
|
410
|
+
cold_start_optimizer_1.ColdStartOptimizer.getInstance().reset();
|
|
411
|
+
});
|
|
412
|
+
it('returns a callable event handler', async () => {
|
|
413
|
+
const handler = (0, cloud_function_adapter_1.createCloudFunctionEventHandler)(MockModule);
|
|
414
|
+
await expect(handler({ data: 'test' }, {})).resolves.toBeUndefined();
|
|
415
|
+
});
|
|
416
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hazeljs/serverless",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.57",
|
|
4
4
|
"description": "Serverless adapters (AWS Lambda, Google Cloud Functions) for HazelJS framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@hazeljs/core": ">=0.2.0-beta.0"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "98c84683e8f487c660e344c2beda3a8dcaaff07f"
|
|
52
52
|
}
|