Files
scrum-poker-internal/tests/Feature/RoomSettingsTest.php
2026-09-02 09:37:11 +02:00

159 lines
5.0 KiB
PHP

<?php
use App\Enums\RoomStateChange;
use App\Events\RoomStateChanged;
use App\Jobs\CloseInactiveRooms;
use App\Models\Room;
use App\Models\User;
use Illuminate\Support\Facades\Event;
use Inertia\Testing\AssertableInertia as Assert;
function createSettingsRoom(array $attributes = []): Room
{
return Room::create([
'title' => 'Teamraum',
'deck_config' => [
'name' => 'Fibonacci',
'cards' => [
['key' => '3', 'label' => '3'],
['key' => '5', 'label' => '5'],
],
],
...$attributes,
]);
}
test('room settings default to moderator control and normal retention', function () {
$room = createSettingsRoom();
expect($room->allow_participants_to_manage_rounds)->toBeFalse()
->and($room->is_persistent)->toBeFalse();
});
test('the owner can view and update room settings', function () {
$owner = User::factory()->create();
$room = createSettingsRoom(['owner_id' => $owner->id]);
$this->actingAs($owner)
->get(route('room.settings.edit', $room))
->assertInertia(fn (Assert $page) => $page
->component('rooms/Settings')
->where('room.id', $room->id)
->where('room.allow_participants_to_manage_rounds', false)
->where('room.is_persistent', false));
Event::fake();
$this->actingAs($owner)
->patch(route('room.settings.update', $room), [
'allow_participants_to_manage_rounds' => true,
'is_persistent' => true,
])
->assertRedirect();
$room->refresh();
expect($room->allow_participants_to_manage_rounds)->toBeTrue()
->and($room->is_persistent)->toBeTrue()
->and($room->state_version)->toBe(2);
Event::assertDispatched(
RoomStateChanged::class,
fn (RoomStateChanged $event): bool => $event->change === RoomStateChange::RoomSettingsUpdated
&& $event->state['allow_participants_to_manage_rounds'] === true,
);
});
test('a user who does not own a room cannot manage its settings', function () {
$owner = User::factory()->create();
$otherUser = User::factory()->create();
$room = createSettingsRoom(['owner_id' => $owner->id]);
$this->actingAs($otherUser)
->get(route('room.settings.edit', $room))
->assertForbidden();
$this->actingAs($otherUser)
->patch(route('room.settings.update', $room), [
'allow_participants_to_manage_rounds' => true,
'is_persistent' => true,
])
->assertForbidden();
expect($room->fresh()->allow_participants_to_manage_rounds)->toBeFalse();
});
test('all active participants can manage rounds when the room setting is enabled', function () {
$room = createSettingsRoom(['allow_participants_to_manage_rounds' => true]);
$player = $room->players()->create([
'name' => 'Anna',
'is_moderator' => false,
]);
$this->withSession(["room_players.{$room->id}" => $player->id])
->post(route('room.reveal', $room))
->assertNoContent();
expect($room->fresh()->revealed_at)->not->toBeNull();
});
test('normal participants remain unable to manage rounds when the setting is disabled', function () {
$room = createSettingsRoom();
$player = $room->players()->create([
'name' => 'Anna',
'is_moderator' => false,
]);
$this->withSession(["room_players.{$room->id}" => $player->id])
->post(route('room.reveal', $room))
->assertForbidden();
});
test('persistent rooms are excluded from automatic closing', function () {
$persistentRoom = createSettingsRoom([
'owner_id' => User::factory()->create()->id,
'is_persistent' => true,
'last_activity_at' => now()->subDays(60),
]);
$expiringRoom = createSettingsRoom([
'owner_id' => User::factory()->create()->id,
'last_activity_at' => now()->subDays(60),
]);
(new CloseInactiveRooms)->handle();
expect($persistentRoom->fresh()->closed_at)->toBeNull()
->and($expiringRoom->fresh()->closed_at)->not->toBeNull();
});
test('room settings broadcasts never expose hidden vote values', function () {
$owner = User::factory()->create();
$room = createSettingsRoom(['owner_id' => $owner->id]);
$player = $room->players()->create([
'name' => 'Anna',
'is_moderator' => false,
]);
$player->votes()->create([
'room_id' => $room->id,
'round' => 1,
'value' => '5',
]);
Event::fake();
$this->actingAs($owner)->patch(route('room.settings.update', $room), [
'allow_participants_to_manage_rounds' => true,
'is_persistent' => false,
]);
Event::assertDispatched(
RoomStateChanged::class,
function (RoomStateChanged $event) use ($player): bool {
$broadcastPlayer = collect($event->state['players'])->firstWhere('id', $player->id);
return $broadcastPlayer['has_voted'] === true
&& $broadcastPlayer['vote'] === null;
},
);
});