1
1
import type { Patch } from 'immer' ;
2
2
import sinon from 'sinon' ;
3
3
4
- import { Messenger } from './Messenger' ;
4
+ import { Messenger , DISABLE_NAMESPACE } from './Messenger' ;
5
5
6
6
describe ( 'Messenger' , ( ) => {
7
7
afterEach ( ( ) => {
@@ -27,6 +27,24 @@ describe('Messenger', () => {
27
27
expect ( count ) . toBe ( 1 ) ;
28
28
} ) ;
29
29
30
+ it ( 'allows registering and calling an action handler for a different namespace using DISABLE_NAMESPACE' , ( ) => {
31
+ type CountAction = {
32
+ type : 'Fixture:count' ;
33
+ handler : ( increment : number ) => void ;
34
+ } ;
35
+ const messenger = new Messenger < string , CountAction , never > ( {
36
+ namespace : DISABLE_NAMESPACE ,
37
+ } ) ;
38
+
39
+ let count = 0 ;
40
+ messenger . registerActionHandler ( 'Fixture:count' , ( increment : number ) => {
41
+ count += increment ;
42
+ } ) ;
43
+ messenger . call ( 'Fixture:count' , 1 ) ;
44
+
45
+ expect ( count ) . toBe ( 1 ) ;
46
+ } ) ;
47
+
30
48
it ( 'automatically delegates actions to parent upon registration' , ( ) => {
31
49
type CountAction = {
32
50
type : 'Fixture:count' ;
@@ -168,6 +186,67 @@ describe('Messenger', () => {
168
186
} ) . toThrow ( 'A handler for Fixture:ping has not been registered' ) ;
169
187
} ) ;
170
188
189
+ it ( 'throws when registering an action handler for a different namespace' , ( ) => {
190
+ type CountAction = {
191
+ type : 'Fixture:count' ;
192
+ handler : ( increment : number ) => void ;
193
+ } ;
194
+ const messenger = new Messenger < 'Different' , CountAction , never > ( {
195
+ namespace : 'Different' ,
196
+ } ) ;
197
+
198
+ expect ( ( ) =>
199
+ // @ts -expect-error Intentionally invalid parameter
200
+ messenger . registerActionHandler ( 'Fixture:count' , jest . fn ( ) ) ,
201
+ ) . toThrow (
202
+ `Only allowed registering action handlers prefixed by 'Different:'` ,
203
+ ) ;
204
+ } ) ;
205
+
206
+ it ( 'throws when unregistering an action handler for a different namespace' , ( ) => {
207
+ type CountAction = {
208
+ type : 'Source:count' ;
209
+ handler : ( increment : number ) => void ;
210
+ } ;
211
+ const sourceMessenger = new Messenger < 'Source' , CountAction , never > ( {
212
+ namespace : 'Source' ,
213
+ } ) ;
214
+ const messenger = new Messenger < 'Destination' , CountAction , never > ( {
215
+ namespace : 'Destination' ,
216
+ } ) ;
217
+ sourceMessenger . delegate ( { actions : [ 'Source:count' ] , messenger } ) ;
218
+
219
+ expect ( ( ) =>
220
+ // @ts -expect-error Intentionally invalid parameter
221
+ messenger . unregisterActionHandler ( 'Source:count' ) ,
222
+ ) . toThrow (
223
+ `Only allowed unregistering action handlers prefixed by 'Destination:'` ,
224
+ ) ;
225
+ } ) ;
226
+
227
+ it ( 'throws when calling an action from a different namespace that has been unregistered using DISABLE_NAMESPACE' , ( ) => {
228
+ type PingAction = { type : 'Fixture:ping' ; handler : ( ) => void } ;
229
+ const messenger = new Messenger < string , PingAction , never > ( {
230
+ namespace : DISABLE_NAMESPACE ,
231
+ } ) ;
232
+
233
+ expect ( ( ) => {
234
+ messenger . call ( 'Fixture:ping' ) ;
235
+ } ) . toThrow ( 'A handler for Fixture:ping has not been registered' ) ;
236
+
237
+ let pingCount = 0 ;
238
+ messenger . registerActionHandler ( 'Fixture:ping' , ( ) => {
239
+ pingCount += 1 ;
240
+ } ) ;
241
+
242
+ messenger . unregisterActionHandler ( 'Fixture:ping' ) ;
243
+
244
+ expect ( ( ) => {
245
+ messenger . call ( 'Fixture:ping' ) ;
246
+ } ) . toThrow ( 'A handler for Fixture:ping has not been registered' ) ;
247
+ expect ( pingCount ) . toBe ( 0 ) ;
248
+ } ) ;
249
+
171
250
it ( 'throws when calling an action that has been unregistered' , ( ) => {
172
251
type PingAction = { type : 'Fixture:ping' ; handler : ( ) => void } ;
173
252
const messenger = new Messenger < 'Fixture' , PingAction , never > ( {
@@ -259,6 +338,20 @@ describe('Messenger', () => {
259
338
expect ( handler . callCount ) . toBe ( 1 ) ;
260
339
} ) ;
261
340
341
+ it ( 'publishes event from different namespace using DISABLE_NAMESPACE' , ( ) => {
342
+ type MessageEvent = { type : 'Fixture:message' ; payload : [ string ] } ;
343
+ const messenger = new Messenger < string , never , MessageEvent > ( {
344
+ namespace : DISABLE_NAMESPACE ,
345
+ } ) ;
346
+
347
+ const handler = sinon . stub ( ) ;
348
+ messenger . subscribe ( 'Fixture:message' , handler ) ;
349
+ messenger . publish ( 'Fixture:message' , 'hello' ) ;
350
+
351
+ expect ( handler . calledWithExactly ( 'hello' ) ) . toBe ( true ) ;
352
+ expect ( handler . callCount ) . toBe ( 1 ) ;
353
+ } ) ;
354
+
262
355
it ( 'automatically delegates events to parent upon first publish' , ( ) => {
263
356
type MessageEvent = { type : 'Fixture:message' ; payload : [ string ] } ;
264
357
const parentMessenger = new Messenger < 'Parent' , never , MessageEvent > ( {
@@ -428,6 +521,66 @@ describe('Messenger', () => {
428
521
} ) ;
429
522
} ) ;
430
523
524
+ describe ( 'on first state change with an initial payload function from another namespace registered (using DISABLE_NAMESPACE)' , ( ) => {
525
+ it ( 'publishes event if selected payload differs' , ( ) => {
526
+ const state = {
527
+ propA : 1 ,
528
+ propB : 1 ,
529
+ } ;
530
+ type MessageEvent = {
531
+ type : 'Fixture:complexMessage' ;
532
+ payload : [ typeof state ] ;
533
+ } ;
534
+ const messenger = new Messenger < string , never , MessageEvent > ( {
535
+ namespace : DISABLE_NAMESPACE ,
536
+ } ) ;
537
+ messenger . registerInitialEventPayload ( {
538
+ eventType : 'Fixture:complexMessage' ,
539
+ getPayload : ( ) => [ state ] ,
540
+ } ) ;
541
+ const handler = sinon . stub ( ) ;
542
+ messenger . subscribe (
543
+ 'Fixture:complexMessage' ,
544
+ handler ,
545
+ ( obj ) => obj . propA ,
546
+ ) ;
547
+
548
+ state . propA += 1 ;
549
+ messenger . publish ( 'Fixture:complexMessage' , state ) ;
550
+
551
+ expect ( handler . getCall ( 0 ) ?. args ) . toStrictEqual ( [ 2 , 1 ] ) ;
552
+ expect ( handler . callCount ) . toBe ( 1 ) ;
553
+ } ) ;
554
+
555
+ it ( 'does not publish event if selected payload is the same' , ( ) => {
556
+ const state = {
557
+ propA : 1 ,
558
+ propB : 1 ,
559
+ } ;
560
+ type MessageEvent = {
561
+ type : 'Fixture:complexMessage' ;
562
+ payload : [ typeof state ] ;
563
+ } ;
564
+ const messenger = new Messenger < string , never , MessageEvent > ( {
565
+ namespace : DISABLE_NAMESPACE ,
566
+ } ) ;
567
+ messenger . registerInitialEventPayload ( {
568
+ eventType : 'Fixture:complexMessage' ,
569
+ getPayload : ( ) => [ state ] ,
570
+ } ) ;
571
+ const handler = sinon . stub ( ) ;
572
+ messenger . subscribe (
573
+ 'Fixture:complexMessage' ,
574
+ handler ,
575
+ ( obj ) => obj . propA ,
576
+ ) ;
577
+
578
+ messenger . publish ( 'Fixture:complexMessage' , state ) ;
579
+
580
+ expect ( handler . callCount ) . toBe ( 0 ) ;
581
+ } ) ;
582
+ } ) ;
583
+
431
584
describe ( 'on first state change without an initial payload function registered' , ( ) => {
432
585
it ( 'publishes event if selected payload differs' , ( ) => {
433
586
const state = {
@@ -727,6 +880,42 @@ describe('Messenger', () => {
727
880
expect ( stub . callCount ) . toBe ( 0 ) ;
728
881
} ) ;
729
882
883
+ it ( 'throws when publishing an event from another namespace' , ( ) => {
884
+ type MessageEvent = { type : 'Fixture:message' ; payload : [ string ] } ;
885
+ const messenger = new Messenger < 'Other' , never , MessageEvent > ( {
886
+ namespace : 'Other' ,
887
+ } ) ;
888
+ const handler = jest . fn ( ) ;
889
+ messenger . subscribe ( 'Fixture:message' , handler ) ;
890
+
891
+ // @ts -expect-error Intentionally invalid parameter
892
+ expect ( ( ) => messenger . publish ( 'Fixture:message' , 'hello' ) ) . toThrow (
893
+ `Only allowed publishing events prefixed by 'Other:'` ,
894
+ ) ;
895
+ expect ( handler ) . not . toHaveBeenCalled ( ) ;
896
+ } ) ;
897
+
898
+ it ( 'throws when registering an initial event payload from another namespace' , ( ) => {
899
+ type MessageEvent = {
900
+ type : 'Fixture:complexMessage' ;
901
+ payload : [ null ] ;
902
+ } ;
903
+ const messenger = new Messenger < 'Other' , never , MessageEvent > ( {
904
+ namespace : 'Other' ,
905
+ } ) ;
906
+
907
+ expect ( ( ) =>
908
+ messenger . registerInitialEventPayload ( {
909
+ // @ts -expect-error Intentionally invalid parameter
910
+ eventType : 'Fixture:complexMessage' ,
911
+ // @ts -expect-error Intentionally invalid parameter
912
+ getPayload : ( ) => [ null ] ,
913
+ } ) ,
914
+ ) . toThrow (
915
+ `Only allowed registering initial payloads for events prefixed by 'Other:'` ,
916
+ ) ;
917
+ } ) ;
918
+
730
919
it ( 'throws when unsubscribing when there are no subscriptions' , ( ) => {
731
920
type MessageEvent = { type : 'Fixture:message' ; payload : [ string ] } ;
732
921
const messenger = new Messenger < 'Fixture' , never , MessageEvent > ( {
0 commit comments