Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tidies test suite #31

Merged
merged 10 commits into from
Dec 6, 2023
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
25 changes: 7 additions & 18 deletions tests/ApiGatewayTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,8 @@ protected function defineEnvironment($app)

/**
* Connect to the server.
*
* @param string $connectionId $name
* @param string $appKey
*/
public function connect($connectionId = 'abc-123', $appKey = 'pusher-key'): void
public function connect(string $connectionId = 'abc-123', string $appKey = 'pusher-key'): void
{
resolve(Server::class)
->handle(Request::fromLambdaEvent(
Expand All @@ -94,10 +91,8 @@ public function connect($connectionId = 'abc-123', $appKey = 'pusher-key'): void

/**
* Send a message to the connected client.
*
* @param string $appKey
*/
public function send(array $message, ?string $connectionId = 'abc-123', $appKey = 'pusher-key'): void
public function send(array $message, ?string $connectionId = 'abc-123', string $appKey = 'pusher-key'): void
{
$this->connect($connectionId, $appKey);

Expand All @@ -115,10 +110,8 @@ public function send(array $message, ?string $connectionId = 'abc-123', $appKey

/**
* Subscribe to a channel.
*
* @param string $appKey
*/
public function subscribe(string $channel, ?array $data = [], ?string $auth = null, ?string $connectionId = 'abc-123', $appKey = 'pusher-key'): void
public function subscribe(string $channel, ?array $data = [], ?string $auth = null, ?string $connectionId = 'abc-123', string $appKey = 'pusher-key'): void
{
$data = ! empty($data) ? json_encode($data) : null;

Expand All @@ -140,10 +133,8 @@ public function subscribe(string $channel, ?array $data = [], ?string $auth = nu

/**
* Disconnect a connected client.
*
* @param string $connectionId
*/
public function disconnect($connectionId = 'abc-123'): void
public function disconnect(string $connectionId = 'abc-123'): void
{
resolve(Server::class)
->handle(Request::fromLambdaEvent(
Expand All @@ -158,10 +149,8 @@ public function disconnect($connectionId = 'abc-123'): void

/**
* Assert a message was sent to the given connection.
*
* @return void
*/
public function assertSent(?string $connectionId = null, mixed $message = null, ?int $times = null)
public function assertSent(?string $connectionId = null, mixed $message = null, ?int $times = null): void
{
Bus::assertDispatched(SendToConnection::class, function ($job) use ($connectionId, $message) {
return ($connectionId ? $job->connectionId === $connectionId : true)
Expand All @@ -180,8 +169,8 @@ public function assertSent(?string $connectionId = null, mixed $message = null,
*/
public function managedConnection(): ?Connection
{
$connection = Arr::last(connectionManager()->all());
$connection = Arr::last(connections()->all());

return connectionManager()->find($connection->identifier());
return connections()->find($connection->identifier());
}
}
61 changes: 55 additions & 6 deletions tests/Connection.php → tests/FakeConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,27 @@
use Laravel\Reverb\Contracts\ApplicationProvider;
use Laravel\Reverb\Contracts\Connection as BaseConnection;

class Connection extends BaseConnection
class FakeConnection extends BaseConnection
{
use GeneratesPusherIdentifiers;

/**
* Messages reveived by the connection.
*
* @var array<int, string>
*/
public $messages = [];

public $identifier = '19c1c8e8-351b-4eb5-b6d9-6cbfc54a3446';
/**
* Connection identifier.
*/
public string $identifier = '19c1c8e8-351b-4eb5-b6d9-6cbfc54a3446';

/**
* Connection socket ID.
*
* @var string
*/
public $id;

public function __construct(?string $identifier = null)
Expand All @@ -25,11 +38,17 @@ public function __construct(?string $identifier = null)
}
}

/**
* Get the raw socket connection identifier.
*/
public function identifier(): string
{
return $this->identifier;
}

/**
* Get the normalized socket ID.
*/
public function id(): string
{
if (! $this->id) {
Expand All @@ -39,53 +58,83 @@ public function id(): string
return $this->id;
}

/**
* Get the application the connection belongs to.
*/
public function app(): Application
{
return app()->make(ApplicationProvider::class)->findByKey('pusher-key');
}

/**
* Get the origin of the connection.
*/
public function origin(): string
{
return 'http://localhost';
}

public function setLastSeenAt(int $time): Connection
/**
* Set the connection last seen at timestamp.
*/
public function setLastSeenAt(int $time): FakeConnection
{
$this->lastSeenAt = $time;

return $this;
}

/**
* Set the connection as pinged.
*/
public function setHasBeenPinged(): void
{
$this->hasBeenPinged = true;
}

/**
* Send a message to the connection.
*/
public function send(string $message): void
{
$this->messages[] = $message;
}

/**
* Terminate a connection.
*/
public function terminate(): void
{
//
}

public function assertSent(array $message): void
/**
* Assert the given message was received by the connection.
*/
public function assertReceived(array $message): void
{
Assert::assertContains(json_encode($message), $this->messages);
}

public function assertSendCount(int $count): void
/**
* Assert the connection received the given message count.
*/
public function assertReceivedCount(int $count): void
{
Assert::assertCount($count, $this->messages);
}

public function assertNothingSent(): void
/**
* Assert the connection didn't receive any messages.
*/
public function assertNothingReceived(): void
{
Assert::assertEmpty($this->messages);
}

/**
* Assert the connection has been pinged.
*/
public function assertHasBeenPinged(): void
{
Assert::assertTrue($this->hasBeenPinged);
Expand Down
62 changes: 27 additions & 35 deletions tests/Feature/ApiGateway/ServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Bus;
use Laravel\Reverb\Contracts\ChannelManager;
use Laravel\Reverb\Contracts\ConnectionManager;
use Laravel\Reverb\Jobs\PingInactiveConnections;
use Laravel\Reverb\Jobs\PruneStaleConnections;
use Laravel\Reverb\Servers\ApiGateway\Request;
Expand All @@ -17,28 +15,28 @@
});

afterEach(function () {
channelManager()->flush();
connectionManager()->flush();
channels()->flush();
connections()->flush();
});

it('can handle a new connection', function () {
$this->connect();

$this->assertCount(1, connectionManager()->all());
$this->assertCount(1, connections()->all());
});

it('can handle multiple new connections', function () {
$this->connect();
$this->connect('def-456');

$this->assertCount(2, connectionManager()->all());
$this->assertCount(2, connections()->all());
});

it('can handle connections to different applications', function () {
$this->connect();
$this->connect('def-456', appKey: 'pusher-key-2');

$connections = connectionManager()->all();
$connections = connections()->all();

expect(Arr::first($connections)->identifier())->toBe('abc-123');
expect(Arr::first($connections)->app()->id())->toBe('123456');
Expand All @@ -49,9 +47,9 @@
it('can subscribe to a channel', function () {
$this->subscribe('test-channel');

expect(connectionManager()->all())->toHaveCount(1);
expect(connections()->all())->toHaveCount(1);

expect(channelManager()->find('test-channel')->connections())->toHaveCount(1);
expect(channels()->find('test-channel')->connections())->toHaveCount(1);

$this->assertSent('abc-123', '{"event":"pusher_internal:subscription_succeeded","channel":"test-channel"}');
});
Expand Down Expand Up @@ -97,11 +95,11 @@
$this->subscribe('presence-test-channel', data: $data, connectionId: 'ghi-789');
$this->assertSent('def-456', '{"event":"pusher_internal:member_added","data":{"user_id":3,"user_info":{"name":"Test User 3"}},"channel":"presence-test-channel"}');

expect(connectionManager()->all())->toHaveCount(3);
expect(connections()->all())->toHaveCount(3);

$this->disconnect('ghi-789');

expect(connectionManager()->all())->toHaveCount(2);
expect(connections()->all())->toHaveCount(2);

$this->assertSent(
message: '{"event":"pusher_internal:member_removed","data":{"user_id":3},"channel":"presence-test-channel"}',
Expand Down Expand Up @@ -146,12 +144,12 @@
$this->subscribe('test-channel');
$this->assertSent('abc-123', 'subscription_succeeded', 1);

$connection = Arr::first(connectionManager()->all());
$connection = Arr::first(connections()->all());
$connection->setLastSeenAt(time() - 60 * 10);
connectionManager()->connect($connection);
connections()->connect($connection);

(new PingInactiveConnections)->handle(
channelManager()
channels()
);

$this->assertSent('abc-123', '{"event":"pusher:ping"}', 1);
Expand All @@ -160,21 +158,21 @@
it('it can disconnect inactive subscribers', function () {
$this->subscribe('test-channel');

$connection = Arr::first(connectionManager()->all());
$connection = Arr::first(connections()->all());
$connection->setLastSeenAt(time() - 60 * 10);
connectionManager()->connect($connection);
connections()->connect($connection);

(new PingInactiveConnections)->handle(
channelManager()
channels()
);
$this->assertSent('abc-123', '{"event":"pusher:ping"}');

(new PruneStaleConnections)->handle(
channelManager()
channels()
);

// expect(connectionManager()->all())->toHaveCount(0);
expect(channelManager()->find('test-channel')->connections())->toHaveCount(0);
// expect(connections()->all())->toHaveCount(0);
expect(channels()->find('test-channel')->connections())->toHaveCount(0);

$this->assertSent('abc-123', '{"event":"pusher:error","data":"{\"code\":4201,\"message\":\"Pong reply not received in time\"}"}', 1);
});
Expand Down Expand Up @@ -202,12 +200,12 @@
$this->subscribe('private-test-channel-3', data: ['foo' => 'bar']);
$this->subscribe('presence-test-channel-4', data: ['user_id' => 1, 'user_info' => ['name' => 'Test User 1']]);

expect(connectionManager()->all())->toHaveCount(1);
expect(channelManager()->all())->toHaveCount(4);
expect(connections()->all())->toHaveCount(1);
expect(channels()->all())->toHaveCount(4);

$connection = $this->managedConnection();

collect(channelManager()->all())->each(function ($channel) use ($connection) {
collect(channels()->all())->each(function ($channel) use ($connection) {
expect($channel->connections())->toHaveCount(1);
expect(collect($channel->connections())->map(fn ($conn, $index) => (string) $index))->toContain($connection->identifier());
});
Expand All @@ -223,13 +221,13 @@
$this->subscribe('test-channel', connectionId: 'def-456');
$this->subscribe('private-test-channel-3', connectionId: 'def-456', data: ['foo' => 'bar']);

expect(connectionManager()->all())->toHaveCount(2);
expect(channelManager()->all())->toHaveCount(4);
expect(connections()->all())->toHaveCount(2);
expect(channels()->all())->toHaveCount(4);

expect(channelManager()->find('test-channel')->connections())->toHaveCount(2);
expect(channelManager()->find('test-channel-2')->connections())->toHaveCount(1);
expect(channelManager()->find('private-test-channel-3')->connections())->toHaveCount(2);
expect(channelManager()->find('presence-test-channel-4')->connections())->toHaveCount(1);
expect(channels()->find('test-channel')->connections())->toHaveCount(2);
expect(channels()->find('test-channel-2')->connections())->toHaveCount(1);
expect(channels()->find('private-test-channel-3')->connections())->toHaveCount(2);
expect(channels()->find('presence-test-channel-4')->connections())->toHaveCount(1);
});

it('fails to subscribe to a private channel with invalid auth signature', function () {
Expand Down Expand Up @@ -301,9 +299,3 @@

$this->assertSent('abc-123', 'connection_established', 1);
});

it('clears application state between requests', function () {
$this->subscribe('test-channel');

expect($this->app->make(ChannelManager::class)->app())->toBeNull();
})->todo();
Loading