Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

Commit 99a48d5

Browse files
authored
Merge pull request #464 from beyondcode/tests/redis-connector
[2.x] Redis connector tests
2 parents 38b2e4d + c2cec0e commit 99a48d5

8 files changed

+669
-32
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"cboden/ratchet": "^0.4.1",
2828
"clue/buzz-react": "^2.5",
2929
"clue/redis-react": "^2.3",
30+
"evenement/evenement": "^2.0|^3.0",
3031
"facade/ignition-contracts": "^1.0",
3132
"guzzlehttp/psr7": "^1.5",
3233
"illuminate/broadcasting": "^6.0|^7.0",

tests/Channels/ChannelReplicationTest.php

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
44

5+
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
56
use BeyondCode\LaravelWebSockets\Tests\TestCase;
67

78
class ChannelReplicationTest extends TestCase
@@ -16,10 +17,142 @@ public function setUp(): void
1617
$this->runOnlyOnRedisReplication();
1718
}
1819

19-
public function test_not_implemented()
20+
/** @test */
21+
public function replication_clients_can_subscribe_to_channels()
2022
{
21-
$this->markTestIncomplete(
22-
'Not yet implemented tests.'
23-
);
23+
$connection = $this->getWebSocketConnection();
24+
25+
$message = new Message(json_encode([
26+
'event' => 'pusher:subscribe',
27+
'data' => [
28+
'channel' => 'basic-channel',
29+
],
30+
]));
31+
32+
$this->pusherServer->onOpen($connection);
33+
34+
$this->pusherServer->onMessage($connection, $message);
35+
36+
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
37+
'channel' => 'basic-channel',
38+
]);
39+
}
40+
41+
/** @test */
42+
public function replication_clients_can_unsubscribe_from_channels()
43+
{
44+
$connection = $this->getConnectedWebSocketConnection(['test-channel']);
45+
46+
$channel = $this->getChannel($connection, 'test-channel');
47+
48+
$this->assertTrue($channel->hasConnections());
49+
50+
$message = new Message(json_encode([
51+
'event' => 'pusher:unsubscribe',
52+
'data' => [
53+
'channel' => 'test-channel',
54+
],
55+
]));
56+
57+
$this->pusherServer->onMessage($connection, $message);
58+
59+
$this->assertFalse($channel->hasConnections());
60+
}
61+
62+
/** @test */
63+
public function replication_a_client_cannot_broadcast_to_other_clients_by_default()
64+
{
65+
// One connection inside channel "test-channel".
66+
$existingConnection = $this->getConnectedWebSocketConnection(['test-channel']);
67+
68+
$connection = $this->getConnectedWebSocketConnection(['test-channel']);
69+
70+
$message = new Message('{"event": "client-test", "data": {}, "channel": "test-channel"}');
71+
72+
$this->pusherServer->onMessage($connection, $message);
73+
74+
$existingConnection->assertNotSentEvent('client-test');
75+
}
76+
77+
/** @test */
78+
public function replication_a_client_can_be_enabled_to_broadcast_to_other_clients()
79+
{
80+
config()->set('websockets.apps.0.enable_client_messages', true);
81+
82+
// One connection inside channel "test-channel".
83+
$existingConnection = $this->getConnectedWebSocketConnection(['test-channel']);
84+
85+
$connection = $this->getConnectedWebSocketConnection(['test-channel']);
86+
87+
$message = new Message('{"event": "client-test", "data": {}, "channel": "test-channel"}');
88+
89+
$this->pusherServer->onMessage($connection, $message);
90+
91+
$existingConnection->assertSentEvent('client-test');
92+
}
93+
94+
/** @test */
95+
public function replication_closed_connections_get_removed_from_all_connected_channels()
96+
{
97+
$connection = $this->getConnectedWebSocketConnection(['test-channel-1', 'test-channel-2']);
98+
99+
$channel1 = $this->getChannel($connection, 'test-channel-1');
100+
$channel2 = $this->getChannel($connection, 'test-channel-2');
101+
102+
$this->assertTrue($channel1->hasConnections());
103+
$this->assertTrue($channel2->hasConnections());
104+
105+
$this->pusherServer->onClose($connection);
106+
107+
$this->assertFalse($channel1->hasConnections());
108+
$this->assertFalse($channel2->hasConnections());
109+
}
110+
111+
/** @test */
112+
public function replication_channels_can_broadcast_messages_to_all_connections()
113+
{
114+
$connection1 = $this->getConnectedWebSocketConnection(['test-channel']);
115+
$connection2 = $this->getConnectedWebSocketConnection(['test-channel']);
116+
117+
$channel = $this->getChannel($connection1, 'test-channel');
118+
119+
$channel->broadcast([
120+
'event' => 'broadcasted-event',
121+
'channel' => 'test-channel',
122+
]);
123+
124+
$connection1->assertSentEvent('broadcasted-event');
125+
$connection2->assertSentEvent('broadcasted-event');
126+
}
127+
128+
/** @test */
129+
public function replication_channels_can_broadcast_messages_to_all_connections_except_the_given_connection()
130+
{
131+
$connection1 = $this->getConnectedWebSocketConnection(['test-channel']);
132+
$connection2 = $this->getConnectedWebSocketConnection(['test-channel']);
133+
134+
$channel = $this->getChannel($connection1, 'test-channel');
135+
136+
$channel->broadcastToOthers($connection1, (object) [
137+
'event' => 'broadcasted-event',
138+
'channel' => 'test-channel',
139+
]);
140+
141+
$connection1->assertNotSentEvent('broadcasted-event');
142+
$connection2->assertSentEvent('broadcasted-event');
143+
}
144+
145+
/** @test */
146+
public function replication_it_responds_correctly_to_the_ping_message()
147+
{
148+
$connection = $this->getConnectedWebSocketConnection();
149+
150+
$message = new Message(json_encode([
151+
'event' => 'pusher:ping',
152+
]));
153+
154+
$this->pusherServer->onMessage($connection, $message);
155+
156+
$connection->assertSentEvent('pusher:pong');
24157
}
25158
}

