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

[2.x] Redis connector tests #464

Merged
merged 4 commits into from
Aug 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"cboden/ratchet": "^0.4.1",
"clue/buzz-react": "^2.5",
"clue/redis-react": "^2.3",
"evenement/evenement": "^2.0|^3.0",
"facade/ignition-contracts": "^1.0",
"guzzlehttp/psr7": "^1.5",
"illuminate/broadcasting": "^6.0|^7.0",
Expand Down
141 changes: 137 additions & 4 deletions tests/Channels/ChannelReplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace BeyondCode\LaravelWebSockets\Tests\Channels;

use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\TestCase;

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

public function test_not_implemented()
/** @test */
public function replication_clients_can_subscribe_to_channels()
{
$this->markTestIncomplete(
'Not yet implemented tests.'
);
$connection = $this->getWebSocketConnection();

$message = new Message(json_encode([
'event' => 'pusher:subscribe',
'data' => [
'channel' => 'basic-channel',
],
]));

$this->pusherServer->onOpen($connection);

$this->pusherServer->onMessage($connection, $message);

$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
'channel' => 'basic-channel',
]);
}

/** @test */
public function replication_clients_can_unsubscribe_from_channels()
{
$connection = $this->getConnectedWebSocketConnection(['test-channel']);

$channel = $this->getChannel($connection, 'test-channel');

$this->assertTrue($channel->hasConnections());

$message = new Message(json_encode([
'event' => 'pusher:unsubscribe',
'data' => [
'channel' => 'test-channel',
],
]));

$this->pusherServer->onMessage($connection, $message);

$this->assertFalse($channel->hasConnections());
}

/** @test */
public function replication_a_client_cannot_broadcast_to_other_clients_by_default()
{
// One connection inside channel "test-channel".
$existingConnection = $this->getConnectedWebSocketConnection(['test-channel']);

$connection = $this->getConnectedWebSocketConnection(['test-channel']);

$message = new Message('{"event": "client-test", "data": {}, "channel": "test-channel"}');

$this->pusherServer->onMessage($connection, $message);

$existingConnection->assertNotSentEvent('client-test');
}

/** @test */
public function replication_a_client_can_be_enabled_to_broadcast_to_other_clients()
{
config()->set('websockets.apps.0.enable_client_messages', true);

// One connection inside channel "test-channel".
$existingConnection = $this->getConnectedWebSocketConnection(['test-channel']);

$connection = $this->getConnectedWebSocketConnection(['test-channel']);

$message = new Message('{"event": "client-test", "data": {}, "channel": "test-channel"}');

$this->pusherServer->onMessage($connection, $message);

$existingConnection->assertSentEvent('client-test');
}

/** @test */
public function replication_closed_connections_get_removed_from_all_connected_channels()
{
$connection = $this->getConnectedWebSocketConnection(['test-channel-1', 'test-channel-2']);

$channel1 = $this->getChannel($connection, 'test-channel-1');
$channel2 = $this->getChannel($connection, 'test-channel-2');

$this->assertTrue($channel1->hasConnections());
$this->assertTrue($channel2->hasConnections());

$this->pusherServer->onClose($connection);

$this->assertFalse($channel1->hasConnections());
$this->assertFalse($channel2->hasConnections());
}

/** @test */
public function replication_channels_can_broadcast_messages_to_all_connections()
{
$connection1 = $this->getConnectedWebSocketConnection(['test-channel']);
$connection2 = $this->getConnectedWebSocketConnection(['test-channel']);

$channel = $this->getChannel($connection1, 'test-channel');

$channel->broadcast([
'event' => 'broadcasted-event',
'channel' => 'test-channel',
]);

$connection1->assertSentEvent('broadcasted-event');
$connection2->assertSentEvent('broadcasted-event');
}

/** @test */
public function replication_channels_can_broadcast_messages_to_all_connections_except_the_given_connection()
{
$connection1 = $this->getConnectedWebSocketConnection(['test-channel']);
$connection2 = $this->getConnectedWebSocketConnection(['test-channel']);

$channel = $this->getChannel($connection1, 'test-channel');

$channel->broadcastToOthers($connection1, (object) [
'event' => 'broadcasted-event',
'channel' => 'test-channel',
]);

$connection1->assertNotSentEvent('broadcasted-event');
$connection2->assertSentEvent('broadcasted-event');
}

