'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('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); });