tests/Channels/PresenceChannelReplicationTest.php

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,87 @@ public function clients_with_valid_auth_signatures_can_join_presence_channels()
5050
$connection->socketId,
5151
json_encode($channelData),
5252
])
53-
->assertCalledWithArgs('hgetall', [
54-
'1234:presence-channel',
55-
]);
56-
// TODO: This fails somehow
57-
// Debugging shows the exact same pattern as good.
58-
/* ->assertCalledWithArgs('publish', [
59-
'1234:presence-channel',
60-
json_encode([
61-
'event' => 'pusher_internal:member_added',
62-
'channel' => 'presence-channel',
63-
'data' => $channelData,
64-
'appId' => '1234',
65-
'serverId' => $this->app->make(ReplicationInterface::class)->getServerId(),
66-
]),
67-
]) */
53+
->assertCalledWithArgs('hgetall', ['1234:presence-channel'])
54+
->assertCalled('publish');
55+
}
56+
57+
/** @test */
58+
public function clients_with_valid_auth_signatures_can_leave_presence_channels()
59+
{
60+
$connection = $this->getWebSocketConnection();
61+
62+
$this->pusherServer->onOpen($connection);
63+
64+
$channelData = [
65+
'user_id' => 1,
66+
];
67+
68+
$signature = "{$connection->socketId}:presence-channel:".json_encode($channelData);
69+
70+
$message = new Message(json_encode([
71+
'event' => 'pusher:subscribe',
72+
'data' => [
73+
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
74+
'channel' => 'presence-channel',
75+
'channel_data' => json_encode($channelData),
76+
],
77+
]));
78+
79+
$this->pusherServer->onMessage($connection, $message);
80+
81+
$this->getSubscribeClient()
82+
->assertEventDispatched('message');
83+
84+
$this->getPublishClient()
85+
->assertCalled('hset')
86+
->assertCalledWithArgs('hgetall', ['1234:presence-channel'])
87+
->assertCalled('publish');
88+
89+
$this->getPublishClient()
90+
->resetAssertions();
91+
92+
$message = new Message(json_encode([
93+
'event' => 'pusher:unsubscribe',
94+
'data' => [
95+
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
96+
'channel' => 'presence-channel',
97+
],
98+
]));
99+
100+
$this->pusherServer->onMessage($connection, $message);
101+
102+
$this->getPublishClient()
103+
->assertCalled('hdel')
104+
->assertCalled('publish');
105+
}
106+
107+
/** @test */
108+
public function clients_with_no_user_info_can_join_presence_channels()
109+
{
110+
$connection = $this->getWebSocketConnection();
111+
112+
$this->pusherServer->onOpen($connection);
113+
114+
$channelData = [
115+
'user_id' => 1,
116+
];
117+
118+
$signature = "{$connection->socketId}:presence-channel:".json_encode($channelData);
119+
120+
$message = new Message(json_encode([
121+
'event' => 'pusher:subscribe',
122+
'data' => [
123+
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
124+
'channel' => 'presence-channel',
125+
'channel_data' => json_encode($channelData),
126+
],
127+
]));
128+
129+
$this->pusherServer->onMessage($connection, $message);
130+
131+
$this->getPublishClient()
132+
->assertCalled('hset')
133+
->assertcalledWithArgs('hgetall', ['1234:presence-channel'])
134+
->assertCalled('publish');
68135
}
69136
}

