Files
scrum-poker-internal/tests/Feature/RoomEmoteTest.php
T
Twyco d2042fb95b
CI/CD / test_and_check_app (push) Successful in 3m39s
CI/CD / Publish immutable image (push) Skipped
removed throttle for mod
2026-09-03 13:21:46 +02:00

154 lines
4.9 KiB
PHP

<?php
use App\Events\PaperBallThrown;
use App\Models\Room;
use Illuminate\Support\Facades\Event;
function createEmoteRoom(array $attributes = []): Room
{
return Room::create([
'title' => 'Playful Planning',
'deck_config' => [
'name' => 'Fibonacci',
'cards' => [
['key' => '3', 'label' => '3'],
['key' => '5', 'label' => '5'],
],
],
...$attributes,
]);
}
test('a participant can throw a realtime paper ball at another player', function () {
Event::fake([PaperBallThrown::class]);
$room = createEmoteRoom(['last_activity_at' => now()->subDay()]);
$sender = $room->players()->create([
'name' => 'Eric',
'is_moderator' => true,
]);
$target = $room->players()->create([
'name' => 'Anna',
'is_moderator' => false,
]);
$room->refresh();
$activity = $room->last_activity_at;
$stateVersion = $room->state_version;
$this->withSession(["room_players.{$room->id}" => $sender->id])
->postJson(route('room.emote.paper-ball.store', $room), [
'target_player_id' => $target->id,
])
->assertNoContent();
Event::assertDispatched(PaperBallThrown::class, function (PaperBallThrown $event) use ($room, $sender, $target): bool {
return $event->roomId === $room->id
&& $event->fromPlayerId === $sender->id
&& $event->targetPlayerId === $target->id
&& $event->broadcastOn()->name === "rooms.{$room->id}"
&& $event->broadcastAs() === 'room.emote.thrown'
&& array_keys($event->broadcastWith()) === [
'id',
'from_player_id',
'target_player_id',
];
});
$room->refresh();
expect($room->last_activity_at->equalTo($activity))->toBeTrue()
->and($room->state_version)->toBe($stateVersion);
});
test('moderator paper ball throws are not rate limited', function () {
Event::fake([PaperBallThrown::class]);
$room = createEmoteRoom();
$moderator = $room->players()->create([
'name' => 'Eric',
'is_moderator' => true,
]);
$target = $room->players()->create([
'name' => 'Anna',
'is_moderator' => false,
]);
for ($throwCount = 0; $throwCount < 11; $throwCount++) {
$this->withSession(["room_players.{$room->id}" => $moderator->id])
->postJson(route('room.emote.paper-ball.store', $room), [
'target_player_id' => $target->id,
])
->assertNoContent();
}
Event::assertDispatchedTimes(PaperBallThrown::class, 11);
});
test('participant paper ball throws remain rate limited', function () {
Event::fake([PaperBallThrown::class]);
$room = createEmoteRoom();
$moderator = $room->players()->create([
'name' => 'Eric',
'is_moderator' => true,
]);
$participant = $room->players()->create([
'name' => 'Anna',
'is_moderator' => false,
]);
for ($throwCount = 0; $throwCount < 10; $throwCount++) {
$this->withSession(["room_players.{$room->id}" => $participant->id])
->postJson(route('room.emote.paper-ball.store', $room), [
'target_player_id' => $moderator->id,
])
->assertNoContent();
}
$this->withSession(["room_players.{$room->id}" => $participant->id])
->postJson(route('room.emote.paper-ball.store', $room), [
'target_player_id' => $moderator->id,
])
->assertTooManyRequests();
Event::assertDispatchedTimes(PaperBallThrown::class, 10);
});
test('a participant cannot throw a paper ball at themselves', function () {
Event::fake([PaperBallThrown::class]);
$room = createEmoteRoom();
$player = $room->players()->create([
'name' => 'Eric',
'is_moderator' => true,
]);
$this->withSession(["room_players.{$room->id}" => $player->id])
->postJson(route('room.emote.paper-ball.store', $room), [
'target_player_id' => $player->id,
])
->assertUnprocessable()
->assertJsonValidationErrors('target_player_id');
Event::assertNotDispatched(PaperBallThrown::class);
});
test('a participant cannot target a player from another room', function () {
Event::fake([PaperBallThrown::class]);
$room = createEmoteRoom();
$sender = $room->players()->create([
'name' => 'Eric',
'is_moderator' => true,
]);
$otherRoom = createEmoteRoom();
$otherPlayer = $otherRoom->players()->create([
'name' => 'Nina',
'is_moderator' => true,
]);
$this->withSession(["room_players.{$room->id}" => $sender->id])
->postJson(route('room.emote.paper-ball.store', $room), [
'target_player_id' => $otherPlayer->id,
])
->assertUnprocessable()
->assertJsonValidationErrors('target_player_id');
Event::assertNotDispatched(PaperBallThrown::class);
});