/** @test */
public function replication_it_responds_correctly_to_the_ping_message()
{
$connection = $this->getConnectedWebSocketConnection();

$message = new Message(json_encode([
'event' => 'pusher:ping',
]));

$this->pusherServer->onMessage($connection, $message);

$connection->assertSentEvent('pusher:pong');
}
}
97 changes: 82 additions & 15 deletions tests/Channels/PresenceChannelReplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,87 @@ public function clients_with_valid_auth_signatures_can_join_presence_channels()
$connection->socketId,
json_encode($channelData),
])
->assertCalledWithArgs('hgetall', [
'1234:presence-channel',
]);
// TODO: This fails somehow
// Debugging shows the exact same pattern as good.
/* ->assertCalledWithArgs('publish', [
'1234:presence-channel',
json_encode([
'event' => 'pusher_internal:member_added',
'channel' => 'presence-channel',
'data' => $channelData,
'appId' => '1234',
'serverId' => $this->app->make(ReplicationInterface::class)->getServerId(),
]),
]) */
->assertCalledWithArgs('hgetall', ['1234:presence-channel'])
->assertCalled('publish');
}

/** @test */
public function clients_with_valid_auth_signatures_can_leave_presence_channels()
{
$connection = $this->getWebSocketConnection();

$this->pusherServer->onOpen($connection);

$channelData = [
'user_id' => 1,
];

$signature = "{$connection->socketId}:presence-channel:".json_encode($channelData);

$message = new Message(json_encode([
'event' => 'pusher:subscribe',
'data' => [
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
'channel' => 'presence-channel',
'channel_data' => json_encode($channelData),
],
]));

$this->pusherServer->onMessage($connection, $message);

$this->getSubscribeClient()
->assertEventDispatched('message');

$this->getPublishClient()
->assertCalled('hset')
->assertCalledWithArgs('hgetall', ['1234:presence-channel'])
->assertCalled('publish');

$this->getPublishClient()
->resetAssertions();

$message = new Message(json_encode([
'event' => 'pusher:unsubscribe',
'data' => [
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
'channel' => 'presence-channel',
],
]));

$this->pusherServer->onMessage($connection, $message);

$this->getPublishClient()
->assertCalled('hdel')
->assertCalled('publish');
}

/** @test */
public function clients_with_no_user_info_can_join_presence_channels()
{
$connection = $this->getWebSocketConnection();

$this->pusherServer->onOpen($connection);

$channelData = [
'user_id' => 1,
];

$signature = "{$connection->socketId}:presence-channel:".json_encode($channelData);

$message = new Message(json_encode([
'event' => 'pusher:subscribe',
'data' => [
'auth' => $connection->app->key.':'.hash_hmac('sha256', $signature, $connection->app->secret),
'channel' => 'presence-channel',
'channel_data' => json_encode($channelData),
],
]));

$this->pusherServer->onMessage($connection, $message);

$this->getPublishClient()
->assertCalled('hset')
->assertcalledWithArgs('hgetall', ['1234:presence-channel'])
->assertCalled('publish');
}
}
49 changes: 45 additions & 4 deletions tests/Channels/PrivateChannelReplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace BeyondCode\LaravelWebSockets\Tests\Channels;

use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;

class PrivateChannelReplicationTest extends TestCase
{
Expand All @@ -16,10 +18,49 @@ public function setUp(): void
$this->runOnlyOnRedisReplication();
}

public function test_not_implemented()
/** @test */
public function replication_clients_need_valid_auth_signatures_to_join_private_channels()
{
$this->markTestIncomplete(
'Not yet implemented tests.'
);
$this->expectException(InvalidSignature::class);

$connection = $this->getWebSocketConnection();

$message = new Message(json_encode([
'event' => 'pusher:subscribe',
'data' => [
'auth' => 'invalid',
'channel' => 'private-channel',
],
]));

$this->pusherServer->onOpen($connection);

$this->pusherServer->onMessage($connection, $message);
}

/** @test */
public function replication_clients_with_valid_auth_signatures_can_join_private_channels()
{
$connection = $this->getWebSocketConnection();

$this->pusherServer->onOpen($connection);

$signature = "{$connection->socketId}:private-channel";

$hashedAppSecret = hash_hmac('sha256', $signature, $connection->app->secret);

$message = new Message(json_encode([
'event' => 'pusher:subscribe',
'data' => [
'auth' => "{$connection->app->key}:{$hashedAppSecret}",
'channel' => 'private-channel',
],
]));

$this->pusherServer->onMessage($connection, $message);

$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
'channel' => 'private-channel',
]);
}
}
3 changes: 2 additions & 1 deletion tests/HttpApi/FetchChannelReplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ public function replication_it_returns_presence_channel_information()
/** @var JsonResponse $response */
$response = array_pop($connection->sentRawData);

$this->getSubscribeClient()->assertNothingCalled();
$this->getSubscribeClient()
->assertEventDispatched('message');

$this->getPublishClient()
->assertCalled('hset')
Expand Down
Loading