ts-procedures 3.3.3 → 3.4.0

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/README.md CHANGED
@@ -265,6 +265,35 @@ AJV is configured with:
265
265
 
266
266
  **Note:** `schema.params` is validated at runtime. `schema.returnType` is for documentation/introspection only.
267
267
 
268
+ ### Skipping Validation with isPrevalidated
269
+
270
+ When building framework integrations that validate params before calling procedure handlers, you can pass `isPrevalidated: true` in the context to skip duplicate validation:
271
+
272
+ ```typescript
273
+ // Framework integration example
274
+ app.post('/rpc/:name', async (req, res) => {
275
+ const procedure = getProcedure(req.params.name)
276
+
277
+ // Validate params at the framework level
278
+ const { errors } = procedure.config.validation?.params?.(req.body)
279
+ if (errors) {
280
+ return res.status(400).json({ errors })
281
+ }
282
+
283
+ // Call handler with isPrevalidated to skip redundant validation
284
+ const result = await procedure.handler(
285
+ { ...context, isPrevalidated: true },
286
+ req.body
287
+ )
288
+ res.json(result)
289
+ })
290
+ ```
291
+
292
+ This is useful for:
293
+ - Framework integrations (like `HonoStreamAppBuilder`) that validate before starting streams
294
+ - Custom middleware that performs early validation for better error responses
295
+ - Performance optimization when validation has already occurred
296
+
268
297
  ## Streaming Procedures
269
298
 
270
299
  Streaming procedures use async generators to yield values over time, enabling SSE (Server-Sent Events), HTTP streaming, and real-time data feeds.