tests/Channels/PrivateChannelReplicationTest.php

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
44

5+
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
56
use BeyondCode\LaravelWebSockets\Tests\TestCase;
7+
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
68

79
class PrivateChannelReplicationTest extends TestCase
810
{
@@ -16,10 +18,49 @@ public function setUp(): void
1618
$this->runOnlyOnRedisReplication();
1719
}
1820

19-
public function test_not_implemented()
21+
/** @test */
22+
public function replication_clients_need_valid_auth_signatures_to_join_private_channels()
2023
{
21-
$this->markTestIncomplete(
22-
'Not yet implemented tests.'
23-
);
24+
$this->expectException(InvalidSignature::class);
25+
26+
$connection = $this->getWebSocketConnection();
27+
28+
$message = new Message(json_encode([
29+
'event' => 'pusher:subscribe',
30+
'data' => [
31+
'auth' => 'invalid',
32+
'channel' => 'private-channel',
33+
],
34+
]));
35+
36+
$this->pusherServer->onOpen($connection);
37+
38+
$this->pusherServer->onMessage($connection, $message);
39+
}
40+
41+
/** @test */
42+
public function replication_clients_with_valid_auth_signatures_can_join_private_channels()
43+
{
44+
$connection = $this->getWebSocketConnection();
45+
46+
$this->pusherServer->onOpen($connection);
47+
48+
$signature = "{$connection->socketId}:private-channel";
49+
50+
$hashedAppSecret = hash_hmac('sha256', $signature, $connection->app->secret);
51+
52+
$message = new Message(json_encode([
53+
'event' => 'pusher:subscribe',
54+
'data' => [
55+
'auth' => "{$connection->app->key}:{$hashedAppSecret}",
56+
'channel' => 'private-channel',
57+
],
58+
]));
59+
60+
$this->pusherServer->onMessage($connection, $message);
61+
62+
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
63+
'channel' => 'private-channel',
64+
]);
2465
}
2566
}

tests/HttpApi/FetchChannelReplicationTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ public function replication_it_returns_presence_channel_information()
103103
/** @var JsonResponse $response */
104104
$response = array_pop($connection->sentRawData);
105105

106-
$this->getSubscribeClient()->assertNothingCalled();
106+
$this->getSubscribeClient()
107+
->assertEventDispatched('message');
107108

108109
$this->getPublishClient()
109110
->assertCalled('hset')

0 commit comments

Comments
 (0)