1
1
import 'dart:convert' ;
2
2
import 'dart:io' ;
3
3
4
+ import 'package:crypto/crypto.dart' ;
4
5
import 'package:mocktail/mocktail.dart' ;
5
6
import 'package:realtime_client/realtime_client.dart' ;
6
7
import 'package:realtime_client/src/constants.dart' ;
@@ -16,6 +17,31 @@ typedef WebSocketChannelClosure = WebSocketChannel Function(
16
17
Map <String , String > headers,
17
18
);
18
19
20
+ /// Generate a JWT token for testing purposes
21
+ ///
22
+ /// [exp] in seconds since Epoch
23
+ String generateJwt ([int ? exp]) {
24
+ final header = {'alg' : 'HS256' , 'typ' : 'JWT' };
25
+
26
+ final now = DateTime .now ();
27
+ final expiry = exp ??
28
+ (now.add (Duration (hours: 1 )).millisecondsSinceEpoch / 1000 ).floor ();
29
+
30
+ final payload = {'exp' : expiry};
31
+
32
+ final key = 'your-256-bit-secret' ;
33
+
34
+ final encodedHeader = base64Url.encode (utf8.encode (json.encode (header)));
35
+ final encodedPayload = base64Url.encode (utf8.encode (json.encode (payload)));
36
+
37
+ final signatureInput = '$encodedHeader .$encodedPayload ' ;
38
+ final hmac = Hmac (sha256, utf8.encode (key));
39
+ final digest = hmac.convert (utf8.encode (signatureInput));
40
+ final signature = base64Url.encode (digest.bytes);
41
+
42
+ return '$encodedHeader .$encodedPayload .$signature ' ;
43
+ }
44
+
19
45
void main () {
20
46
const int int64MaxValue = 9223372036854775807 ;
21
47
@@ -174,7 +200,7 @@ void main() {
174
200
await Future .delayed (const Duration (milliseconds: 200 ));
175
201
expect (opens, 1 );
176
202
177
- socket.sendHeartbeat ();
203
+ await socket.sendHeartbeat ();
178
204
// need to wait for event to trigger
179
205
await Future .delayed (const Duration (seconds: 1 ));
180
206
expect (lastMsg['event' ], 'heartbeat' );
@@ -427,12 +453,13 @@ void main() {
427
453
});
428
454
429
455
group ('setAuth' , () {
430
- final updateJoinPayload = {'access_token' : 'token123' };
431
- final pushPayload = {'access_token' : 'token123' };
456
+ final token = generateJwt ();
457
+ final updateJoinPayload = {'access_token' : token};
458
+ final pushPayload = {'access_token' : token};
432
459
433
460
test (
434
461
"sets access token, updates channels' join payload, and pushes token to channels" ,
435
- () {
462
+ () async {
436
463
final mockedChannel1 = MockChannel ();
437
464
when (() => mockedChannel1.joinedOnce).thenReturn (true );
438
465
when (() => mockedChannel1.isJoined).thenReturn (true );
@@ -457,7 +484,9 @@ void main() {
457
484
final channel1 = mockedSocket.channel (tTopic1);
458
485
final channel2 = mockedSocket.channel (tTopic2);
459
486
460
- mockedSocket.setAuth ('token123' );
487
+ await mockedSocket.setAuth (token);
488
+
489
+ expect (mockedSocket.accessToken, token);
461
490
462
491
verify (() => channel1.updateJoinPayload (updateJoinPayload)).called (1 );
463
492
verify (() => channel2.updateJoinPayload (updateJoinPayload)).called (1 );
@@ -466,6 +495,62 @@ void main() {
466
495
verify (() => channel2.push (ChannelEvents .accessToken, pushPayload))
467
496
.called (1 );
468
497
});
498
+
499
+ test (
500
+ "sets access token, updates channels' join payload, and pushes token to channels if is not a jwt" ,
501
+ () async {
502
+ final mockedChannel1 = MockChannel ();
503
+ final mockedChannel2 = MockChannel ();
504
+ final mockedChannel3 = MockChannel ();
505
+
506
+ when (() => mockedChannel1.joinedOnce).thenReturn (true );
507
+ when (() => mockedChannel1.isJoined).thenReturn (true );
508
+ when (() => mockedChannel1.push (ChannelEvents .accessToken, any ()))
509
+ .thenReturn (MockPush ());
510
+
511
+ when (() => mockedChannel2.joinedOnce).thenReturn (false );
512
+ when (() => mockedChannel2.isJoined).thenReturn (false );
513
+ when (() => mockedChannel2.push (ChannelEvents .accessToken, any ()))
514
+ .thenReturn (MockPush ());
515
+
516
+ when (() => mockedChannel3.joinedOnce).thenReturn (true );
517
+ when (() => mockedChannel3.isJoined).thenReturn (true );
518
+ when (() => mockedChannel3.push (ChannelEvents .accessToken, any ()))
519
+ .thenReturn (MockPush ());
520
+
521
+ const tTopic1 = 'test-topic1' ;
522
+ const tTopic2 = 'test-topic2' ;
523
+ const tTopic3 = 'test-topic3' ;
524
+
525
+ final mockedSocket = SocketWithMockedChannel (socketEndpoint);
526
+ mockedSocket.mockedChannelLooker.addAll (< String , RealtimeChannel > {
527
+ tTopic1: mockedChannel1,
528
+ tTopic2: mockedChannel2,
529
+ tTopic3: mockedChannel3,
530
+ });
531
+
532
+ final channel1 = mockedSocket.channel (tTopic1);
533
+ final channel2 = mockedSocket.channel (tTopic2);
534
+ final channel3 = mockedSocket.channel (tTopic3);
535
+
536
+ const token = 'sb-key' ;
537
+ final pushPayload = {'access_token' : token};
538
+ final updateJoinPayload = {'access_token' : token};
539
+
540
+ await mockedSocket.setAuth (token);
541
+
542
+ expect (mockedSocket.accessToken, token);
543
+
544
+ verify (() => channel1.updateJoinPayload (updateJoinPayload)).called (1 );
545
+ verify (() => channel2.updateJoinPayload (updateJoinPayload)).called (1 );
546
+ verify (() => channel3.updateJoinPayload (updateJoinPayload)).called (1 );
547
+
548
+ verify (() => channel1.push (ChannelEvents .accessToken, pushPayload))
549
+ .called (1 );
550
+ verifyNever (() => channel2.push (ChannelEvents .accessToken, pushPayload));
551
+ verify (() => channel3.push (ChannelEvents .accessToken, pushPayload))
552
+ .called (1 );
553
+ });
469
554
});
470
555
471
556
group ('sendHeartbeat' , () {
@@ -496,18 +581,18 @@ void main() {
496
581
497
582
//! Unimplemented Test: closes socket when heartbeat is not ack'd within heartbeat window
498
583
499
- test ('pushes heartbeat data when connected' , () {
584
+ test ('pushes heartbeat data when connected' , () async {
500
585
mockedSocket.connState = SocketStates .open;
501
586
502
- mockedSocket.sendHeartbeat ();
587
+ await mockedSocket.sendHeartbeat ();
503
588
504
589
verify (() => mockedSink.add (captureAny (that: equals (data)))).called (1 );
505
590
});
506
591
507
- test ('no ops when not connected' , () {
592
+ test ('no ops when not connected' , () async {
508
593
mockedSocket.connState = SocketStates .connecting;
509
594
510
- mockedSocket.sendHeartbeat ();
595
+ await mockedSocket.sendHeartbeat ();
511
596
verifyNever (() => mockedSink.add (any ()));
512
597
});
513
598
});
0 commit comments