package/build/errors.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { formatDefinitionInfo } from './stack-utils.js';
2
+ import { kebabCase } from 'es-toolkit/string';
2
3
  export class ProcedureError extends Error {
3
4
  procedureName;
4
5
  message;
@@ -50,7 +51,10 @@ export class ProcedureValidationError extends ProcedureError {
50
51
  constructor(procedureName, message, errors,
51
52
  // Used for error stack trace details
52
53
  definitionInfo) {
53
- super(procedureName, message, undefined, definitionInfo);
54
+ const readableErrors = errors
55
+ ?.map((err) => `- ${kebabCase(err.instancePath).replace('-', '.')} ${err.message}`)
56
+ .join(', ');
57
+ super(procedureName, message + ' ' + readableErrors, { errors }, definitionInfo);
54
58
  this.procedureName = procedureName;
55
59
  this.errors = errors;
56
60
  this.name = 'ProcedureValidationError';
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,15 @@ import { TStreamProcedureRegistration } from '../../../index.js';
3
3
  import { ExtractConfig, ExtractContext, ProceduresFactory, RPCConfig } from '../../types.js';
4
4
  import { StreamHttpRouteDoc, StreamMode } from './types.js';
5
5
  export type { StreamHttpRouteDoc, StreamMode };
6
+ /**
7
+ * Result from onMidStreamError callback.
8
+ * @property value - The value to write to the stream (should match yieldType schema)
9
+ * @property closeStream - Whether to close the stream after writing (defaults to true)
10
+ */
11
+ export type MidStreamErrorResult = {
12
+ value: unknown;
13
+ closeStream?: boolean;
14
+ };
6
15
  export type HonoStreamAppBuilderConfig = {
7
16
  /**
8
17
  * An existing Hono application instance to use.
@@ -18,9 +27,19 @@ export type HonoStreamAppBuilderConfig = {
18
27
  onStreamStart?: (procedure: TStreamProcedureRegistration, c: Context) => void;
19
28
  onStreamEnd?: (procedure: TStreamProcedureRegistration, c: Context) => void;
20
29
  /**
21
- * Error handler called when a streaming procedure throws an error.
30
+ * Called for errors BEFORE streaming starts (validation, auth, context resolution).
31
+ * Return value IS used as the HTTP response.
32
+ */
33
+ onPreStreamError?: (procedure: TStreamProcedureRegistration, c: Context, error: Error) => Response | Promise<Response>;
34
+ /**
35
+ * Called for errors DURING streaming (generator throws).
36
+ * Return value is written to the stream as a yield.
37
+ * Should return a value matching your yieldType schema (e.g., error variant of a union).
38
+ * Return undefined to use default behavior (writes { error: message }).
39
+ *
40
+ * @returns { value, closeStream? } - value to yield, whether to close after (default true)
22
41
  */
23
- onStreamError?: (procedure: TStreamProcedureRegistration, c: Context, error: Error) => Response | Promise<Response>;
42
+ onMidStreamError?: (procedure: TStreamProcedureRegistration, c: Context, error: Error) => MidStreamErrorResult | undefined;
24
43
  };
25
44
  /**
26
45
  * Builder class for creating a Hono application with streaming RPC routes.
@@ -2,6 +2,7 @@ import { Hono } from 'hono';
2
2
  import { streamSSE, streamText } from 'hono/streaming';
3
3
  import { kebabCase } from 'es-toolkit/string';
4
4
  import { castArray } from 'es-toolkit/compat';
5
+ import { ProcedureValidationError } from '../../../errors.js';
5
6
  /**
6
7
  * Builder class for creating a Hono application with streaming RPC routes.
7
8
  *
@@ -31,12 +32,6 @@ export class HonoStreamAppBuilder {
31
32
  await next();
32
33
  });
33
34
  }
34
- if (config?.onRequestEnd) {
35
- this._app.use('*', async (c, next) => {
36
- await next();
37
- config.onRequestEnd(c);
38
- });
39
- }
40
35
  }
41
36
  /**
42
37
  * Generates the stream route path based on the RPC configuration.
@@ -83,13 +78,23 @@ export class HonoStreamAppBuilder {
83
78
  createStreamHandler(procedure, factoryContext, streamMode) {
84
79
  return async (c) => {
85
80
  try {
86
- const context = typeof factoryContext === 'function'
87
- ? await factoryContext(c)
88
- : factoryContext;
81
+ const context = typeof factoryContext === 'function' ? await factoryContext(c) : factoryContext;
89
82
  // GET: query params, POST: JSON body
90
83
  const params = c.req.method === 'GET'
91
84
  ? Object.fromEntries(new URL(c.req.url).searchParams)
92
85
  : await c.req.json().catch(() => ({}));
86
+ // Validate params BEFORE starting the stream
87
+ if (procedure.config.validation?.params) {
88
+ const { errors } = procedure.config.validation.params(params);
89
+ if (errors) {
90
+ const error = new ProcedureValidationError(procedure.name, `Validation error for ${procedure.name}`, errors);
91
+ // Use onPreStreamError if provided
92
+ if (this.config?.onPreStreamError) {
93
+ return this.config.onPreStreamError(procedure, c, error);
94
+ }
95
+ return c.json({ error: error.message }, 400);
96
+ }
97
+ }
93
98
  if (this.config?.onStreamStart) {
94
99
  this.config.onStreamStart(procedure, c);
95
100
  }
@@ -101,8 +106,9 @@ export class HonoStreamAppBuilder {
101
106
  }
102
107
  }
103
108
  catch (error) {
104
- if (this.config?.onStreamError) {
105
- return this.config.onStreamError(procedure, c, error);
109
+ // Use onPreStreamError for context resolution errors
110
+ if (this.config?.onPreStreamError) {
111
+ return this.config.onPreStreamError(procedure, c, error);
106
112
  }
107
113
  return c.json({ error: error.message }, 500);
108
114
  }
@@ -113,12 +119,13 @@ export class HonoStreamAppBuilder {
113
119
  */
114
120
  handleSSEStream(procedure, context, params, c) {
115
121
  return streamSSE(c, async (stream) => {
116
- const generator = procedure.handler(context, params);
122
+ // Pass isPrevalidated: true since we already validated params in createStreamHandler
123
+ const generator = procedure.handler({ ...context, isPrevalidated: true }, params);
117
124
  stream.onAbort(async () => {
118
125
  await generator.return(undefined);
119
126
  });
127
+ let eventId = 0;
120
128
  try {
121
- let eventId = 0;
122
129
  for await (const value of generator) {
123
130
  await stream.writeSSE({
124
131
  data: JSON.stringify(value),
@@ -128,16 +135,29 @@ export class HonoStreamAppBuilder {
128
135
  }
129
136
  }
130
137
  catch (error) {
131
- // Write error as SSE event before closing
138
+ // Get error yield value from callback (onMidStreamError)
139
+ let errorResult;
140
+ if (this.config?.onMidStreamError) {
141
+ errorResult = this.config.onMidStreamError(procedure, c, error);
142
+ }
143
+ // Write error value to stream
144
+ const errorValue = errorResult?.value ?? { error: error.message };
132
145
  await stream.writeSSE({
133
- data: JSON.stringify({ error: error.message }),
134
- event: 'error',
146
+ data: JSON.stringify(errorValue),
147
+ // Use procedure event name if custom value provided, otherwise 'error'
148
+ event: errorResult?.value !== undefined ? procedure.name : 'error',
149
+ id: String(eventId++),
135
150
  });
151
+ // closeStream defaults to true if not specified
152
+ // (stream closes naturally after this handler completes)
136
153
  }
137
154
  finally {
138
155
  if (this.config?.onStreamEnd) {
139
156
  this.config.onStreamEnd(procedure, c);
140
157
  }
158
+ if (this.config?.onRequestEnd) {
159
+ this.config.onRequestEnd(c);
160
+ }
141
161
  }
142
162
  });
143
163
  }
@@ -146,7 +166,8 @@ export class HonoStreamAppBuilder {
146
166
  */
147
167
  handleTextStream(procedure, context, params, c) {
148
168
  return streamText(c, async (stream) => {
149
- const generator = procedure.handler(context, params);
169
+ // Pass isPrevalidated: true since we already validated params in createStreamHandler
170
+ const generator = procedure.handler({ ...context, isPrevalidated: true }, params);
150
171
  stream.onAbort(async () => {
151
172
  await generator.return(undefined);
152
173
  });
@@ -156,13 +177,22 @@ export class HonoStreamAppBuilder {
156
177
  }
157
178
  }
158
179
  catch (error) {
159
- // Write error as JSON line before closing
160
- await stream.writeln(JSON.stringify({ error: error.message }));
180
+ // Get error yield value from callback (onMidStreamError)
181
+ let errorResult;
182
+ if (this.config?.onMidStreamError) {
183
+ errorResult = this.config.onMidStreamError(procedure, c, error);
184
+ }
185
+ // Write error value to stream
186
+ const errorValue = errorResult?.value ?? { error: error.message };
187
+ await stream.writeln(JSON.stringify(errorValue));
161
188
  }
162
189
  finally {
163
190
  if (this.config?.onStreamEnd) {
164
191
  this.config.onStreamEnd(procedure, c);
165
192
  }
193
+ if (this.config?.onRequestEnd) {
194
+ this.config.onRequestEnd(c);
195
+ }
166
196
  }
167
197
  });
168
198
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/implementations/http/hono-stream/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/implementations/http/hono-stream/index.ts"],"names":[],"mappings":"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"}
@@ -268,7 +268,8 @@ describe('HonoStreamAppBuilder', () => {
268
268
  });
269
269
  builder.register(RPC, () => ({}));
270
270
  const app = builder.build();
271
- await app.request('/test/test/1');
271
+ const response = await app.request('/test/test/1');
272
+ await response.text(); // Consume stream to trigger onRequestEnd
272
273
  expect(onRequestEnd).toHaveBeenCalledTimes(1);
273
274
  expect(onRequestEnd.mock.calls[0][0]).toHaveProperty('req');
274
275
  });
@@ -329,6 +330,8 @@ describe('HonoStreamAppBuilder', () => {
329
330
  expect(order[0]).toBe('request-start');
330
331
  // stream-start should be before handler
331
332
  expect(order.indexOf('stream-start')).toBeLessThan(order.indexOf('handler'));
333
+ // request-end should be last
334
+ expect(order[order.length - 1]).toBe('request-end');
332
335
  });
333
336
  });
334
337
  // --------------------------------------------------------------------------
@@ -339,15 +342,26 @@ describe('HonoStreamAppBuilder', () => {
339
342
  const errorHandler = vi.fn((procedure, c, error) => {
340
343
  return c.json({ customError: error.message }, 400);
341
344
  });
342
- const builder = new HonoStreamAppBuilder({ onStreamError: errorHandler });
345
+ const builder = new HonoStreamAppBuilder({ onPreStreamError: errorHandler });
343
346
  const RPC = Procedures();
344
- // Error during context resolution (before streaming starts)
345
- builder.register(RPC, () => {
346
- throw new Error('Context error');
347
+ RPC.CreateStream('ValidatedStream', {
348
+ scope: 'validated',
349
+ version: 1,
350
+ schema: {
351
+ params: v.object({ count: v.number() }),
352
+ },
353
+ }, async function* (ctx, params) {
354
+ yield { count: params.count };
347
355
  });
356
+ builder.register(RPC, () => ({}));
348
357
  const app = builder.build();
349
- // Since no streaming procedures were registered, this should 404
350
- // Let's test with a real streaming procedure that throws during setup
358
+ const res = await app.request('/validated/validated-stream/1?count=not-a-number');
359
+ expect(res.status).toBe(400);
360
+ const body = await res.json();
361
+ expect(body.customError).toContain('Validation error');
362
+ expect(errorHandler).toHaveBeenCalledTimes(1);
363
+ expect(errorHandler.mock.calls[0][0].name).toBe('ValidatedStream');
364
+ expect(errorHandler.mock.calls[0][2].message).toContain('Validation error');
351
365
  });
352
366
  test('errors during streaming are sent as error events (SSE mode)', async () => {
353
367
  const builder = new HonoStreamAppBuilder();
@@ -380,6 +394,150 @@ describe('HonoStreamAppBuilder', () => {
380
394
  // Error is wrapped by Procedures with "Error in streaming handler for {name}" prefix
381
395
  expect(JSON.parse(lines[1]).error).toContain('Stream error');
382
396
  });
397
+ test('validation errors return 400 by default when no error handler', async () => {
398
+ const builder = new HonoStreamAppBuilder();
399
+ const RPC = Procedures();
400
+ RPC.CreateStream('ValidatedStream', {
401
+ scope: 'validated',
402
+ version: 1,
403
+ schema: {
404
+ params: v.object({ count: v.number() }),
405
+ },
406
+ }, async function* (ctx, params) {
407
+ yield { count: params.count };
408
+ });
409
+ builder.register(RPC, () => ({}));
410
+ const app = builder.build();
411
+ const res = await app.request('/validated/validated-stream/1?count=not-a-number');
412
+ // Default: returns 400 JSON error
413
+ expect(res.status).toBe(400);
414
+ const body = await res.json();
415
+ expect(body.error).toContain('Validation error');
416
+ });
417
+ // Tests for onPreStreamError and onMidStreamError callbacks
418
+ test('onPreStreamError handles validation errors with custom Response', async () => {
419
+ const onPreStreamError = vi.fn((procedure, c, error) => {
420
+ return c.json({ customError: true, procedureName: procedure.name, details: error.message }, 422);
421
+ });
422
+ const builder = new HonoStreamAppBuilder({ onPreStreamError });
423
+ const RPC = Procedures();
424
+ RPC.CreateStream('ValidatedStream', {
425
+ scope: 'validated',
426
+ version: 1,
427
+ schema: {
428
+ params: v.object({ count: v.number() }),
429
+ },
430
+ }, async function* (ctx, params) {
431
+ yield { count: params.count };
432
+ });
433
+ builder.register(RPC, () => ({}));
434
+ const app = builder.build();
435
+ const res = await app.request('/validated/validated-stream/1?count=not-a-number');
436
+ expect(res.status).toBe(422);
437
+ const body = await res.json();
438
+ expect(body.customError).toBe(true);
439
+ expect(body.procedureName).toBe('ValidatedStream');
440
+ expect(body.details).toContain('Validation error');
441
+ expect(onPreStreamError).toHaveBeenCalledTimes(1);
442
+ });
443
+ test('onPreStreamError handles context resolution errors', async () => {
444
+ const onPreStreamError = vi.fn((procedure, c, error) => {
445
+ return c.json({ contextError: error.message }, 401);
446
+ });
447
+ const builder = new HonoStreamAppBuilder({ onPreStreamError });
448
+ const RPC = Procedures();
449
+ RPC.CreateStream('SecureStream', { scope: 'secure', version: 1 }, async function* (ctx) {
450
+ yield { userId: ctx.userId };
451
+ });
452
+ builder.register(RPC, () => {
453
+ throw new Error('Authentication required');
454
+ });
455
+ const app = builder.build();
456
+ const res = await app.request('/secure/secure-stream/1');
457
+ expect(res.status).toBe(401);
458
+ const body = await res.json();
459
+ expect(body.contextError).toBe('Authentication required');
460
+ expect(onPreStreamError).toHaveBeenCalledTimes(1);
461
+ });
462
+ test('onMidStreamError returns custom value written to SSE stream', async () => {
463
+ const onMidStreamError = vi.fn((procedure, c, error) => {
464
+ return {
465
+ value: {
466
+ type: 'error',
467
+ code: 'STREAM_FAILED',
468
+ message: error.message,
469
+ retryable: false,
470
+ },
471
+ closeStream: true,
472
+ };
473
+ });
474
+ const builder = new HonoStreamAppBuilder({ onMidStreamError });
475
+ const RPC = Procedures();
476
+ RPC.CreateStream('ErrorStream', { scope: 'error', version: 1 }, async function* () {
477
+ yield { type: 'data', value: 1 };
478
+ throw new Error('Something broke');
479
+ });
480
+ builder.register(RPC, () => ({}));
481
+ const app = builder.build();
482
+ const res = await app.request('/error/error-stream/1');
483
+ const text = await res.text();
484
+ // First yield should be present
485
+ expect(text).toContain('data: {"type":"data","value":1}');
486
+ // Error should use custom format from onMidStreamError
487
+ expect(text).toContain('data: {"type":"error","code":"STREAM_FAILED"');
488
+ expect(text).toContain('"retryable":false');
489
+ // Event should use procedure name (not 'error') since custom value provided
490
+ expect(text).toContain('event: ErrorStream');
491
+ expect(onMidStreamError).toHaveBeenCalledTimes(1);
492
+ });
493
+ test('onMidStreamError returns custom value written to text stream', async () => {
494
+ const onMidStreamError = vi.fn((procedure, c, error) => {
495
+ return {
496
+ value: { type: 'error', message: error.message },
497
+ };
498
+ });
499
+ const builder = new HonoStreamAppBuilder({
500
+ defaultStreamMode: 'text',
501
+ onMidStreamError,
502
+ });
503
+ const RPC = Procedures();
504
+ RPC.CreateStream('ErrorStream', { scope: 'error', version: 1 }, async function* () {
505
+ yield { type: 'data', value: 'hello' };
506
+ throw new Error('Stream failed');
507
+ });
508
+ builder.register(RPC, () => ({}));
509
+ const app = builder.build();
510
+ const res = await app.request('/error/error-stream/1');
511
+ const text = await res.text();
512
+ const lines = text.trim().split('\n');
513
+ expect(JSON.parse(lines[0])).toEqual({ type: 'data', value: 'hello' });
514
+ // Error message may be wrapped by Procedures with "Error in streaming handler for X - " prefix
515
+ const errorLine = JSON.parse(lines[1]);
516
+ expect(errorLine.type).toBe('error');
517
+ expect(errorLine.message).toContain('Stream failed');
518
+ expect(onMidStreamError).toHaveBeenCalledTimes(1);
519
+ });
520
+ test('onMidStreamError returning undefined falls back to default error format', async () => {
521
+ const onMidStreamError = vi.fn(() => undefined);
522
+ const builder = new HonoStreamAppBuilder({
523
+ defaultStreamMode: 'text',
524
+ onMidStreamError,
525
+ });
526
+ const RPC = Procedures();
527
+ RPC.CreateStream('ErrorStream', { scope: 'error', version: 1 }, async function* () {
528
+ yield { value: 1 };
529
+ throw new Error('Fallback test');
530
+ });
531
+ builder.register(RPC, () => ({}));
532
+ const app = builder.build();
533
+ const res = await app.request('/error/error-stream/1');
534
+ const text = await res.text();
535
+ const lines = text.trim().split('\n');
536
+ expect(JSON.parse(lines[0])).toEqual({ value: 1 });
537
+ // Falls back to default { error: message } format
538
+ expect(JSON.parse(lines[1]).error).toContain('Fallback test');
539
+ expect(onMidStreamError).toHaveBeenCalledTimes(1);
540
+ });
383
541
  });
384
542
  // --------------------------------------------------------------------------
385
543
  // Context Resolution Tests
@@ -622,6 +780,75 @@ describe('HonoStreamAppBuilder', () => {
622
780
  });
623
781
  });
624
782
  // --------------------------------------------------------------------------
783
+ // isPrevalidated Tests
784
+ // --------------------------------------------------------------------------
785
+ describe('isPrevalidated context property', () => {
786
+ test('passes isPrevalidated: true to procedure handler to skip double validation', async () => {
787
+ let receivedIsPrevalidated;
788
+ const builder = new HonoStreamAppBuilder({ defaultStreamMode: 'text' });
789
+ const RPC = Procedures();
790
+ RPC.CreateStream('CheckPrevalidated', { scope: 'check', version: 1 }, async function* (ctx) {
791
+ receivedIsPrevalidated = ctx.isPrevalidated;
792
+ yield { ok: true };
793
+ });
794
+ builder.register(RPC, () => ({}));
795
+ const app = builder.build();
796
+ const res = await app.request('/check/check-prevalidated/1');
797
+ await res.text();
798
+ expect(receivedIsPrevalidated).toBe(true);
799
+ });
800
+ test('valid params work correctly with pre-validation flow', async () => {
801
+ const builder = new HonoStreamAppBuilder({ defaultStreamMode: 'text' });
802
+ const RPC = Procedures();
803
+ RPC.CreateStream('ValidParams', {
804
+ scope: 'valid',
805
+ version: 1,
806
+ schema: {
807
+ params: v.object({ count: v.number() }),
808
+ },
809
+ }, async function* (ctx, params) {
810
+ const count = params.count ?? 0;
811
+ for (let i = 0; i < count; i++) {
812
+ yield { index: i };
813
+ }
814
+ });
815
+ builder.register(RPC, () => ({}));
816
+ const app = builder.build();
817
+ // With valid params, both HonoStreamAppBuilder validation and procedure validation should work
818
+ const res = await app.request('/valid/valid-params/1?count=2');
819
+ expect(res.status).toBe(200);
820
+ const text = await res.text();
821
+ const lines = text.trim().split('\n');
822
+ expect(lines).toHaveLength(2);
823
+ expect(JSON.parse(lines[0])).toEqual({ index: 0 });
824
+ expect(JSON.parse(lines[1])).toEqual({ index: 1 });
825
+ });
826
+ test('invalid params are caught by HonoStreamAppBuilder before handler runs', async () => {
827
+ let handlerCalled = false;
828
+ const builder = new HonoStreamAppBuilder({ defaultStreamMode: 'text' });
829
+ const RPC = Procedures();
830
+ RPC.CreateStream('InvalidParams', {
831
+ scope: 'invalid',
832
+ version: 1,
833
+ schema: {
834
+ params: v.object({ count: v.number() }),
835
+ },
836
+ }, async function* () {
837
+ handlerCalled = true;
838
+ yield { ok: true };
839
+ });
840
+ builder.register(RPC, () => ({}));
841
+ const app = builder.build();
842
+ // With invalid params, HonoStreamAppBuilder catches the error before streaming starts
843
+ const res = await app.request('/invalid/invalid-params/1?count=not-a-number');
844
+ expect(res.status).toBe(400);
845
+ const body = await res.json();
846
+ expect(body.error).toContain('Validation error');
847
+ // Handler should never be called since validation fails before streaming
848
+ expect(handlerCalled).toBe(false);
849
+ });
850
+ });
851
+ // --------------------------------------------------------------------------
625
852
  // Integration Test
626
853
  // --------------------------------------------------------------------------
627
854
  describe('integration', () => {